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

#include <lac/petsc_matrix_base.h>
#include <lac/petsc_full_matrix.h>
#include <lac/petsc_sparse_matrix.h>
#include <lac/petsc_parallel_sparse_matrix.h>
#include <lac/petsc_vector.h>

#ifdef DEAL_II_USE_PETSC

namespace PETScWrappers
{
  namespace MatrixIterators
  {
    void
    MatrixBase::const_iterator::Accessor::
    visit_present_row ()
    {
                                       // if we are asked to visit the
                                       // past-the-end line, then simply
                                       // release all our caches and go on
                                       // with life
      if (this->a_row == matrix->m())
        {
          colnum_cache.reset ();
          value_cache.reset ();

          return;
        }

                                       // otherwise first flush PETSc caches
      matrix->compress ();

                                       // get a representation of the present
                                       // row
      int          ncols;
      int         *colnums;
      PetscScalar *values;

      int ierr;
      ierr = MatGetRow(*matrix, this->a_row, &ncols, &colnums, &values);
      AssertThrow (ierr == 0, MatrixBase::ExcPETScError(ierr));

                                       // copy it into our caches
      colnum_cache.reset (new std::vector<unsigned int> (colnums,
                                                         colnums+ncols));
      value_cache.reset (new std::vector<PetscScalar> (values, values+ncols));

                                       // and finally restore the matrix
      ierr = MatRestoreRow(*matrix, this->a_row, &ncols, &colnums, &values);
      AssertThrow (ierr == 0, MatrixBase::ExcPETScError(ierr));
    }
  }

  MatrixBase::MatrixBase ()
                  :
                  last_action (LastAction::none)
  {}

  MatrixBase::~MatrixBase ()
  {
    const int ierr = MatDestroy (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::clear ()
  {
                                     // destroy the matrix...
    int ierr = MatDestroy (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
                                     // ...and replace it by an empty
                                     // sequential matrix
    const int m=0, n=0, n_nonzero_per_row=0;
    ierr = MatCreateSeqAIJ(PETSC_COMM_SELF, m, n, n_nonzero_per_row,
                           0, &matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  MatrixBase &
  MatrixBase::operator = (const double d)
  {
    Assert (d==0, ExcScalarAssignmentOnlyForZeroValue());

    const int ierr = MatZeroEntries (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return *this;
  }

  void
  MatrixBase::set (const unsigned int i,
                   const unsigned int j,
                   const PetscScalar value)
  {
    if (last_action != LastAction::insert)
      {
        int ierr;
        ierr = MatAssemblyBegin(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));

        ierr = MatAssemblyEnd(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));
      }

    const signed int petsc_i = i;
    const signed int petsc_j = j;

    const int ierr
      = MatSetValues (matrix, 1, &petsc_i, 1, &petsc_j,
                      &value, INSERT_VALUES);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    last_action = LastAction::insert;
  }

  void
  MatrixBase::add (const unsigned int i,
                   const unsigned int j,
                   const PetscScalar value)
  {
    if (last_action != LastAction::add)
      {
        int ierr;
        ierr = MatAssemblyBegin(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));

        ierr = MatAssemblyEnd(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));
      }

    const signed int petsc_i = i;
    const signed int petsc_j = j;

    const int ierr
      = MatSetValues (matrix, 1, &petsc_i, 1, &petsc_j,
                      &value, ADD_VALUES);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    last_action = LastAction::add;
  }

  PetscScalar
  MatrixBase::el (const unsigned int i,
                  const unsigned int j) const
  {
    const signed int petsc_i = i;
    const signed int petsc_j = j;
    PetscScalar value;

    const int ierr
      = MatGetValues (matrix, 1, &petsc_i, 1, &petsc_j,
                      &value);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return value;
  }

  PetscScalar
  MatrixBase::diag_element (const unsigned int i) const
  {
    Assert (m() == n(), ExcMatrixNotSquare());

                                     // this doesn't seem to work any
                                     // different than any other element
    return el(i,i);
  }

  void
  MatrixBase::compress ()
  {
                                     // flush buffers
    int ierr;
    ierr = MatAssemblyBegin (matrix,MAT_FINAL_ASSEMBLY);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    ierr = MatAssemblyEnd (matrix,MAT_FINAL_ASSEMBLY);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

                                     // try to compress the representation
    ierr = MatCompress (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  unsigned int
  MatrixBase::m () const
  {
    int n_rows, n_cols;
    int ierr = MatGetSize (matrix, &n_rows, &n_cols);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return n_rows;
  }

  unsigned int
  MatrixBase::n () const
  {
    int n_rows, n_cols;
    int ierr = MatGetSize (matrix, &n_rows, &n_cols);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return n_cols;
  }

  unsigned int
  MatrixBase::n_nonzero_elements () const
  {
    MatInfo mat_info;
    const int ierr
      = MatGetInfo (matrix, MAT_GLOBAL_SUM, &mat_info);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return static_cast<unsigned int>(mat_info.nz_used);
  }

  PetscReal
  MatrixBase::l1_norm () const
  {
    PetscReal result;

    const int ierr
      = MatNorm (matrix, NORM_1, &result);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return result;
  }

  PetscReal
  MatrixBase::linfty_norm () const
  {
    PetscReal result;

    const int ierr
      = MatNorm (matrix, NORM_INFINITY, &result);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return result;
  }

  PetscReal
  MatrixBase::frobenius_norm () const
  {
    PetscReal result;

    const int ierr
      = MatNorm (matrix, NORM_FROBENIUS, &result);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return result;
  }

  MatrixBase &
  MatrixBase::operator *= (const PetscScalar a)
  {
    const int ierr
      = MatScale (&a, matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return *this;
  }

  MatrixBase &
  MatrixBase::operator /= (const PetscScalar a)
  {
    const PetscScalar factor = 1./a;

    const int ierr
      = MatScale (&factor, matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return *this;
  }

  void
  MatrixBase::vmult (VectorBase       &dst,
                     const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMult (matrix, src, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::Tvmult (VectorBase       &dst,
                      const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMultTranspose (matrix, src, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::vmult_add (VectorBase       &dst,
                         const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMultAdd (matrix, src, dst, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::Tvmult_add (VectorBase       &dst,
                          const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMultTransposeAdd (matrix, src, dst, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  PetscScalar
  MatrixBase::matrix_norm_square (const VectorBase &v) const
  {
    Vector tmp(v.size());
    vmult (tmp, v);
    return tmp*v;
  }

  PetscScalar
  MatrixBase::matrix_scalar_product (const VectorBase &u,
                                     const VectorBase &v) const
  {
    Vector tmp(v.size());
    vmult (tmp, v);
    return u*tmp;
  }

  double
  MatrixBase::residual (VectorBase       &dst,
                        const VectorBase &x,
                        const VectorBase &b) const
  {
                                     // avoid the use of a temporary, and
                                     // rather do one negation pass more than
                                     // necessary
    vmult (dst, x);
    dst -= b;
    dst *= -1;

    return dst.l2_norm();
  }

  MatrixBase::operator const Mat () const
  {
    return matrix;
  }
}

#else
// On gcc2.95 on Alpha OSF1, the native assembler does not like empty
// files, so provide some dummy code
namespace { void dummy () {} }
#endif // DEAL_II_USE_PETSC
<commit_msg>In operator = function we need to compress before we call MatZeroEntries.<commit_after>//---------------------------------------------------------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2004 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//---------------------------------------------------------------------------

#include <lac/petsc_matrix_base.h>
#include <lac/petsc_full_matrix.h>
#include <lac/petsc_sparse_matrix.h>
#include <lac/petsc_parallel_sparse_matrix.h>
#include <lac/petsc_vector.h>

#ifdef DEAL_II_USE_PETSC

namespace PETScWrappers
{
  namespace MatrixIterators
  {
    void
    MatrixBase::const_iterator::Accessor::
    visit_present_row ()
    {
                                       // if we are asked to visit the
                                       // past-the-end line, then simply
                                       // release all our caches and go on
                                       // with life
      if (this->a_row == matrix->m())
        {
          colnum_cache.reset ();
          value_cache.reset ();

          return;
        }

                                       // otherwise first flush PETSc caches
      matrix->compress ();

                                       // get a representation of the present
                                       // row
      int          ncols;
      int         *colnums;
      PetscScalar *values;

      int ierr;
      ierr = MatGetRow(*matrix, this->a_row, &ncols, &colnums, &values);
      AssertThrow (ierr == 0, MatrixBase::ExcPETScError(ierr));

                                       // copy it into our caches
      colnum_cache.reset (new std::vector<unsigned int> (colnums,
                                                         colnums+ncols));
      value_cache.reset (new std::vector<PetscScalar> (values, values+ncols));

                                       // and finally restore the matrix
      ierr = MatRestoreRow(*matrix, this->a_row, &ncols, &colnums, &values);
      AssertThrow (ierr == 0, MatrixBase::ExcPETScError(ierr));
    }
  }

  MatrixBase::MatrixBase ()
                  :
                  last_action (LastAction::none)
  {}

  MatrixBase::~MatrixBase ()
  {
    const int ierr = MatDestroy (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::clear ()
  {
                                     // destroy the matrix...
    int ierr = MatDestroy (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
                                     // ...and replace it by an empty
                                     // sequential matrix
    const int m=0, n=0, n_nonzero_per_row=0;
    ierr = MatCreateSeqAIJ(PETSC_COMM_SELF, m, n, n_nonzero_per_row,
                           0, &matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  MatrixBase &
  MatrixBase::operator = (const double d)
  {
    Assert (d==0, ExcScalarAssignmentOnlyForZeroValue());
				     // first flush the buffers as
				     // this is not done by
				     // MatZeroEntries
    compress();

    const int ierr = MatZeroEntries (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return *this;
  }

  void
  MatrixBase::set (const unsigned int i,
                   const unsigned int j,
                   const PetscScalar value)
  {
    if (last_action != LastAction::insert)
      {
        int ierr;
        ierr = MatAssemblyBegin(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));

        ierr = MatAssemblyEnd(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));
      }

    const signed int petsc_i = i;
    const signed int petsc_j = j;

    const int ierr
      = MatSetValues (matrix, 1, &petsc_i, 1, &petsc_j,
                      &value, INSERT_VALUES);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    last_action = LastAction::insert;
  }

  void
  MatrixBase::add (const unsigned int i,
                   const unsigned int j,
                   const PetscScalar value)
  {
    if (last_action != LastAction::add)
      {
        int ierr;
        ierr = MatAssemblyBegin(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));

        ierr = MatAssemblyEnd(matrix,MAT_FLUSH_ASSEMBLY);
        AssertThrow (ierr == 0, ExcPETScError(ierr));
      }

    const signed int petsc_i = i;
    const signed int petsc_j = j;

    const int ierr
      = MatSetValues (matrix, 1, &petsc_i, 1, &petsc_j,
                      &value, ADD_VALUES);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    last_action = LastAction::add;
  }

  PetscScalar
  MatrixBase::el (const unsigned int i,
                  const unsigned int j) const
  {
    const signed int petsc_i = i;
    const signed int petsc_j = j;
    PetscScalar value;

    const int ierr
      = MatGetValues (matrix, 1, &petsc_i, 1, &petsc_j,
                      &value);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return value;
  }

  PetscScalar
  MatrixBase::diag_element (const unsigned int i) const
  {
    Assert (m() == n(), ExcMatrixNotSquare());

                                     // this doesn't seem to work any
                                     // different than any other element
    return el(i,i);
  }

  void
  MatrixBase::compress ()
  {
                                     // flush buffers
    int ierr;
    ierr = MatAssemblyBegin (matrix,MAT_FINAL_ASSEMBLY);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    ierr = MatAssemblyEnd (matrix,MAT_FINAL_ASSEMBLY);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

                                     // try to compress the representation
    ierr = MatCompress (matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  unsigned int
  MatrixBase::m () const
  {
    int n_rows, n_cols;
    int ierr = MatGetSize (matrix, &n_rows, &n_cols);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return n_rows;
  }

  unsigned int
  MatrixBase::n () const
  {
    int n_rows, n_cols;
    int ierr = MatGetSize (matrix, &n_rows, &n_cols);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return n_cols;
  }

  unsigned int
  MatrixBase::n_nonzero_elements () const
  {
    MatInfo mat_info;
    const int ierr
      = MatGetInfo (matrix, MAT_GLOBAL_SUM, &mat_info);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return static_cast<unsigned int>(mat_info.nz_used);
  }

  PetscReal
  MatrixBase::l1_norm () const
  {
    PetscReal result;

    const int ierr
      = MatNorm (matrix, NORM_1, &result);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return result;
  }

  PetscReal
  MatrixBase::linfty_norm () const
  {
    PetscReal result;

    const int ierr
      = MatNorm (matrix, NORM_INFINITY, &result);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return result;
  }

  PetscReal
  MatrixBase::frobenius_norm () const
  {
    PetscReal result;

    const int ierr
      = MatNorm (matrix, NORM_FROBENIUS, &result);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return result;
  }

  MatrixBase &
  MatrixBase::operator *= (const PetscScalar a)
  {
    const int ierr
      = MatScale (&a, matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return *this;
  }

  MatrixBase &
  MatrixBase::operator /= (const PetscScalar a)
  {
    const PetscScalar factor = 1./a;

    const int ierr
      = MatScale (&factor, matrix);
    AssertThrow (ierr == 0, ExcPETScError(ierr));

    return *this;
  }

  void
  MatrixBase::vmult (VectorBase       &dst,
                     const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMult (matrix, src, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::Tvmult (VectorBase       &dst,
                      const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMultTranspose (matrix, src, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::vmult_add (VectorBase       &dst,
                         const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMultAdd (matrix, src, dst, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  void
  MatrixBase::Tvmult_add (VectorBase       &dst,
                          const VectorBase &src) const
  {
    Assert (&src != &dst, ExcSourceEqualsDestination());

    const int ierr = MatMultTransposeAdd (matrix, src, dst, dst);
    AssertThrow (ierr == 0, ExcPETScError(ierr));
  }

  PetscScalar
  MatrixBase::matrix_norm_square (const VectorBase &v) const
  {
    Vector tmp(v.size());
    vmult (tmp, v);
    return tmp*v;
  }

  PetscScalar
  MatrixBase::matrix_scalar_product (const VectorBase &u,
                                     const VectorBase &v) const
  {
    Vector tmp(v.size());
    vmult (tmp, v);
    return u*tmp;
  }

  double
  MatrixBase::residual (VectorBase       &dst,
                        const VectorBase &x,
                        const VectorBase &b) const
  {
                                     // avoid the use of a temporary, and
                                     // rather do one negation pass more than
                                     // necessary
    vmult (dst, x);
    dst -= b;
    dst *= -1;

    return dst.l2_norm();
  }

  MatrixBase::operator const Mat () const
  {
    return matrix;
  }
}

#else
// On gcc2.95 on Alpha OSF1, the native assembler does not like empty
// files, so provide some dummy code
namespace { void dummy () {} }
#endif // DEAL_II_USE_PETSC
<|endoftext|>


<commit_before>/// @file
/// @version 3.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#define _CUSTOM_WINDOW
#define _CUSTOM_RENDER_SYSTEM

#include <april/april.h>
#include <april/Cursor.h>
#include <april/main.h>
#include <april/MouseDelegate.h>
#include <april/Platform.h>
#include <april/RenderSystem.h>
#include <april/SystemDelegate.h>
#include <april/UpdateDelegate.h>
#include <april/Window.h>
#include <gtypes/Rectangle.h>
#include <gtypes/Vector2.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hstring.h>

#include "CustomRenderSystem.h"
#include "CustomWindow.h"

#define RESOURCE_PATH "../../demos/media/"

static april::Texture* texture = NULL;
static grect drawRect(0.0f, 0.0f, 800.0f, 600.0f);
static gvec2 offset = drawRect.getSize() * 0.5f;
static grect textureRect;
static bool mousePressed = false;

class UpdateDelegate : public april::UpdateDelegate
{
	bool onUpdate(float timeSinceLastFrame)
	{
		april::rendersys->clear();
		april::rendersys->setOrthoProjection(drawRect);
		april::rendersys->drawFilledRect(drawRect, april::Color(64, 64, 64));
		april::rendersys->setTexture(texture);
		april::rendersys->drawTexturedRect(textureRect + offset, grect(0.0f, 0.0f, 1.0f, 1.0f));
		april::rendersys->drawFilledRect(grect(0.0f, 0.0f, 100.0f, 75.0f), april::Color::Orange);
		april::rendersys->drawFilledRect(grect(10.0f, 10.0f, 80.0f, 55.0f), april::Color::Yellow);
		return true;
	}

} updateDelegate;

class SystemDelegate : public april::SystemDelegate
{
public:
	SystemDelegate() : april::SystemDelegate()
	{
	}

} systemDelegate;

class MouseDelegate : public april::MouseDelegate
{
	void onMouseDown(april::Key key)
	{
		offset = april::window->getCursorPosition();
		mousePressed = true;
	}

	void onMouseUp(april::Key key)
	{
		mousePressed = false;
	}

	void onMouseMove()
	{
		if (mousePressed)
		{
			offset = april::window->getCursorPosition();
		}
	}

} mouseDelegate;

void april_init(const harray<hstr>& args)
{
	srand(get_system_time());
#if defined(_CUSTOM_WINDOW) && defined(_CUSTOM_RENDER_SYSTEM)
	april::init(new CustomRenderSystem(), new CustomWindow());
#elif defined(_CUSTOM_WINDOW)
	april::init(april::RS_DEFAULT, new CustomWindow());
#elif defined(_CUSTOM_RENDER_SYSTEM)
	april::init(new CustomRenderSystem(), april::WS_DEFAULT);
#else
	april::init(april::RS_DEFAULT, april::WS_DEFAULT);
#endif
	april::createRenderSystem();
	april::createWindow((int)drawRect.w, (int)drawRect.h, false, "APRIL: Simple Interface");
	april::window->setUpdateDelegate(&updateDelegate);
	april::window->setSystemDelegate(&systemDelegate);
	april::window->setMouseDelegate(&mouseDelegate);
	texture = april::rendersys->createTextureFromResource(RESOURCE_PATH "jpt_final", april::Texture::TYPE_MANAGED);
	textureRect.setSize(texture->getWidth() * 0.5f, texture->getHeight() * 0.5f);
	textureRect.x = -textureRect.w / 2;
	textureRect.y = -textureRect.h / 2;
}

void april_destroy()
{
	delete texture;
	april::destroy();
}
<commit_msg>- small fix<commit_after>/// @file
/// @version 3.5
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://opensource.org/licenses/BSD-3-Clause

#include <april/april.h>
#include <april/Cursor.h>
#include <april/main.h>
#include <april/MouseDelegate.h>
#include <april/Platform.h>
#include <april/RenderSystem.h>
#include <april/SystemDelegate.h>
#include <april/UpdateDelegate.h>
#include <april/Window.h>
#include <gtypes/Rectangle.h>
#include <gtypes/Vector2.h>
#include <hltypes/hlog.h>
#include <hltypes/hltypesUtil.h>
#include <hltypes/hstring.h>

#include "CustomRenderSystem.h"
#include "CustomWindow.h"

#define RESOURCE_PATH "../../demos/media/"

static april::Texture* texture = NULL;
static grect drawRect(0.0f, 0.0f, 800.0f, 600.0f);
static gvec2 offset = drawRect.getSize() * 0.5f;
static grect textureRect;
static bool mousePressed = false;

class UpdateDelegate : public april::UpdateDelegate
{
	bool onUpdate(float timeSinceLastFrame)
	{
		april::rendersys->clear();
		april::rendersys->setOrthoProjection(drawRect);
		april::rendersys->drawFilledRect(drawRect, april::Color(64, 64, 64));
		april::rendersys->setTexture(texture);
		april::rendersys->drawTexturedRect(textureRect + offset, grect(0.0f, 0.0f, 1.0f, 1.0f));
		april::rendersys->drawFilledRect(grect(0.0f, 0.0f, 100.0f, 75.0f), april::Color::Orange);
		april::rendersys->drawFilledRect(grect(10.0f, 10.0f, 80.0f, 55.0f), april::Color::Yellow);
		return true;
	}

} updateDelegate;

class SystemDelegate : public april::SystemDelegate
{
public:
	SystemDelegate() : april::SystemDelegate()
	{
	}

} systemDelegate;

class MouseDelegate : public april::MouseDelegate
{
	void onMouseDown(april::Key key)
	{
		offset = april::window->getCursorPosition();
		mousePressed = true;
	}

	void onMouseUp(april::Key key)
	{
		mousePressed = false;
	}

	void onMouseMove()
	{
		if (mousePressed)
		{
			offset = april::window->getCursorPosition();
		}
	}

} mouseDelegate;

void april_init(const harray<hstr>& args)
{
	srand(get_system_time());
	april::init(new CustomRenderSystem(), new CustomWindow());
	april::createRenderSystem();
	april::createWindow((int)drawRect.w, (int)drawRect.h, false, "APRIL: Simple Interface");
	april::window->setUpdateDelegate(&updateDelegate);
	april::window->setSystemDelegate(&systemDelegate);
	april::window->setMouseDelegate(&mouseDelegate);
	texture = april::rendersys->createTextureFromResource(RESOURCE_PATH "jpt_final", april::Texture::TYPE_MANAGED);
	textureRect.setSize(texture->getWidth() * 0.5f, texture->getHeight() * 0.5f);
	textureRect.x = -textureRect.w / 2;
	textureRect.y = -textureRect.h / 2;
}

void april_destroy()
{
	delete texture;
	april::destroy();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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.
 */

#include <thrift/lib/cpp2/protocol/CompactProtocol.h>

#include <thrift/lib/cpp2/test/gen-cpp2/CompactProtocolBenchData_types.h>

#include <iostream>
#include <vector>

#include <fmt/core.h>
#include <folly/Benchmark.h>
#include <folly/Optional.h>
#include <folly/portability/GFlags.h>
#include <glog/logging.h>
#include <thrift/lib/cpp2/protocol/Serializer.h>

using namespace std;
using namespace folly;
using namespace apache::thrift;
using namespace ::cpp2;

const size_t kMultExp = 0;

Shallow makeShallow() {
  Shallow data;
  data.one = 750ll;
  data.two = 750ll << 22;
  return data;
}

Deep makeDeep(size_t triplesz) {
  Deep data;
  for (size_t i = 0; i < triplesz; ++i) {
    Deep1 data1;
    for (size_t j = 0; j < triplesz; ++j) {
      Deep2 data2;
      for (size_t k = 0; k < triplesz; ++k) {
        data2.datas.push_back(fmt::format("omg[{}, {}, {}]", i, j, k));
      }
      data1.deeps.push_back(move(data2));
    }
    data.deeps.push_back(move(data1));
  }
  return data;
}

BENCHMARK(CompactProtocolReader_ctor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolReader>> protos(iters);
  braces.dismiss();
  while (iters--) {
    protos[iters].emplace();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_dtor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolReader>> protos(iters);
  for (auto& proto : protos) {
    proto.emplace();
  }
  braces.dismiss();
  while (iters--) {
    protos[iters].clear();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_ctor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolWriter>> protos(iters);
  braces.dismiss();
  while (iters--) {
    protos[iters].emplace();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_dtor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolWriter>> protos(iters);
  for (auto& proto : protos) {
    proto.emplace();
  }
  braces.dismiss();
  while (iters--) {
    protos[iters].clear();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_deserialize_empty, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Empty data;
  CompactSerializer ser;
  IOBufQueue bufq;
  ser.serialize(data, &bufq);
  auto buf = bufq.move();
  braces.dismiss();
  while (iters--) {
    CompactSerializer s;
    Empty empty;
    s.deserialize(buf.get(), empty);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_serialize_empty, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Empty data;
  braces.dismiss();
  while (iters--) {
    CompactSerializer ser;
    IOBufQueue bufq;
    ser.serialize(data, &bufq);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_deserialize_shallow, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Shallow data = makeShallow();
  CompactSerializer ser;
  IOBufQueue bufq;
  ser.serialize(data, &bufq);
  auto buf = bufq.move();
  braces.dismiss();
  while (iters--) {
    CompactSerializer s;
    Deep data;
    s.deserialize(buf.get(), data);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_serialize_shallow, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Shallow data = makeShallow();
  braces.dismiss();
  while (iters--) {
    CompactSerializer ser;
    IOBufQueue bufq;
    ser.serialize(data, &bufq);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_deserialize_deep, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Deep data = makeDeep(16);
  CompactSerializer ser;
  IOBufQueue bufq;
  ser.serialize(data, &bufq);
  auto buf = bufq.move();
  braces.dismiss();
  while (iters--) {
    CompactSerializer s;
    Deep deep;
    s.deserialize(buf.get(), deep);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_serialize_deep, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Deep data = makeDeep(16);
  braces.dismiss();
  while (iters--) {
    CompactSerializer ser;
    IOBufQueue bufq;
    ser.serialize(data, &bufq);
  }
  braces.rehire();
}

int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);
  runBenchmarks();
  return 0;
}
<commit_msg>replace more folly::Optional::clear by reset (3)<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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.
 */

#include <thrift/lib/cpp2/protocol/CompactProtocol.h>

#include <thrift/lib/cpp2/test/gen-cpp2/CompactProtocolBenchData_types.h>

#include <iostream>
#include <vector>

#include <fmt/core.h>
#include <folly/Benchmark.h>
#include <folly/Optional.h>
#include <folly/portability/GFlags.h>
#include <glog/logging.h>
#include <thrift/lib/cpp2/protocol/Serializer.h>

using namespace std;
using namespace folly;
using namespace apache::thrift;
using namespace ::cpp2;

const size_t kMultExp = 0;

Shallow makeShallow() {
  Shallow data;
  data.one = 750ll;
  data.two = 750ll << 22;
  return data;
}

Deep makeDeep(size_t triplesz) {
  Deep data;
  for (size_t i = 0; i < triplesz; ++i) {
    Deep1 data1;
    for (size_t j = 0; j < triplesz; ++j) {
      Deep2 data2;
      for (size_t k = 0; k < triplesz; ++k) {
        data2.datas.push_back(fmt::format("omg[{}, {}, {}]", i, j, k));
      }
      data1.deeps.push_back(move(data2));
    }
    data.deeps.push_back(move(data1));
  }
  return data;
}

BENCHMARK(CompactProtocolReader_ctor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolReader>> protos(iters);
  braces.dismiss();
  while (iters--) {
    protos[iters].emplace();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_dtor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolReader>> protos(iters);
  for (auto& proto : protos) {
    proto.emplace();
  }
  braces.dismiss();
  while (iters--) {
    protos[iters].reset();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_ctor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolWriter>> protos(iters);
  braces.dismiss();
  while (iters--) {
    protos[iters].emplace();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_dtor, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  vector<Optional<CompactProtocolWriter>> protos(iters);
  for (auto& proto : protos) {
    proto.emplace();
  }
  braces.dismiss();
  while (iters--) {
    protos[iters].reset();
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_deserialize_empty, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Empty data;
  CompactSerializer ser;
  IOBufQueue bufq;
  ser.serialize(data, &bufq);
  auto buf = bufq.move();
  braces.dismiss();
  while (iters--) {
    CompactSerializer s;
    Empty empty;
    s.deserialize(buf.get(), empty);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_serialize_empty, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Empty data;
  braces.dismiss();
  while (iters--) {
    CompactSerializer ser;
    IOBufQueue bufq;
    ser.serialize(data, &bufq);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_deserialize_shallow, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Shallow data = makeShallow();
  CompactSerializer ser;
  IOBufQueue bufq;
  ser.serialize(data, &bufq);
  auto buf = bufq.move();
  braces.dismiss();
  while (iters--) {
    CompactSerializer s;
    Deep data;
    s.deserialize(buf.get(), data);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_serialize_shallow, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Shallow data = makeShallow();
  braces.dismiss();
  while (iters--) {
    CompactSerializer ser;
    IOBufQueue bufq;
    ser.serialize(data, &bufq);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolReader_deserialize_deep, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Deep data = makeDeep(16);
  CompactSerializer ser;
  IOBufQueue bufq;
  ser.serialize(data, &bufq);
  auto buf = bufq.move();
  braces.dismiss();
  while (iters--) {
    CompactSerializer s;
    Deep deep;
    s.deserialize(buf.get(), deep);
  }
  braces.rehire();
}

BENCHMARK(CompactProtocolWriter_serialize_deep, kiters) {
  BenchmarkSuspender braces;
  size_t iters = kiters << kMultExp;
  Deep data = makeDeep(16);
  braces.dismiss();
  while (iters--) {
    CompactSerializer ser;
    IOBufQueue bufq;
    ser.serialize(data, &bufq);
  }
  braces.rehire();
}

int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);
  runBenchmarks();
  return 0;
}
<|endoftext|>


<commit_before>//===-- iSwitch.cpp - Implement the Switch instruction -----------*- C++ -*--=//
//
// This file implements the Switch instruction...
//
//===----------------------------------------------------------------------===//

#include "llvm/iTerminators.h"
#include "llvm/BasicBlock.h"
#ifndef NDEBUG
#include "llvm/Type.h"
#endif

SwitchInst::SwitchInst(Value *V, BasicBlock *DefDest)
  : TerminatorInst(Instruction::Switch) {
  assert(V && DefDest);
  Operands.push_back(Use(V, this));
  Operands.push_back(Use(DefDest, this));
}

SwitchInst::SwitchInst(const SwitchInst &SI)
  : TerminatorInst(Instruction::Switch) {
  Operands.reserve(SI.Operands.size());

  for (unsigned i = 0, E = SI.Operands.size(); i != E; i+=2) {
    Operands.push_back(Use(SI.Operands[i], this));
    Operands.push_back(Use(SI.Operands[i+1], this));
  }
}

void SwitchInst::dest_push_back(Constant *OnVal, BasicBlock *Dest) {
  Operands.push_back(Use(OnVal, this));
  Operands.push_back(Use(Dest, this));
}
<commit_msg>Add a couple of extra casts to avoid extra #include<commit_after>//===-- iSwitch.cpp - Implement the Switch instruction -----------*- C++ -*--=//
//
// This file implements the Switch instruction...
//
//===----------------------------------------------------------------------===//

#include "llvm/iTerminators.h"
#include "llvm/BasicBlock.h"
#ifndef NDEBUG
#include "llvm/Type.h"
#endif

SwitchInst::SwitchInst(Value *V, BasicBlock *DefDest)
  : TerminatorInst(Instruction::Switch) {
  assert(V && DefDest);
  Operands.push_back(Use(V, this));
  Operands.push_back(Use(DefDest, this));
}

SwitchInst::SwitchInst(const SwitchInst &SI)
  : TerminatorInst(Instruction::Switch) {
  Operands.reserve(SI.Operands.size());

  for (unsigned i = 0, E = SI.Operands.size(); i != E; i+=2) {
    Operands.push_back(Use(SI.Operands[i], this));
    Operands.push_back(Use(SI.Operands[i+1], this));
  }
}

void SwitchInst::dest_push_back(Constant *OnVal, BasicBlock *Dest) {
  Operands.push_back(Use((Value*)OnVal, this));
  Operands.push_back(Use((Value*)Dest, this));
}
<|endoftext|>


<commit_before>
#include "density_clustering_mpi.hpp"

#include "tools.hpp"
#include "logger.hpp"

#include <mpi.h>

namespace Clustering {
namespace Density {
namespace MPI {

  namespace {
    const int MAIN_PROCESS = 0;
  } // end local namespace

  std::vector<std::size_t>
  calculate_populations(const float* coords,
                        const std::size_t n_rows,
                        const std::size_t n_cols,
                        const float radius,
                        const int mpi_n_nodes,
                        const int mpi_node_id) {
    //TODO change this to quadratically falling number of rows
    //     per chunk due to uneven workload of first chunks
    //     compared to last chunks (shorter j-loop!)
    unsigned int rows_per_chunk = n_rows / mpi_n_nodes;
    unsigned int i_row_from = mpi_node_id * rows_per_chunk;
    unsigned int i_row_to = i_row_from + rows_per_chunk;
    // last process has to do slightly more work
    // in case of uneven separation of workload
    if (mpi_node_id == mpi_n_nodes-1 ) {
      i_row_to = n_rows;
    }
    std::vector<unsigned int> pops(n_rows, 0);
    // parallel computation of pops using shared memory
    {
      const float rad2 = radius * radius;
      std::size_t i, j, k;
      float dist, c;
      ASSUME_ALIGNED(coords);
      #pragma omp parallel for default(none) private(i,j,k,c,dist) \
                               firstprivate(i_row_from,i_row_to,n_rows,n_cols,rad2) \
                               shared(coords,pops) \
                               schedule(dynamic,1024)
      for (i=i_row_from; i < i_row_to; ++i) {
        for (j=i+1; j < n_rows; ++j) {
          dist = 0.0f;
          #pragma simd reduction(+:dist)
          for (k=0; k < n_cols; ++k) {
            c = coords[i*n_cols+k] - coords[j*n_cols+k];
            dist += c*c;
          }
          if (dist < rad2) {
            #pragma omp atomic
            pops[i] += 1;
            #pragma omp atomic
            pops[j] += 1;
          }
        }
      }
    }
    // accumulate pops in main process and send result to slaves
    MPI_Barrier(MPI_COMM_WORLD);
    if (mpi_node_id == MAIN_PROCESS) {
      // collect slave results
      for (int slave_id=1; slave_id < mpi_n_nodes; ++slave_id) {
        std::vector<unsigned int> pops_buf(n_rows);
        MPI_Recv(pops_buf.data(), n_rows, MPI_UNSIGNED, slave_id, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        for (std::size_t i=0; i < n_rows; ++i) {
          pops[i] += pops_buf[i];
        }
      }
    } else {
      // send pops from slaves
      MPI_Send(pops.data(), n_rows, MPI_UNSIGNED, MAIN_PROCESS, 0, MPI_COMM_WORLD);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    // broadcast accumulated pops to slaves
    MPI_Bcast(pops.data(), n_rows, MPI_UNSIGNED, MAIN_PROCESS, MPI_COMM_WORLD);
    MPI_Barrier(MPI_COMM_WORLD);
    // cast unsigned int to size_t and add 1 for own structure
    std::vector<std::size_t> pops_result(n_rows);
    for (std::size_t i=0; i < n_rows; ++i) {
      pops_result[i] = (std::size_t) pops[i] + 1;
    }
    return pops_result;
  }

  std::tuple<Neighborhood, Neighborhood>
  nearest_neighbors(const float* coords,
                    const std::size_t n_rows,
                    const std::size_t n_cols,
                    const std::vector<float>& free_energy,
                    const int mpi_n_nodes,
                    const int mpi_node_id) {
    unsigned int rows_per_chunk = n_rows / mpi_n_nodes;
    unsigned int i_row_from = mpi_node_id * rows_per_chunk;
    unsigned int i_row_to = i_row_from + rows_per_chunk;
    // last process has to do slightly more work
    // in case of uneven separation of workload
    if (mpi_node_id == mpi_n_nodes-1 ) {
      i_row_to = n_rows;
    }
    Neighborhood nh;
    Neighborhood nh_high_dens;
    // initialize neighborhood
    for (std::size_t i=i_row_from; i < i_row_to; ++i) {
      nh[i] = Neighbor(n_rows+1, std::numeric_limits<float>::max());
      nh_high_dens[i] = Neighbor(n_rows+1, std::numeric_limits<float>::max());
    }
    // calculate nearest neighbors with distances
    std::size_t i, j, c, min_j, min_j_high_dens;
    float dist, d, mindist, mindist_high_dens;
    ASSUME_ALIGNED(coords);
    #pragma omp parallel for default(none) \
                             private(i,j,c,dist,d,mindist,mindist_high_dens,min_j,min_j_high_dens) \
                             firstprivate(i_row_from,i_row_to,n_rows,n_cols) \
                             shared(coords,nh,nh_high_dens,free_energy) \
                             schedule(dynamic, 2048)
    for (i=i_row_from; i < i_row_to; ++i) {
      mindist = std::numeric_limits<float>::max();
      mindist_high_dens = std::numeric_limits<float>::max();
      min_j = n_rows+1;
      min_j_high_dens = n_rows+1;
      for (j=0; j < n_rows; ++j) {
        if (i != j) {
          dist = 0.0f;
          #pragma simd reduction(+:dist)
          for (c=0; c < n_cols; ++c) {
            d = coords[i*n_cols+c] - coords[j*n_cols+c];
            dist += d*d;
          }
          // direct neighbor
          if (dist < mindist) {
            mindist = dist;
            min_j = j;
          }
          // next neighbor with higher density / lower free energy
          if (free_energy[j] < free_energy[i] && dist < mindist_high_dens) {
            mindist_high_dens = dist;
            min_j_high_dens = j;
          }
        }
      }
      nh[i] = Neighbor(min_j, mindist);
      nh_high_dens[i] = Neighbor(min_j_high_dens, mindist_high_dens);
    }
    // TODO: collect results in MAIN_PROCESS and broadcast to slaves
    MPI_Barrier(MPI_COMM_WORLD);

    return std::make_tuple(nh, nh_high_dens);
  }

  void
  main(boost::program_options::variables_map args) {
    // initialize MPI
    MPI_Init(NULL, NULL);
    int n_nodes;
    MPI_Comm_size(MPI_COMM_WORLD, &n_nodes);
    int node_id;
    MPI_Comm_rank(MPI_COMM_WORLD, &node_id);
    // read basic inputs
    const std::string input_file = args["file"].as<std::string>();
    const float radius = args["radius"].as<float>();
    // setup coords
    float* coords;
    std::size_t n_rows;
    std::size_t n_cols;
    if (node_id == MAIN_PROCESS) {
      Clustering::logger(std::cout) << "reading coords" << std::endl;
    }
    std::tie(coords, n_rows, n_cols) = Clustering::Tools::read_coords<float>(input_file);
    //// free energies
    std::vector<float> free_energies;
    if (args.count("free-energy-input")) {
      if (node_id == MAIN_PROCESS) {
        Clustering::logger(std::cout) << "re-using free energy data." << std::endl;
      }
      free_energies = Clustering::Tools::read_free_energies(args["free-energy-input"].as<std::string>());
    } else if (args.count("free-energy") || args.count("population") || args.count("output")) {
      if (node_id == MAIN_PROCESS) {
        Clustering::logger(std::cout) << "calculating populations" << std::endl;
      }
      std::vector<std::size_t> pops = calculate_populations(coords, n_rows, n_cols, radius, n_nodes, node_id);
      if (node_id == MAIN_PROCESS && args.count("population")) {
        Clustering::Tools::write_single_column<std::size_t>(args["population"].as<std::string>(), pops);
      }
      if (node_id == MAIN_PROCESS) {
        Clustering::logger(std::cout) << "calculating free energies" << std::endl;
      }
      free_energies = Clustering::Density::calculate_free_energies(pops);
      if (node_id == MAIN_PROCESS && args.count("free-energy")) {
        Clustering::Tools::write_single_column<float>(args["free-energy"].as<std::string>(), free_energies, true);
      }
    }

    // TODO use mpi for following code, too

    // run the rest on a single node only
    if (node_id == MAIN_PROCESS) {
      //// nearest neighbors
      Neighborhood nh;
      Neighborhood nh_high_dens;
      if (args.count("nearest-neighbors-input")) {
        Clustering::logger(std::cout) << "re-using nearest neighbor data." << std::endl;
        std::ifstream ifs(args["nearest-neighbors-input"].as<std::string>());
        if (ifs.fail()) {
          std::cerr << "error: cannot open file '" << args["nearest-neighbors-input"].as<std::string>() << "'" << std::endl;
          exit(EXIT_FAILURE);
        } else {
          std::size_t i=0;
          while (ifs.good()) {
            std::size_t buf1;
            float buf2;
            std::size_t buf3;
            float buf4;
            ifs >> buf1;
            ifs >> buf2;
            ifs >> buf3;
            ifs >> buf4;
            if ( ! ifs.fail()) {
              nh[i] = std::pair<std::size_t, float>(buf1, buf2);
              nh_high_dens[i] = std::pair<std::size_t, float>(buf3, buf4);
              ++i;
            }
          }
        }
      } else if (args.count("nearest-neighbors") || args.count("output")) {
        Clustering::logger(std::cout) << "calculating nearest neighbors" << std::endl;
        auto nh_tuple = Clustering::Density::nearest_neighbors(coords, n_rows, n_cols, free_energies);
        nh = std::get<0>(nh_tuple);
        nh_high_dens = std::get<1>(nh_tuple);
        if (args.count("nearest-neighbors")) {
          std::ofstream ofs(args["nearest-neighbors"].as<std::string>());
          auto p = nh.begin();
          auto p_hd = nh_high_dens.begin();
          while (p != nh.end() && p_hd != nh_high_dens.end()) {
            // first: key (not used)
            // second: neighbor
            // second.first: id; second.second: squared dist
            ofs << p->second.first    << " " << p->second.second    << " "
                << p_hd->second.first << " " << p_hd->second.second << "\n";
            ++p;
            ++p_hd;
          }
        }
      }
      //// clustering
      if (args.count("output")) {
        const std::string output_file = args["output"].as<std::string>();
        std::vector<std::size_t> clustering;
        if (args.count("input")) {
          Clustering::logger(std::cout) << "reading initial clusters from file." << std::endl;
          clustering = Clustering::Tools::read_clustered_trajectory(args["input"].as<std::string>());
        } else {
          Clustering::logger(std::cout) << "calculating initial clusters" << std::endl;
          if (args.count("threshold") == 0) {
            std::cerr << "error: need threshold value for initial clustering" << std::endl;
            exit(EXIT_FAILURE);
          }
          float threshold = args["threshold"].as<float>();
          clustering = Clustering::Density::initial_density_clustering(free_energies, nh, threshold, coords, n_rows, n_cols);
        }
        if ( ! args["only-initial"].as<bool>()) {
          Clustering::logger(std::cout) << "assigning low density states to initial clusters" << std::endl;
          clustering = Clustering::Density::assign_low_density_frames(clustering, nh_high_dens, free_energies);
        }
        Clustering::logger(std::cout) << "writing clusters to file " << output_file << std::endl;
        Clustering::Tools::write_single_column<std::size_t>(output_file, clustering);
      }
    }

    // clean up
    if (node_id == MAIN_PROCESS) {
      Clustering::logger(std::cout) << "freeing coords" << std::endl;
    }
    Clustering::Tools::free_coords(coords);
    MPI_Finalize();
  }

} // end namespace MPI
} // end namespace Density
} // end namespace Clustering

<commit_msg>proper load balancing for triangular sums.<commit_after>
#include "density_clustering_mpi.hpp"

#include "tools.hpp"
#include "logger.hpp"

#include <mpi.h>

namespace Clustering {
namespace Density {
namespace MPI {

  namespace {
    const int MAIN_PROCESS = 0;

    /*
     * use no. of rows and no. of MPI nodes to calculate the optimal
     * indices for equal load balancing on all machines to
     * calculate an upper triangular matrix by a nested loop
     * of the form
     *   FOR i=0 TO n_rows
     *     FOR j=i+1 TO n_rows
     *       [...]
     *
     * the returned indices are for the initial index of the outer loop.
     * the inner loop will be local.
     * i.e. on every MPI node, the loop will be of the form
     *   FOR i=indices[node_id] TO (is_last_node ? n_rows : indices[next_node])
     *     FOR j=i+1 TO n_rows
     *       [...]
     *
     * computation of optimal indices is heavily based on triangular summation
     * (please recall the 'algorithm of young C.F. Gauss').
     */
    std::vector<std::size_t>
    triangular_load_balance(std::size_t n_rows,
                            std::size_t n_nodes) {
      auto young_gauss = [](std::size_t n) -> std::size_t {
        return n*(n+1) / 2;
      };
      std::size_t workload = young_gauss(n_rows) / n_nodes;
      std::size_t last_index = 0;
      std::vector<std::size_t> load_balanced_indices(n_nodes);
      for (int i=n_nodes-1; i >= 0; --i) {
        if (i == 0) {
          load_balanced_indices[i] = 0;
        } else {
          last_index = (std::size_t) sqrt(2*(young_gauss(last_index) + workload));
          load_balanced_indices[i] = n_rows - last_index;
        }
      }
      return load_balanced_indices;
    }
  } // end local namespace

  std::vector<std::size_t>
  calculate_populations(const float* coords,
                        const std::size_t n_rows,
                        const std::size_t n_cols,
                        const float radius,
                        const int mpi_n_nodes,
                        const int mpi_node_id) {
    std::vector<std::size_t> load_balanced_indices = triangular_load_balance(n_rows, mpi_n_nodes);
    unsigned int i_row_from = load_balanced_indices[mpi_node_id];
    unsigned int i_row_to;
    if (mpi_node_id == mpi_n_nodes-1) {
      // last node: run to end
      i_row_to = n_rows;
    } else {
      i_row_to = load_balanced_indices[mpi_node_id+1];
    }
    std::vector<unsigned int> pops(n_rows, 0);
    // per-node parallel computation of pops using shared memory
    {
      const float rad2 = radius * radius;
      std::size_t i, j, k;
      float dist, c;
      ASSUME_ALIGNED(coords);
      #pragma omp parallel for default(none) private(i,j,k,c,dist) \
                               firstprivate(i_row_from,i_row_to,n_rows,n_cols,rad2) \
                               shared(coords,pops) \
                               schedule(dynamic,1024)
      for (i=i_row_from; i < i_row_to; ++i) {
        for (j=i+1; j < n_rows; ++j) {
          dist = 0.0f;
          #pragma simd reduction(+:dist)
          for (k=0; k < n_cols; ++k) {
            c = coords[i*n_cols+k] - coords[j*n_cols+k];
            dist += c*c;
          }
          if (dist < rad2) {
            #pragma omp atomic
            pops[i] += 1;
            #pragma omp atomic
            pops[j] += 1;
          }
        }
      }
    }
    // accumulate pops in main process and send result to slaves
    MPI_Barrier(MPI_COMM_WORLD);
    if (mpi_node_id == MAIN_PROCESS) {
      // collect slave results
      for (int slave_id=1; slave_id < mpi_n_nodes; ++slave_id) {
        std::vector<unsigned int> pops_buf(n_rows);
        MPI_Recv(pops_buf.data(), n_rows, MPI_UNSIGNED, slave_id, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        for (std::size_t i=0; i < n_rows; ++i) {
          pops[i] += pops_buf[i];
        }
      }
    } else {
      // send pops from slaves
      MPI_Send(pops.data(), n_rows, MPI_UNSIGNED, MAIN_PROCESS, 0, MPI_COMM_WORLD);
    }
    MPI_Barrier(MPI_COMM_WORLD);
    // broadcast accumulated pops to slaves
    MPI_Bcast(pops.data(), n_rows, MPI_UNSIGNED, MAIN_PROCESS, MPI_COMM_WORLD);
    MPI_Barrier(MPI_COMM_WORLD);
    // cast unsigned int to size_t and add 1 for own structure
    std::vector<std::size_t> pops_result(n_rows);
    for (std::size_t i=0; i < n_rows; ++i) {
      pops_result[i] = (std::size_t) pops[i] + 1;
    }
    return pops_result;
  }

  std::tuple<Neighborhood, Neighborhood>
  nearest_neighbors(const float* coords,
                    const std::size_t n_rows,
                    const std::size_t n_cols,
                    const std::vector<float>& free_energy,
                    const int mpi_n_nodes,
                    const int mpi_node_id) {
    unsigned int rows_per_chunk = n_rows / mpi_n_nodes;
    unsigned int i_row_from = mpi_node_id * rows_per_chunk;
    unsigned int i_row_to = i_row_from + rows_per_chunk;
    // last process has to do slightly more work
    // in case of uneven separation of workload
    if (mpi_node_id == mpi_n_nodes-1 ) {
      i_row_to = n_rows;
    }
    Neighborhood nh;
    Neighborhood nh_high_dens;
    // initialize neighborhood
    for (std::size_t i=i_row_from; i < i_row_to; ++i) {
      nh[i] = Neighbor(n_rows+1, std::numeric_limits<float>::max());
      nh_high_dens[i] = Neighbor(n_rows+1, std::numeric_limits<float>::max());
    }
    // calculate nearest neighbors with distances
    std::size_t i, j, c, min_j, min_j_high_dens;
    float dist, d, mindist, mindist_high_dens;
    ASSUME_ALIGNED(coords);
    #pragma omp parallel for default(none) \
                             private(i,j,c,dist,d,mindist,mindist_high_dens,min_j,min_j_high_dens) \
                             firstprivate(i_row_from,i_row_to,n_rows,n_cols) \
                             shared(coords,nh,nh_high_dens,free_energy) \
                             schedule(dynamic, 2048)
    for (i=i_row_from; i < i_row_to; ++i) {
      mindist = std::numeric_limits<float>::max();
      mindist_high_dens = std::numeric_limits<float>::max();
      min_j = n_rows+1;
      min_j_high_dens = n_rows+1;
      for (j=0; j < n_rows; ++j) {
        if (i != j) {
          dist = 0.0f;
          #pragma simd reduction(+:dist)
          for (c=0; c < n_cols; ++c) {
            d = coords[i*n_cols+c] - coords[j*n_cols+c];
            dist += d*d;
          }
          // direct neighbor
          if (dist < mindist) {
            mindist = dist;
            min_j = j;
          }
          // next neighbor with higher density / lower free energy
          if (free_energy[j] < free_energy[i] && dist < mindist_high_dens) {
            mindist_high_dens = dist;
            min_j_high_dens = j;
          }
        }
      }
      nh[i] = Neighbor(min_j, mindist);
      nh_high_dens[i] = Neighbor(min_j_high_dens, mindist_high_dens);
    }
    // TODO: collect results in MAIN_PROCESS and broadcast to slaves
    MPI_Barrier(MPI_COMM_WORLD);

    return std::make_tuple(nh, nh_high_dens);
  }

  void
  main(boost::program_options::variables_map args) {
    // initialize MPI
    MPI_Init(NULL, NULL);
    int n_nodes;
    MPI_Comm_size(MPI_COMM_WORLD, &n_nodes);
    int node_id;
    MPI_Comm_rank(MPI_COMM_WORLD, &node_id);
    // read basic inputs
    const std::string input_file = args["file"].as<std::string>();
    const float radius = args["radius"].as<float>();
    // setup coords
    float* coords;
    std::size_t n_rows;
    std::size_t n_cols;
    if (node_id == MAIN_PROCESS) {
      Clustering::logger(std::cout) << "reading coords" << std::endl;
    }
    std::tie(coords, n_rows, n_cols) = Clustering::Tools::read_coords<float>(input_file);
    //// free energies
    std::vector<float> free_energies;
    if (args.count("free-energy-input")) {
      if (node_id == MAIN_PROCESS) {
        Clustering::logger(std::cout) << "re-using free energy data." << std::endl;
      }
      free_energies = Clustering::Tools::read_free_energies(args["free-energy-input"].as<std::string>());
    } else if (args.count("free-energy") || args.count("population") || args.count("output")) {
      if (node_id == MAIN_PROCESS) {
        Clustering::logger(std::cout) << "calculating populations" << std::endl;
      }
      std::vector<std::size_t> pops = calculate_populations(coords, n_rows, n_cols, radius, n_nodes, node_id);
      if (node_id == MAIN_PROCESS && args.count("population")) {
        Clustering::Tools::write_single_column<std::size_t>(args["population"].as<std::string>(), pops);
      }
      if (node_id == MAIN_PROCESS) {
        Clustering::logger(std::cout) << "calculating free energies" << std::endl;
      }
      free_energies = Clustering::Density::calculate_free_energies(pops);
      if (node_id == MAIN_PROCESS && args.count("free-energy")) {
        Clustering::Tools::write_single_column<float>(args["free-energy"].as<std::string>(), free_energies, true);
      }
    }

    // TODO use mpi for following code, too

    // run the rest on a single node only
    if (node_id == MAIN_PROCESS) {
      //// nearest neighbors
      Neighborhood nh;
      Neighborhood nh_high_dens;
      if (args.count("nearest-neighbors-input")) {
        Clustering::logger(std::cout) << "re-using nearest neighbor data." << std::endl;
        std::ifstream ifs(args["nearest-neighbors-input"].as<std::string>());
        if (ifs.fail()) {
          std::cerr << "error: cannot open file '" << args["nearest-neighbors-input"].as<std::string>() << "'" << std::endl;
          exit(EXIT_FAILURE);
        } else {
          std::size_t i=0;
          while (ifs.good()) {
            std::size_t buf1;
            float buf2;
            std::size_t buf3;
            float buf4;
            ifs >> buf1;
            ifs >> buf2;
            ifs >> buf3;
            ifs >> buf4;
            if ( ! ifs.fail()) {
              nh[i] = std::pair<std::size_t, float>(buf1, buf2);
              nh_high_dens[i] = std::pair<std::size_t, float>(buf3, buf4);
              ++i;
            }
          }
        }
      } else if (args.count("nearest-neighbors") || args.count("output")) {
        Clustering::logger(std::cout) << "calculating nearest neighbors" << std::endl;
        auto nh_tuple = Clustering::Density::nearest_neighbors(coords, n_rows, n_cols, free_energies);
        nh = std::get<0>(nh_tuple);
        nh_high_dens = std::get<1>(nh_tuple);
        if (args.count("nearest-neighbors")) {
          std::ofstream ofs(args["nearest-neighbors"].as<std::string>());
          auto p = nh.begin();
          auto p_hd = nh_high_dens.begin();
          while (p != nh.end() && p_hd != nh_high_dens.end()) {
            // first: key (not used)
            // second: neighbor
            // second.first: id; second.second: squared dist
            ofs << p->second.first    << " " << p->second.second    << " "
                << p_hd->second.first << " " << p_hd->second.second << "\n";
            ++p;
            ++p_hd;
          }
        }
      }
      //// clustering
      if (args.count("output")) {
        const std::string output_file = args["output"].as<std::string>();
        std::vector<std::size_t> clustering;
        if (args.count("input")) {
          Clustering::logger(std::cout) << "reading initial clusters from file." << std::endl;
          clustering = Clustering::Tools::read_clustered_trajectory(args["input"].as<std::string>());
        } else {
          Clustering::logger(std::cout) << "calculating initial clusters" << std::endl;
          if (args.count("threshold") == 0) {
            std::cerr << "error: need threshold value for initial clustering" << std::endl;
            exit(EXIT_FAILURE);
          }
          float threshold = args["threshold"].as<float>();
          clustering = Clustering::Density::initial_density_clustering(free_energies, nh, threshold, coords, n_rows, n_cols);
        }
        if ( ! args["only-initial"].as<bool>()) {
          Clustering::logger(std::cout) << "assigning low density states to initial clusters" << std::endl;
          clustering = Clustering::Density::assign_low_density_frames(clustering, nh_high_dens, free_energies);
        }
        Clustering::logger(std::cout) << "writing clusters to file " << output_file << std::endl;
        Clustering::Tools::write_single_column<std::size_t>(output_file, clustering);
      }
    }

    // clean up
    if (node_id == MAIN_PROCESS) {
      Clustering::logger(std::cout) << "freeing coords" << std::endl;
    }
    Clustering::Tools::free_coords(coords);
    MPI_Finalize();
  }

} // end namespace MPI
} // end namespace Density
} // end namespace Clustering

<|endoftext|>


<commit_before>/*
 * Copyright 2008 Google Inc.
 * Copyright 2006, 2007 Nintendo Co., Ltd.
 *
 * 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.
 */

#define VERBOSE

#include <es.h>
#include "cpu.h"
#include "io.h"
#include "mps.h"

bool Mps::ConfigurationTableHeader::
accept(Visitor& visitor)
{
    u8* ptr = reinterpret_cast<u8*>(this);
    ptr += sizeof(ConfigurationTableHeader);
    bool cont = true;
    for (int i = 0; cont && i < entryCount; ++i)
    {
        switch (*ptr)
        {
        case PROCESSOR:
            cont = visitor.at(reinterpret_cast<Processor*>(ptr));
            ptr += sizeof(Processor);
            break;
        case BUS:
            cont = visitor.at(reinterpret_cast<Bus*>(ptr));
            ptr += sizeof(Bus);
            break;
        case IO_APIC:
            cont = visitor.at(reinterpret_cast<IOApic*>(ptr));
            ptr += sizeof(IOApic);
            break;
        case IO_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<InterruptAssignment*>(ptr));
            ptr += sizeof(InterruptAssignment);
            break;
        case LOCAL_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<LocalInterruptAssignment*>(ptr));
            ptr += sizeof(LocalInterruptAssignment);
            break;
        default:
            cont = false;
            break;
        }
    }
    return true;
}

Mps::FloatingPointerStructure* Mps::
lookup(void* base, int len)
{
#ifdef VERBOSE
    esReport("Mps::lookup() at %p, %u\n", base, len);
#endif
    u8* ptr = static_cast<u8*>(base);
    while (sizeof(FloatingPointerStructure) <= len--)
    {
        if (ptr[0] == '_' && ptr[1] == 'M' && ptr[2] == 'P' && ptr[3] == '_')
        {
            u8 sum = 0;
            for (int i = 0; i < 16; i++)
            {
                sum += ptr[i];
            }
            if (sum == 0)
            {
                return reinterpret_cast<FloatingPointerStructure*>(ptr);
            }
        }
        ++ptr;
    }
    return 0;
}

Mps::FloatingPointerStructure* Mps::
lookup()
{
    FloatingPointerStructure* fps;
    u16* ebda = reinterpret_cast<u16*>(0x40e);  // for EBDA segment

    if (*ebda)
    {
        // Lookup the first kilobyte of Extended BIOS Data Area.
        fps = lookup(reinterpret_cast<void*>(*ebda * 16), 1024);
        if (fps)
        {
            return fps;
        }
    }
    else
    {
        // Lookup the last kilobyte of system base memory.
        fps = lookup(reinterpret_cast<void*>(*reinterpret_cast<u16*>(0x413) * 1024), 1024);
        if (fps)
        {
            return fps;
        }
    }

    // Lookup the BIOS ROM address space between 0F0000h and 0FFFFFh.
    fps = lookup((void*) 0xf0000, 0x10000);
    if (fps)
    {
        return fps;
    }

    return 0;
}

Mps::
Mps() :
    fps(lookup()),
    cth(0)
{
    ASSERT(sizeof(FloatingPointerStructure) == 16);
    ASSERT(sizeof(ConfigurationTableHeader) == 44);
    ASSERT(sizeof(Processor) == 20);
    ASSERT(sizeof(Bus) == 8);
    ASSERT(sizeof(IOApic) == 8);
    ASSERT(sizeof(InterruptAssignment) == 8);
    ASSERT(sizeof(LocalInterruptAssignment) == 8);

    if (fps == 0)
    {
        return;
    }
#ifdef VERBOSE
    fps->print();
#endif

    cth = reinterpret_cast<ConfigurationTableHeader*>(fps->address);
    if (!cth)
    {
        processorCount = 2;
    }
    else
    {
        cth->accept(processorCount);
#ifdef VERBOSE
        cth->print();
        Printer printer;
        cth->accept(printer);
#endif
    }
    ASSERT(0 < processorCount);
#ifdef VERBOSE
    esReport("MPS %d.%d (%d processor%s)\n",
             1 + fps->specRev / 10, fps->specRev % 10,
             static_cast<int>(processorCount),
             (1 < processorCount) ? "s" : "");
#endif

    fps = reinterpret_cast<FloatingPointerStructure*>(0x80000000 |reinterpret_cast<unsigned long>(fps));
    if (cth)
    {
        cth = reinterpret_cast<ConfigurationTableHeader*>(0x80000000 |reinterpret_cast<unsigned long>(cth));
    }
}

volatile u32* Mps::
getInterruptAssignment(unsigned int bus, unsigned int irq, InterruptAssignment& assignment)
{
    if (cth == 0)
    {
        if (16 <= irq || irq == 2)
        {
            return 0;
        }
        assignment.entryType = IO_INTERRUPT_ASSIGNMENT;
        assignment.type = 0;    // INT
        assignment.flags = 0;
        assignment.busID = 0;
        assignment.busIRQ = irq;
        assignment.apicID = 0;
        assignment.apicINTINn = (irq == 0) ? 2 : irq;
        return reinterpret_cast<u32*>(0xfec00000);
    }

    LookupAssignment entry(bus, irq);
    cth->accept(entry);
    if (!entry)
    {
        return 0;
    }

    LookupIoApic apic(entry->apicID);
    cth->accept(apic);
    if (!apic || !apic->isUsable())
    {
        return 0;
    }

    assignment = *entry;
    return reinterpret_cast<u32*>(apic->address);
}
<commit_msg>(Mps()) : Add a workaround for qemu/Fedora 11.<commit_after>/*
 * Copyright 2008 Google Inc.
 * Copyright 2006, 2007 Nintendo Co., Ltd.
 *
 * 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.
 */

#define VERBOSE

#include <es.h>
#include "cpu.h"
#include "io.h"
#include "mps.h"

bool Mps::ConfigurationTableHeader::
accept(Visitor& visitor)
{
    u8* ptr = reinterpret_cast<u8*>(this);
    ptr += sizeof(ConfigurationTableHeader);
    bool cont = true;
    for (int i = 0; cont && i < entryCount; ++i)
    {
        switch (*ptr)
        {
        case PROCESSOR:
            cont = visitor.at(reinterpret_cast<Processor*>(ptr));
            ptr += sizeof(Processor);
            break;
        case BUS:
            cont = visitor.at(reinterpret_cast<Bus*>(ptr));
            ptr += sizeof(Bus);
            break;
        case IO_APIC:
            cont = visitor.at(reinterpret_cast<IOApic*>(ptr));
            ptr += sizeof(IOApic);
            break;
        case IO_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<InterruptAssignment*>(ptr));
            ptr += sizeof(InterruptAssignment);
            break;
        case LOCAL_INTERRUPT_ASSIGNMENT:
            cont = visitor.at(reinterpret_cast<LocalInterruptAssignment*>(ptr));
            ptr += sizeof(LocalInterruptAssignment);
            break;
        default:
            cont = false;
            break;
        }
    }
    return true;
}

Mps::FloatingPointerStructure* Mps::
lookup(void* base, int len)
{
#ifdef VERBOSE
    esReport("Mps::lookup() at %p, %u\n", base, len);
#endif
    u8* ptr = static_cast<u8*>(base);
    while (sizeof(FloatingPointerStructure) <= len--)
    {
        if (ptr[0] == '_' && ptr[1] == 'M' && ptr[2] == 'P' && ptr[3] == '_')
        {
            u8 sum = 0;
            for (int i = 0; i < 16; i++)
            {
                sum += ptr[i];
            }
            if (sum == 0)
            {
                return reinterpret_cast<FloatingPointerStructure*>(ptr);
            }
        }
        ++ptr;
    }
    return 0;
}

Mps::FloatingPointerStructure* Mps::
lookup()
{
    FloatingPointerStructure* fps;
    u16* ebda = reinterpret_cast<u16*>(0x40e);  // for EBDA segment

    if (*ebda)
    {
        // Lookup the first kilobyte of Extended BIOS Data Area.
        fps = lookup(reinterpret_cast<void*>(*ebda * 16), 1024);
        if (fps)
        {
            return fps;
        }
    }
    else
    {
        // Lookup the last kilobyte of system base memory.
        fps = lookup(reinterpret_cast<void*>(*reinterpret_cast<u16*>(0x413) * 1024), 1024);
        if (fps)
        {
            return fps;
        }
    }

    // Lookup the BIOS ROM address space between 0F0000h and 0FFFFFh.
    fps = lookup((void*) 0xf0000, 0x10000);
    if (fps)
    {
        return fps;
    }

    return 0;
}

Mps::
Mps() :
    fps(lookup()),
    cth(0)
{
    ASSERT(sizeof(FloatingPointerStructure) == 16);
    ASSERT(sizeof(ConfigurationTableHeader) == 44);
    ASSERT(sizeof(Processor) == 20);
    ASSERT(sizeof(Bus) == 8);
    ASSERT(sizeof(IOApic) == 8);
    ASSERT(sizeof(InterruptAssignment) == 8);
    ASSERT(sizeof(LocalInterruptAssignment) == 8);

    if (fps == 0)
    {
        return;
    }
#ifdef VERBOSE
    fps->print();
#endif

    cth = reinterpret_cast<ConfigurationTableHeader*>(fps->address);
    if (!cth)
    {
        processorCount = 2;
    }
    else
    {
        cth->accept(processorCount);
#ifdef VERBOSE
        cth->print();
        Printer printer;
        cth->accept(printer);
#endif
    }
    ASSERT(0 < processorCount);
#ifdef VERBOSE
    esReport("MPS %d.%d (%d processor%s)\n",
             1 + fps->specRev / 10, fps->specRev % 10,
             static_cast<int>(processorCount),
             (1 < processorCount) ? "s" : "");
#endif

    // TODO: The following block is a workaround for qemu/Fedora 11
    //       so as not to use APIC. This should be removed in future.
    if (static_cast<int>(processorCount) == 1)
    {
        fps = 0;
        cth = 0;
        return;
    }

    fps = reinterpret_cast<FloatingPointerStructure*>(0x80000000 |reinterpret_cast<unsigned long>(fps));
    if (cth)
    {
        cth = reinterpret_cast<ConfigurationTableHeader*>(0x80000000 |reinterpret_cast<unsigned long>(cth));
    }
}

volatile u32* Mps::
getInterruptAssignment(unsigned int bus, unsigned int irq, InterruptAssignment& assignment)
{
    if (cth == 0)
    {
        if (16 <= irq || irq == 2)
        {
            return 0;
        }
        assignment.entryType = IO_INTERRUPT_ASSIGNMENT;
        assignment.type = 0;    // INT
        assignment.flags = 0;
        assignment.busID = 0;
        assignment.busIRQ = irq;
        assignment.apicID = 0;
        assignment.apicINTINn = (irq == 0) ? 2 : irq;
        return reinterpret_cast<u32*>(0xfec00000);
    }

    LookupAssignment entry(bus, irq);
    cth->accept(entry);
    if (!entry)
    {
        return 0;
    }

    LookupIoApic apic(entry->apicID);
    cth->accept(apic);
    if (!apic || !apic->isUsable())
    {
        return 0;
    }

    assignment = *entry;
    return reinterpret_cast<u32*>(apic->address);
}
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "regression_serv.hpp"

#include "../regression/regression_factory.hpp"
#include "../common/util.hpp"
#include "../common/vector_util.hpp"
#include "../framework/mixer/mixer_factory.hpp"
#include "../fv_converter/datum.hpp"
#include "../fv_converter/datum_to_fv_converter.hpp"
#include "../fv_converter/converter_config.hpp"
#include "../storage/storage_factory.hpp"

using namespace std;
using pfi::lang::shared_ptr;
using namespace jubatus::common;
using namespace jubatus::framework;
using namespace jubatus::fv_converter;

namespace jubatus {
namespace server {

namespace {

linear_function_mixer::model_ptr make_model(const framework::server_argv& arg) {
  return linear_function_mixer::model_ptr(storage::storage_factory::create_storage((arg.is_standalone())?"local":"local_mixture"));
}

}

regression_serv::regression_serv(const framework::server_argv& a,
                                 const cshared_ptr<lock_service>& zk)
    : server_base(a) {
  gresser_.set_model(make_model(a));
  wm_.set_model(mixable_weight_manager::model_ptr(new weight_manager));

  mixer_.reset(mixer::create_mixer(a, zk));
  mixable_holder_.reset(new mixable_holder());

  mixer_->set_mixable_holder(mixable_holder_);
  mixable_holder_->register_mixable(&gresser_);
  mixable_holder_->register_mixable(&wm_);
}

regression_serv::~regression_serv() {
}

void regression_serv::get_status(status_t& status) const {
  status_t my_status;
  gresser_.get_model()->get_status(my_status);
  my_status["storage"] = gresser_.get_model()->type();

  status.insert(my_status.begin(), my_status.end());
}

int regression_serv::set_config(const string& config) {
  LOG(INFO) << __func__;

  std::string fv_config = "";
  std::string method;

  fv_config = jubatus::util::get_json((std::string)config, "converter");
  method = jubatus::util::get_jsonstring((std::string)config, "method");

  shared_ptr<datum_to_fv_converter> converter
      = fv_converter::make_fv_converter(fv_config);

  config_ = config;
  converter_ = converter;
  (*converter_).set_weight_manager(wm_.get_model());

  // TODO: use param
  pfi::text::json::json param;
  regression_.reset(jubatus::regression::regression_factory().create_regression(method, param, gresser_.get_model().get()));

  // FIXME: switch the function when set_config is done
  // because mixing method differs btwn PA, CW, etc...
  return 0;
}

string regression_serv::get_config() {
  check_set_config();
  return config_;
}

int regression_serv::train(const vector<pair<float, jubatus::datum> >& data) {
  check_set_config();

  int count = 0;
  sfv_t v;
  fv_converter::datum d;

  for (size_t i = 0; i < data.size(); ++i) {
    convert<jubatus::datum, fv_converter::datum>(data[i].second, d);
    converter_->convert_and_update_weight(d, v);
    regression_->train(v, data[i].first);
    count++;
  }
  // FIXME: send count incrementation to mixer
  return count;
}

vector<float> regression_serv::estimate(const vector<jubatus::datum>& data) const {
  check_set_config();

  vector<float> ret;
  sfv_t v;
  fv_converter::datum d;
  for (size_t i = 0; i < data.size(); ++i) {
    convert<datum, fv_converter::datum>(data[i], d);
    converter_->convert(d, v);
    ret.push_back(regression_->estimate(v));
  }
  return ret; //vector<estimate_results> >::ok(ret);
}

void regression_serv::check_set_config() const {
  if (!regression_) {
    throw JUBATUS_EXCEPTION(config_not_set());
  }
}

} // namespace server
} // namespace jubatus
<commit_msg>Remove unnecessary casts<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "regression_serv.hpp"

#include "../regression/regression_factory.hpp"
#include "../common/util.hpp"
#include "../common/vector_util.hpp"
#include "../framework/mixer/mixer_factory.hpp"
#include "../fv_converter/datum.hpp"
#include "../fv_converter/datum_to_fv_converter.hpp"
#include "../fv_converter/converter_config.hpp"
#include "../storage/storage_factory.hpp"

using namespace std;
using pfi::lang::shared_ptr;
using namespace jubatus::common;
using namespace jubatus::framework;
using namespace jubatus::fv_converter;

namespace jubatus {
namespace server {

namespace {

linear_function_mixer::model_ptr make_model(const framework::server_argv& arg) {
  return linear_function_mixer::model_ptr(storage::storage_factory::create_storage((arg.is_standalone())?"local":"local_mixture"));
}

}

regression_serv::regression_serv(const framework::server_argv& a,
                                 const cshared_ptr<lock_service>& zk)
    : server_base(a) {
  gresser_.set_model(make_model(a));
  wm_.set_model(mixable_weight_manager::model_ptr(new weight_manager));

  mixer_.reset(mixer::create_mixer(a, zk));
  mixable_holder_.reset(new mixable_holder());

  mixer_->set_mixable_holder(mixable_holder_);
  mixable_holder_->register_mixable(&gresser_);
  mixable_holder_->register_mixable(&wm_);
}

regression_serv::~regression_serv() {
}

void regression_serv::get_status(status_t& status) const {
  status_t my_status;
  gresser_.get_model()->get_status(my_status);
  my_status["storage"] = gresser_.get_model()->type();

  status.insert(my_status.begin(), my_status.end());
}

int regression_serv::set_config(const string& config) {
  LOG(INFO) << __func__;

  std::string fv_config = "";
  std::string method;

  fv_config = jubatus::util::get_json(config, "converter");
  method = jubatus::util::get_jsonstring(config, "method");

  shared_ptr<datum_to_fv_converter> converter
      = fv_converter::make_fv_converter(fv_config);

  config_ = config;
  converter_ = converter;
  (*converter_).set_weight_manager(wm_.get_model());

  // TODO: use param
  pfi::text::json::json param;
  regression_.reset(jubatus::regression::regression_factory().create_regression(method, param, gresser_.get_model().get()));

  // FIXME: switch the function when set_config is done
  // because mixing method differs btwn PA, CW, etc...
  return 0;
}

string regression_serv::get_config() {
  check_set_config();
  return config_;
}

int regression_serv::train(const vector<pair<float, jubatus::datum> >& data) {
  check_set_config();

  int count = 0;
  sfv_t v;
  fv_converter::datum d;

  for (size_t i = 0; i < data.size(); ++i) {
    convert<jubatus::datum, fv_converter::datum>(data[i].second, d);
    converter_->convert_and_update_weight(d, v);
    regression_->train(v, data[i].first);
    count++;
  }
  // FIXME: send count incrementation to mixer
  return count;
}

vector<float> regression_serv::estimate(const vector<jubatus::datum>& data) const {
  check_set_config();

  vector<float> ret;
  sfv_t v;
  fv_converter::datum d;
  for (size_t i = 0; i < data.size(); ++i) {
    convert<datum, fv_converter::datum>(data[i], d);
    converter_->convert(d, v);
    ret.push_back(regression_->estimate(v));
  }
  return ret; //vector<estimate_results> >::ok(ret);
}

void regression_serv::check_set_config() const {
  if (!regression_) {
    throw JUBATUS_EXCEPTION(config_not_set());
  }
}

} // namespace server
} // namespace jubatus
<|endoftext|>