<commit_before>#include "StateMachine.h"
#include "StateMachineFactory.h"
#include "StateTransitionOperation.h"
#include "OperationEvent.h"
#include "UndoController.h"
#include "mitkInteractionConst.h"

//##ModelId=3E5B2DB301FD
//##Documentation
//## Constructor
//## daclares a new StateMachine and connects
//## it to a StateMachine of Type type;
mitk::StateMachine::StateMachine(std::string type)
: m_Type(type)
{
	m_CurrentState = mitk::StateMachineFactory::GetStartState(type);
    m_UndoController = new UndoController(LIMITEDLINEARUNDO);//switch to LLU or add LLU
	m_UndoEnabled = true;
}

//##ModelId=3E5B2E660087
std::string mitk::StateMachine::GetType() const
{
	return m_Type;
}

//##ModelId=3E5B2DE30378
bool mitk::StateMachine::HandleEvent(StateEvent const* stateEvent, int objectEventId, int groupEventId)
{
  if (m_CurrentState == NULL)
  return false;//m_CurrentState needs to be set first!

  //get Transition from m_Current State with equals ID
  const Transition *tempTransition = m_CurrentState->GetTransition(stateEvent->GetId());
  if (tempTransition == NULL) return false;
  //get next State
  State *tempNextState = tempTransition->GetNextState();
  if (tempNextState == NULL) return false;
  //and SideEffectId to execute later on
  int tempSideEffectId = tempTransition->GetSideEffectId();
  if ( m_CurrentState->GetId() != tempNextState->GetId() )//statechange only if there is a real statechange
  {
    if ( m_UndoEnabled )	//write to UndoMechanism if Undo is enabled
    {
      //UNDO for this statechange
	  StateTransitionOperation* doOp = new StateTransitionOperation(OpSTATECHANGE, tempNextState);
      StateTransitionOperation* undoOp = new StateTransitionOperation(OpSTATECHANGE, m_CurrentState);
	  OperationEvent *operationEvent = new OperationEvent(((mitk::OperationActor*)(this)),
														doOp, undoOp,
														objectEventId ,groupEventId);
	  m_UndoController->SetOperationEvent(operationEvent);
    }
    //first following StateChange(or calling ExecuteOperation(tempNextStateOp)), then operation(SideEffect)
    m_CurrentState = tempNextState;
  }
  //Undo of the SideEffect is handled in ExecuteSideEffect(...)
  bool ok = ExecuteSideEffect(tempSideEffectId, stateEvent, objectEventId, groupEventId);

//Doku: if the operation didn't work, then we have already changed the state.
//Check, if we have already done a statechange, if yes, then recall all of thet ObjectEventId
  if (!ok && m_UndoEnabled &&
    m_UndoController->GetLastObjectEventIdInList()==OperationEvent::GetCurrObjectEventId())//oder objectEventId
  {
    ok = m_UndoController->Undo(true);//fine undo!
  }
  else if (!ok && !m_UndoEnabled &&
    m_UndoController->GetLastObjectEventIdInList()==OperationEvent::GetCurrObjectEventId())
  {
    std::cout<<"Error! Sender: StateMachine; Message: Operation could not be done!"<<std::endl;
  }
  return ok;
}

//##ModelId=3EDCAECB0175
void mitk::StateMachine::EnableUndo(bool enable)
{
	m_UndoEnabled = enable;
}

//##ModelId=3EF099EA03C0
int mitk::StateMachine::IncCurrGroupEventId()
{
	return mitk::OperationEvent::IncCurrGroupEventId();
}

void mitk::StateMachine::ExecuteOperation(Operation* operation)
{
	switch (operation->GetOperationType())
	{
	case OpNOTHING:
		break;
	case OpSTATECHANGE:
		{
			mitk::StateTransitionOperation* stateTransOp = dynamic_cast<mitk::StateTransitionOperation *>(operation);
			if (stateTransOp == NULL)
			{
				std::cout<<"Error! see StateMachine.cpp"<<std::endl;
				return;
			}
			m_CurrentState = stateTransOp->GetState();
		}
		break;
	default:
		;
	}
}<commit_msg>corrected Undo-bug in StateMachine<commit_after>#include "StateMachine.h"
#include "StateMachineFactory.h"
#include "StateTransitionOperation.h"
#include "OperationEvent.h"
#include "UndoController.h"
#include "mitkInteractionConst.h"

//##ModelId=3E5B2DB301FD
//##Documentation
//## Constructor
//## daclares a new StateMachine and connects
//## it to a StateMachine of Type type;
mitk::StateMachine::StateMachine(std::string type)
: m_Type(type)
{
	m_CurrentState = mitk::StateMachineFactory::GetStartState(type);
    m_UndoController = new UndoController(LIMITEDLINEARUNDO);//switch to LLU or add LLU
	m_UndoEnabled = true;
}

//##ModelId=3E5B2E660087
std::string mitk::StateMachine::GetType() const
{
	return m_Type;
}

//##ModelId=3E5B2DE30378
bool mitk::StateMachine::HandleEvent(StateEvent const* stateEvent, int objectEventId, int groupEventId)
{
  if (m_CurrentState == NULL)
  return false;//m_CurrentState needs to be set first!

  //get Transition from m_Current State with equals ID
  const Transition *tempTransition = m_CurrentState->GetTransition(stateEvent->GetId());
  if (tempTransition == NULL) return false;
  //get next State
  State *tempNextState = tempTransition->GetNextState();
  if (tempNextState == NULL) return false;
  //and SideEffectId to execute later on
  int tempSideEffectId = tempTransition->GetSideEffectId();
  if ( m_CurrentState->GetId() != tempNextState->GetId() )//statechange only if there is a real statechange
  {
    if ( m_UndoEnabled )	//write to UndoMechanism if Undo is enabled
    {
      //UNDO for this statechange
	  StateTransitionOperation* doOp = new StateTransitionOperation(OpSTATECHANGE, tempNextState);
      StateTransitionOperation* undoOp = new StateTransitionOperation(OpSTATECHANGE, m_CurrentState);
	  OperationEvent *operationEvent = new OperationEvent(((mitk::OperationActor*)(this)),
														doOp, undoOp,
														objectEventId ,groupEventId);
	  m_UndoController->SetOperationEvent(operationEvent);
    }
    //first following StateChange(or calling ExecuteOperation(tempNextStateOp)), then operation(SideEffect)
    m_CurrentState = tempNextState;
  }
  //Undo of the SideEffect is handled in ExecuteSideEffect(...)
  bool ok = ExecuteSideEffect(tempSideEffectId, stateEvent, objectEventId, groupEventId);

//Doku: if the operation didn't work, then we have already changed the state.
//Check, if we have already done a statechange, if yes, then recall all of thet ObjectEventId
  if ((!ok) && m_UndoEnabled &&
    m_UndoController->GetLastObjectEventIdInList()==objectEventId)//oder objectEventId
  {
    ok = m_UndoController->Undo(true);//fine undo!
  }
  else if (!ok && !m_UndoEnabled &&
    m_UndoController->GetLastObjectEventIdInList()==objectEventId)
  {
    std::cout<<"Error! Sender: StateMachine; Message: Operation could not be done!"<<std::endl;
  }
  return ok;
}

//##ModelId=3EDCAECB0175
void mitk::StateMachine::EnableUndo(bool enable)
{
	m_UndoEnabled = enable;
}

//##ModelId=3EF099EA03C0
int mitk::StateMachine::IncCurrGroupEventId()
{
	return mitk::OperationEvent::IncCurrGroupEventId();
}

void mitk::StateMachine::ExecuteOperation(Operation* operation)
{
	switch (operation->GetOperationType())
	{
	case OpNOTHING:
		break;
	case OpSTATECHANGE:
		{
			mitk::StateTransitionOperation* stateTransOp = dynamic_cast<mitk::StateTransitionOperation *>(operation);
			if (stateTransOp == NULL)
			{
				std::cout<<"Error! see StateMachine.cpp"<<std::endl;
				return;
			}
			m_CurrentState = stateTransOp->GetState();
		}
		break;
	default:
		;
	}
}<|endoftext|>


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

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

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

#include "mitkContourMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include <vtkTransform.h>

#include <GL/glut.h>

mitk::ContourMapper2D::ContourMapper2D()
{
}

mitk::ContourMapper2D::~ContourMapper2D()
{
}

void mitk::ContourMapper2D::Paint(mitk::BaseRenderer * renderer)
  {
  if(IsVisible(renderer)==false) return;

  ////	@FIXME: Logik fuer update
  bool updateNeccesary=true;

  if (updateNeccesary)
    {
    mitk::Contour::Pointer input =  const_cast<mitk::Contour*>(this->GetInput());

    // ok, das ist aus GenerateData kopiert
    mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
    assert(displayGeometry.IsNotNull());

    //apply color and opacity read from the PropertyList
    ApplyProperties(renderer);

    vtkTransform* transform = GetDataTreeNode()->GetVtkTransform();

    //    Contour::OutputType point;
    Contour::BoundingBoxType::PointType point;

    mitk::Point3D p, projected_p;
    float vtkp[3];
    float lineWidth = 3.0;

    if (dynamic_cast<mitk::FloatProperty *>(this->GetDataTreeNode()->GetProperty("Width").GetPointer()) != NULL)
      lineWidth = dynamic_cast<mitk::FloatProperty*>(this->GetDataTreeNode()->GetProperty("Width").GetPointer())->GetValue();
    glLineWidth(lineWidth);

    if (input->GetClosed())
      {
      glBegin (GL_LINE_LOOP);
      }
    else
      {
      glBegin (GL_LINE_STRIP);
      }

    //Contour::InputType end = input->GetContourPath()->EndOfInput();
    //if (end > 50000) end = 0;

    mitk::Contour::PointsContainerPointer points = input->GetPoints();
    mitk::Contour::PointsContainerIterator pointsIt = points->Begin();

    while ( pointsIt != points->End() )
      {
      //while ( idx != end )
      //{
      //      point = input->GetContourPath()->Evaluate(idx);
      point = pointsIt.Value();

      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);

      displayGeometry->Project(p, projected_p);
      Vector3D diff=p-projected_p;
      if(diff.GetSquaredNorm()<1.0)
      {
        Point2D pt2d, tmp;
        displayGeometry->Map(projected_p, pt2d);
        displayGeometry->MMToDisplay(pt2d, pt2d);
        glVertex2f(pt2d[0], pt2d[1]);
      }

      pointsIt++;
      //      idx += 1;
      }
    glEnd ();

    glLineWidth(1.0);

    }
  }

const mitk::Contour* mitk::ContourMapper2D::GetInput(void)
{
  return static_cast<const mitk::Contour * > ( GetData() );
}
<commit_msg>ENH: projection mode (property "project")<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

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

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

#include "mitkContourMapper2D.h"
#include "mitkBaseRenderer.h"
#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include <vtkTransform.h>

#include <GL/glut.h>

mitk::ContourMapper2D::ContourMapper2D()
{
}

mitk::ContourMapper2D::~ContourMapper2D()
{
}

void mitk::ContourMapper2D::Paint(mitk::BaseRenderer * renderer)
  {
  if(IsVisible(renderer)==false) return;

  ////	@FIXME: Logik fuer update
  bool updateNeccesary=true;

  if (updateNeccesary)
    {
    mitk::Contour::Pointer input =  const_cast<mitk::Contour*>(this->GetInput());

    // ok, das ist aus GenerateData kopiert
    mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
    assert(displayGeometry.IsNotNull());

    //apply color and opacity read from the PropertyList
    ApplyProperties(renderer);

    vtkTransform* transform = GetDataTreeNode()->GetVtkTransform();

    //    Contour::OutputType point;
    Contour::BoundingBoxType::PointType point;

    mitk::Point3D p, projected_p;
    float vtkp[3];
    float lineWidth = 3.0;

    if (dynamic_cast<mitk::FloatProperty *>(this->GetDataTreeNode()->GetProperty("Width").GetPointer()) != NULL)
      lineWidth = dynamic_cast<mitk::FloatProperty*>(this->GetDataTreeNode()->GetProperty("Width").GetPointer())->GetValue();
    glLineWidth(lineWidth);

    if (input->GetClosed())
      {
      glBegin (GL_LINE_LOOP);
      }
    else
      {
      glBegin (GL_LINE_STRIP);
      }

    //Contour::InputType end = input->GetContourPath()->EndOfInput();
    //if (end > 50000) end = 0;

    mitk::Contour::PointsContainerPointer points = input->GetPoints();
    mitk::Contour::PointsContainerIterator pointsIt = points->Begin();

    while ( pointsIt != points->End() )
      {
      //while ( idx != end )
      //{
      //      point = input->GetContourPath()->Evaluate(idx);
      point = pointsIt.Value();

      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);

      displayGeometry->Project(p, projected_p);
      bool projectmode=false;
      GetDataTreeNode()->GetVisibility(projectmode, renderer, "project");
      bool drawit=false;
      if(projectmode)
        drawit=true;
      else
      {
        Vector3D diff=p-projected_p;
        if(diff.GetSquaredNorm()<1.0)
          drawit=true;
      }
      if(drawit)
      {
        Point2D pt2d, tmp;
        displayGeometry->Map(projected_p, pt2d);
        displayGeometry->MMToDisplay(pt2d, pt2d);
        glVertex2f(pt2d[0], pt2d[1]);
      }

      pointsIt++;
      //      idx += 1;
      }
    glEnd ();

    glLineWidth(1.0);

    }
  }

const mitk::Contour* mitk::ContourMapper2D::GetInput(void)
{
  return static_cast<const mitk::Contour * > ( GetData() );
}
<|endoftext|>


<commit_before><commit_msg>cppcheck: Prefer prefix ++/-- operators for non-primitive types<commit_after><|endoftext|>


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

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMeshSpatialObjectTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkDefaultDynamicMeshTraits.h>
#include <itkMesh.h>
#include <itkMeshSpatialObject.h>
#include <itkTetrahedronCell.h>

int itkMeshSpatialObjectTest(int, char * [] )
{
  typedef itk::DefaultDynamicMeshTraits< float , 3, 3 > MeshTrait;
  typedef itk::Mesh<float,3,MeshTrait>                  MeshType;
  typedef MeshType::CellTraits                          CellTraits;
  typedef itk::CellInterface< float, CellTraits >       CellInterfaceType;
  typedef itk::TetrahedronCell<CellInterfaceType>       TetraCellType;
  typedef itk::MeshSpatialObject<MeshType>              MeshSpatialObjectType;
  typedef MeshType::PointType                           PointType;
  typedef MeshType::CellType                            CellType;
  typedef CellType::CellAutoPointer                     CellAutoPointer;

  // Create an itkMesh
  MeshType::Pointer mesh = MeshType::New();

  MeshType::CoordRepType testPointCoords[4][3]
    = { {0,0,0}, {9,0,0}, {9,9,0}, {0,0,9} };

  unsigned long tetraPoints[4] = {0,1,2,3};

  int i;
  for(i=0; i < 4 ; ++i)
    {
    mesh->SetPoint(i, PointType(testPointCoords[i]));
    }

  mesh->SetCellsAllocationMethod( MeshType::CellsAllocatedDynamicallyCellByCell );
  CellAutoPointer testCell1;
  testCell1.TakeOwnership(  new TetraCellType );
  testCell1->SetPointIds(tetraPoints);
  mesh->SetCell(0, testCell1 );

  // Create the mesh Spatial Object

  MeshSpatialObjectType::Pointer meshSO = MeshSpatialObjectType::New();
  meshSO->SetMesh(mesh);

  std::cout << "Testing GetMesh(): ";

  if(mesh != meshSO->GetMesh())
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }
  std::cout<<"[PASSED]"<<std::endl;

  std::cout << "Testing Bounding Box: ";

  if( (meshSO->GetBoundingBox()->GetBounds()[0] != 0)
   || (meshSO->GetBoundingBox()->GetBounds()[1] != 9)
   || (meshSO->GetBoundingBox()->GetBounds()[2] != 0)
   || (meshSO->GetBoundingBox()->GetBounds()[3] != 9)
   || (meshSO->GetBoundingBox()->GetBounds()[4] != 0)
   || (meshSO->GetBoundingBox()->GetBounds()[5] != 9)
   )
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }

  std::cout<<"[PASSED]"<<std::endl;

  // Testing is inside
  std::cout << "Testing IsInside: ";

  MeshSpatialObjectType::PointType inside;
  inside[0] = 1;
  inside[1] = 1;
  inside[2] = 1;
  MeshSpatialObjectType::PointType outside;
  outside[0] = 0;
  outside[1] = 3;
  outside[2] = 0;

  if(!meshSO->IsInside(inside) || meshSO->IsInside(outside))
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }
  std::cout<<"[PASSED]"<<std::endl;

  // Testing is valueAt
  std::cout << "Testing ValueAt: ";
  double value;
  meshSO->ValueAt(inside,value);
  if(!value)
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }

  meshSO->ValueAt(outside,value);
  if(value)
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }

  std::cout<<"[PASSED]"<<std::endl;

  // Testing IsInside() for triangle mesh
  std::cout << "Testing IsInside() Triangle: ";
  typedef itk::TriangleCell<CellInterfaceType>          TriangleCellType;

  // Create an itkMesh
  MeshType::Pointer meshTriangle = MeshType::New();

  MeshType::CoordRepType testTrianglePointCoords[4][3]
    = { {50,50,64}, {50,100,64}, {100,50,64} , {100,100,64}};

  unsigned long trianglePoint1[3] = {0,1,2};

  for(i=0; i < 4 ; ++i)
    {
    meshTriangle->SetPoint(i, PointType(testTrianglePointCoords[i]));
    }

  unsigned long trianglePoint2[] = {1,2,3};

  meshTriangle->SetCellsAllocationMethod( MeshType::CellsAllocatedDynamicallyCellByCell );
  CellAutoPointer testCell3;
  testCell3.TakeOwnership(  new TriangleCellType );
  testCell3->SetPointIds(trianglePoint1);
  meshTriangle->SetCell(0, testCell3 );

  CellAutoPointer testCell4;
  testCell4.TakeOwnership(  new TriangleCellType );
  testCell4->SetPointIds(trianglePoint2);
  meshTriangle->SetCell(1, testCell4 );

  // Create the mesh Spatial Object
  MeshSpatialObjectType::Pointer meshTriangleSO = MeshSpatialObjectType::New();
  meshTriangleSO->SetMesh(meshTriangle);

  itk::Point<double,3> pIn;
  pIn[0] = 60;
  pIn[1] = 60;
  pIn[2] = 64;
  itk::Point<double,3> pOut;
  pOut[0] = 60;
  pOut[1] = 102;
  pOut[2] = 64;
  if(!meshTriangleSO->IsInside(pIn) || meshTriangleSO->IsInside(pOut))
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }
  std::cout<<"[PASSED]"<<std::endl;

  std::cout<<"[TEST DONE]"<<std::endl;

  return EXIT_SUCCESS;

}
<commit_msg>ENH: Added some descriptions when the test fails<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMeshSpatialObjectTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

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

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkDefaultDynamicMeshTraits.h>
#include <itkMesh.h>
#include <itkMeshSpatialObject.h>
#include <itkTetrahedronCell.h>

int itkMeshSpatialObjectTest(int, char * [] )
{
  typedef itk::DefaultDynamicMeshTraits< float , 3, 3 > MeshTrait;
  typedef itk::Mesh<float,3,MeshTrait>                  MeshType;
  typedef MeshType::CellTraits                          CellTraits;
  typedef itk::CellInterface< float, CellTraits >       CellInterfaceType;
  typedef itk::TetrahedronCell<CellInterfaceType>       TetraCellType;
  typedef itk::MeshSpatialObject<MeshType>              MeshSpatialObjectType;
  typedef MeshType::PointType                           PointType;
  typedef MeshType::CellType                            CellType;
  typedef CellType::CellAutoPointer                     CellAutoPointer;

  // Create an itkMesh
  MeshType::Pointer mesh = MeshType::New();

  MeshType::CoordRepType testPointCoords[4][3]
    = { {0,0,0}, {9,0,0}, {9,9,0}, {0,0,9} };

  unsigned long tetraPoints[4] = {0,1,2,3};

  int i;
  for(i=0; i < 4 ; ++i)
    {
    mesh->SetPoint(i, PointType(testPointCoords[i]));
    }

  mesh->SetCellsAllocationMethod( MeshType::CellsAllocatedDynamicallyCellByCell );
  CellAutoPointer testCell1;
  testCell1.TakeOwnership(  new TetraCellType );
  testCell1->SetPointIds(tetraPoints);
  mesh->SetCell(0, testCell1 );

  // Create the mesh Spatial Object

  MeshSpatialObjectType::Pointer meshSO = MeshSpatialObjectType::New();
  meshSO->SetMesh(mesh);

  std::cout << "Testing GetMesh(): ";

  if(mesh != meshSO->GetMesh())
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }
  std::cout<<"[PASSED]"<<std::endl;

  std::cout << "Testing Bounding Box: ";

  if( (meshSO->GetBoundingBox()->GetBounds()[0] != 0)
   || (meshSO->GetBoundingBox()->GetBounds()[1] != 9)
   || (meshSO->GetBoundingBox()->GetBounds()[2] != 0)
   || (meshSO->GetBoundingBox()->GetBounds()[3] != 9)
   || (meshSO->GetBoundingBox()->GetBounds()[4] != 0)
   || (meshSO->GetBoundingBox()->GetBounds()[5] != 9)
   )
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }

  std::cout<<"[PASSED]"<<std::endl;

  // Testing is inside
  std::cout << "Testing IsInside: ";

  MeshSpatialObjectType::PointType inside;
  inside[0] = 1;
  inside[1] = 1;
  inside[2] = 1;
  MeshSpatialObjectType::PointType outside;
  outside[0] = 0;
  outside[1] = 3;
  outside[2] = 0;

  if(!meshSO->IsInside(inside) || meshSO->IsInside(outside))
    {
    std::cout<<"[FAILED]"<<std::endl;
    if(!meshSO->IsInside(inside))
      {
      std::cout << inside << " is not inside the mesh!" << std::endl;
      }
    if(meshSO->IsInside(outside))
      {
      std::cout << outside << " is inside the mesh!" << std::endl;
      }
    return EXIT_FAILURE;
    }
  std::cout<<"[PASSED]"<<std::endl;

  // Testing is valueAt
  std::cout << "Testing ValueAt: ";
  double value;
  meshSO->ValueAt(inside,value);
  if(!value)
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }

  meshSO->ValueAt(outside,value);
  if(value)
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }

  std::cout<<"[PASSED]"<<std::endl;

  // Testing IsInside() for triangle mesh
  std::cout << "Testing IsInside() Triangle: ";
  typedef itk::TriangleCell<CellInterfaceType>          TriangleCellType;

  // Create an itkMesh
  MeshType::Pointer meshTriangle = MeshType::New();

  MeshType::CoordRepType testTrianglePointCoords[4][3]
    = { {50,50,64}, {50,100,64}, {100,50,64} , {100,100,64}};

  unsigned long trianglePoint1[3] = {0,1,2};

  for(i=0; i < 4 ; ++i)
    {
    meshTriangle->SetPoint(i, PointType(testTrianglePointCoords[i]));
    }

  unsigned long trianglePoint2[] = {1,2,3};

  meshTriangle->SetCellsAllocationMethod( MeshType::CellsAllocatedDynamicallyCellByCell );
  CellAutoPointer testCell3;
  testCell3.TakeOwnership(  new TriangleCellType );
  testCell3->SetPointIds(trianglePoint1);
  meshTriangle->SetCell(0, testCell3 );

  CellAutoPointer testCell4;
  testCell4.TakeOwnership(  new TriangleCellType );
  testCell4->SetPointIds(trianglePoint2);
  meshTriangle->SetCell(1, testCell4 );

  // Create the mesh Spatial Object
  MeshSpatialObjectType::Pointer meshTriangleSO = MeshSpatialObjectType::New();
  meshTriangleSO->SetMesh(meshTriangle);

  itk::Point<double,3> pIn;
  pIn[0] = 60;
  pIn[1] = 60;
  pIn[2] = 64;
  itk::Point<double,3> pOut;
  pOut[0] = 60;
  pOut[1] = 102;
  pOut[2] = 64;
  if(!meshTriangleSO->IsInside(pIn) || meshTriangleSO->IsInside(pOut))
    {
    std::cout<<"[FAILED]"<<std::endl;
    return EXIT_FAILURE;
    }
  std::cout<<"[PASSED]"<<std::endl;

  std::cout<<"[TEST DONE]"<<std::endl;

  return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before>/*
 * opencog/atoms/core/FreeLink.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/atom_types.h>
#include <opencog/atoms/base/ClassServer.h>
#include "FreeLink.h"
#include "DefineLink.h"
#include "FunctionLink.h"
#include "TypedAtomLink.h"
#include "UniqueLink.h"

using namespace opencog;

FreeLink::FreeLink(const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(FREE_LINK, oset, tv, av)
{
	init();
}

FreeLink::FreeLink(const Handle& a,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(FREE_LINK, a, tv, av)
{
	init();
}

FreeLink::FreeLink(Type t, const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(t, oset, tv, av)
{
	if (not classserver().isA(t, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != t) return;
	init();
}

FreeLink::FreeLink(Type t, const Handle& a,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(t, a, tv, av)
{
	if (not classserver().isA(t, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != t) return;
	init();
}

FreeLink::FreeLink(Type t, const Handle& a, const Handle& b,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(t, a, b, tv, av)
{
	if (not classserver().isA(t, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != t) return;
	init();
}

FreeLink::FreeLink(Link& l)
    : Link(l)
{
	Type tscope = l.getType();
	if (not classserver().isA(tscope, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != tscope) return;
	init();
}

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

void FreeLink::init(void)
{
	_vars.find_variables(_outgoing);
}

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

FreeLinkPtr FreeLink::factory(const Handle& h)
{
	// If h is of the right form already, its just a matter of calling
	// it.  Otherwise, we have to create
	FreeLinkPtr flp(FreeLinkCast(h));
	if (flp) return flp;

	if (nullptr == h)
		throw RuntimeException(TRACE_INFO, "Not executable!");

	return factory(h->getType(), h->getOutgoingSet());
}

// Basic type factory.
FreeLinkPtr FreeLink::factory(Type t, const HandleSeq& seq)
{
	if (DEFINE_LINK == t)
		return createDefineLink(seq);

	if (classserver().isA(t, FUNCTION_LINK))
		return FunctionLink::factory(t, seq);

	if (TYPED_ATOM_LINK == t)
		return createTypedAtomLink(seq);

	if (UNIQUE_LINK == t)
		return createUniqueLink(seq);

	if (classserver().isA(t, FREE_LINK))
		return createFreeLink(t, seq);

	throw SyntaxException(TRACE_INFO,
		"FreeLink is not a factory for %s",
		classserver().getTypeName(t).c_str());
}
<commit_msg>Add a missing link type to the factory<commit_after>/*
 * opencog/atoms/core/FreeLink.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atoms/base/atom_types.h>
#include <opencog/atoms/base/ClassServer.h>
#include "FreeLink.h"
#include "DefineLink.h"
#include "FunctionLink.h"
#include "StateLink.h"
#include "TypedAtomLink.h"
#include "UniqueLink.h"

using namespace opencog;

FreeLink::FreeLink(const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(FREE_LINK, oset, tv, av)
{
	init();
}

FreeLink::FreeLink(const Handle& a,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(FREE_LINK, a, tv, av)
{
	init();
}

FreeLink::FreeLink(Type t, const HandleSeq& oset,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(t, oset, tv, av)
{
	if (not classserver().isA(t, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != t) return;
	init();
}

FreeLink::FreeLink(Type t, const Handle& a,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(t, a, tv, av)
{
	if (not classserver().isA(t, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != t) return;
	init();
}

FreeLink::FreeLink(Type t, const Handle& a, const Handle& b,
                   TruthValuePtr tv,
                   AttentionValuePtr av)
    : Link(t, a, b, tv, av)
{
	if (not classserver().isA(t, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != t) return;
	init();
}

FreeLink::FreeLink(Link& l)
    : Link(l)
{
	Type tscope = l.getType();
	if (not classserver().isA(tscope, FREE_LINK))
		throw InvalidParamException(TRACE_INFO, "Expecting a FreeLink");

	// Derived classes have thier own init routines.
	if (FREE_LINK != tscope) return;
	init();
}

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

void FreeLink::init(void)
{
	_vars.find_variables(_outgoing);
}

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

FreeLinkPtr FreeLink::factory(const Handle& h)
{
	// If h is of the right form already, its just a matter of calling
	// it.  Otherwise, we have to create
	FreeLinkPtr flp(FreeLinkCast(h));
	if (flp) return flp;

	if (nullptr == h)
		throw RuntimeException(TRACE_INFO, "Not executable!");

	return factory(h->getType(), h->getOutgoingSet());
}

// Basic type factory.
FreeLinkPtr FreeLink::factory(Type t, const HandleSeq& seq)
{
	if (DEFINE_LINK == t)
		return createDefineLink(seq);

	if (classserver().isA(t, FUNCTION_LINK))
		return FunctionLink::factory(t, seq);

	if (STATE_LINK == t)
		return createStateLink(seq);

	if (TYPED_ATOM_LINK == t)
		return createTypedAtomLink(seq);

	if (UNIQUE_LINK == t)
		return createUniqueLink(seq);

	if (classserver().isA(t, FREE_LINK))
		return createFreeLink(t, seq);

	throw SyntaxException(TRACE_INFO,
		"FreeLink is not a factory for %s",
		classserver().getTypeName(t).c_str());
}
<|endoftext|>


<commit_before>/*
 * TypeUtils.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  December 2015
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public
 * License along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/Link.h>
#include <opencog/atomspace/ClassServer.h>

#include <opencog/atoms/TypeNode.h>
#include <opencog/atoms/core/DefineLink.h>

#include "TypeUtils.h"

using namespace opencog;

/* ================================================================= */
/**
 * Type checker.  Returns true if `val` is of type `deep`.
 */
bool opencog::value_is_type(const Handle& spec, const Handle& val)
{
	Handle deep(spec);

	Type valtype = val->getType();
	Type dpt = deep->getType();

	// If it's a user-defined type, replace by it's defintion.
	if (DEFINED_TYPE_NODE == dpt)
	{
		deep = DefineLink::get_definition(deep);
		dpt = deep->getType();
	}

	// If it's a signature, unpack it now.
	if (SIGNATURE_LINK == dpt)
	{
		LinkPtr dptr(LinkCast(deep));
		deep = dptr->getOutgoingAtom(0);
		dpt = deep->getType();
	}

	if (TYPE_NODE == dpt)
	{
		Type deeptype = TypeNodeCast(deep)->get_value();
		return (valtype == deeptype);
	}
	else if (TYPE_CHOICE == dpt)
	{
		LinkPtr dptr(LinkCast(deep));
		for (const Handle& choice : dptr->getOutgoingSet())
		{
			if (value_is_type(choice, val)) return true;
		}
		return false;
	}
	else if (FUZZY_LINK == dpt)
	{
		throw RuntimeException(TRACE_INFO,
			"Not implemented! TODO XXX FIXME");
	}

	// If it is a node, not a link, then it is a type-constant,
	// and thus must match perfectly.
	LinkPtr dptr(LinkCast(deep));
	if (nullptr == dptr)
		return (deep == val);

	// If a link, then both must be same link type.
	if (valtype != dpt) return false;

	LinkPtr vptr(LinkCast(val));
	const HandleSeq& vlo = vptr->getOutgoingSet();
	const HandleSeq& dpo = dptr->getOutgoingSet();
	size_t sz = dpo.size();

	// Both must be the same size...
	if (vlo.size() != sz) return false;

	// Unordered links are harder to handle...
	if (classserver().isA(dpt, UNORDERED_LINK))
		throw RuntimeException(TRACE_INFO,
			"Not implemented! TODO XXX FIXME");

	// Ordered links are compared side-by-side
	for (size_t i=0; i<sz; i++)
	{
		if (not value_is_type(dpo[i], vlo[i])) return false;
	}

	// If we are here, all checks must hav passed.
	return true;
}

/* ===================== END OF FILE ===================== */
<commit_msg>Continue adding to the type utils<commit_after>/*
 * TypeUtils.cc
 *
 * Copyright (C) 2015 Linas Vepstas
 *
 * Author: Linas Vepstas <linasvepstas@gmail.com>  December 2015
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the
 * exceptions at http://opencog.org/wiki/Licenses
 *
 * 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 Affero General Public
 * License along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/atomspace/Link.h>
#include <opencog/atomspace/ClassServer.h>

#include <opencog/atoms/TypeNode.h>
#include <opencog/atoms/core/DefineLink.h>

#include "TypeUtils.h"

using namespace opencog;

/* ================================================================= */
/**
 * Type checker.  Returns true if `val` is of type `deep`.
 */
bool opencog::value_is_type(const Handle& spec, const Handle& val)
{
	Handle deep(spec);

	Type valtype = val->getType();
	Type dpt = deep->getType();

	// If it's a user-defined type, replace by it's defintion.
	if (DEFINED_TYPE_NODE == dpt)
	{
		deep = DefineLink::get_definition(deep);
		dpt = deep->getType();
	}

	// If it's a signature, unpack it now.
	if (SIGNATURE_LINK == dpt)
	{
		LinkPtr dptr(LinkCast(deep));
		deep = dptr->getOutgoingAtom(0);
		dpt = deep->getType();
	}

	if (TYPE_NODE == dpt)
	{
		Type deeptype = TypeNodeCast(deep)->get_value();
		return (valtype == deeptype);
	}
	else if (TYPE_CHOICE == dpt)
	{
		LinkPtr dptr(LinkCast(deep));
		for (const Handle& choice : dptr->getOutgoingSet())
		{
			if (value_is_type(choice, val)) return true;
		}
		return false;
	}
	else if (FUZZY_LINK == dpt)
	{
		throw RuntimeException(TRACE_INFO,
			"Not implemented! TODO XXX FIXME");
	}

	// If it is a node, not a link, then it is a type-constant,
	// and thus must match perfectly.
	LinkPtr dptr(LinkCast(deep));
	if (nullptr == dptr)
		return (deep == val);

	// If a link, then both must be same link type.
	if (valtype != dpt) return false;

	LinkPtr vptr(LinkCast(val));
	const HandleSeq& vlo = vptr->getOutgoingSet();
	const HandleSeq& dpo = dptr->getOutgoingSet();
	size_t sz = dpo.size();

	// Both must be the same size...
	if (vlo.size() != sz) return false;

	// Unordered links are harder to handle...
	if (classserver().isA(dpt, UNORDERED_LINK))
		throw RuntimeException(TRACE_INFO,
			"Not implemented! TODO XXX FIXME");

	// Ordered links are compared side-by-side
	for (size_t i=0; i<sz; i++)
	{
		if (not value_is_type(dpo[i], vlo[i])) return false;
	}

	// If we are here, all checks must hav passed.
	return true;
}

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

bool type_match(const Handle& left_, const Handle& right_)
{
	Handle left(left_);
	Type ltype = left->getType();

	// If it's a user-defined type, replace by it's defintion.
	if (DEFINED_TYPE_NODE == ltype)
	{
		left = DefineLink::get_definition(left);
		ltype = left->getType();
	}

	// Unpack the arrow; right must match left's input.
	if (ARROW_LINK == ltype)
	{
		LinkPtr larrow(LinkCast(left));
		left = larrow->getOutgoingAtom(0); // 0 == input
	}

	// If right is not a type, then just use value-check.
	Type rtype = right_->getType();
	if (TYPE_NODE != rtype and
	    TYPE_CHOICE != rtype and
	    SIGNATURE_LINK != rtype and
	    DEFINED_TYPE_NODE != rtype and
	    ARROW_LINK != rtype)
	{
		return value_is_type(left, right_);
	}

	Handle right(right_);

	// If it's a user-defined type, replace by it's defintion.
	if (DEFINED_TYPE_NODE == rtype)
	{
		right = DefineLink::get_definition(right);
		rtype = right->getType();
	}

	// Unpack the arrow; right's output must match left.
	if (ARROW_LINK == rtype)
	{
		LinkPtr rarrow(LinkCast(right));
		right = rarrow->getOutgoingAtom(1); // 1 == output
	}

	return false;
}

Handle type_compose(const Handle& left, const Handle& right)
{
	return Handle::UNDEFINED;
}

/* ===================== END OF FILE ===================== */
<|endoftext|>


<commit_before><commit_msg>Different approach to calculating fitness whereby the genotypes are pre-computed, and the union of all set bits is walked.  This requires that the bits to be disambiguated.  The assumption being that it is more efficient to walk a single block and disambiguate, than it is to walk multiple unambiguous blocks<commit_after><|endoftext|>


<commit_before><commit_msg>Adapt tbb_sched to recent changes<commit_after><|endoftext|>


<commit_before><commit_msg>Remove the "Proxy-Support: Session-Based-Authentication" response headers from the NTLMAuth1 and NTLMAuth2 tests because they were inserted by Fiddler 2 (acting as a proxy) rather than from the server.<commit_after><|endoftext|>


<commit_before>#ifndef AIKIDO_STATESPACE_COMPOUNDSTATESPACE_H
#define AIKIDO_STATESPACE_COMPOUNDSTATESPACE_H
#include <vector>
#include "StateSpace.hpp"
#include "ScopedState.hpp"

namespace aikido {
namespace statespace {

// Defined in detail/CompoundStateSpace.hpp
template <class> class CompoundStateHandle;

/// Represents the Cartesian product of other StateSpaces.
class CompoundStateSpace
  : std::enable_shared_from_this<CompoundStateSpace>
  , public virtual StateSpace
{
public:
  /// A tuple of states where the i-th state is from the i-th subspace.
  class State : public StateSpace::State
  {
  protected:
    State() = default;
    ~State() = default;

    friend class CompoundStateSpace;
  };

  using StateHandle = CompoundStateHandle<State>;
  using StateHandleConst = CompoundStateHandle<const State>;

  using ScopedState = statespace::ScopedState<StateHandle>;
  using ScopedStateConst = statespace::ScopedState<StateHandleConst>;

  /// Construct the Cartesian product of a vector of subspaces.
  explicit CompoundStateSpace(const std::vector<StateSpacePtr>& _subspaces);

  /// Helper function to create a ScopedState.
  ScopedState createState() const;

  /// Gets number of subspaces.
  size_t getNumStates() const;

  /// Gets subspace by index.
  template <class Space = StateSpace>
  const Space* getSubSpace(size_t _index) const;

  /// Gets state of type by subspace index.
  template <class Space = StateSpace>
  typename Space::State* getSubState(
    StateSpace::State* _state, size_t _index) const;

  /// Gets state of type by subspace index.
  template <class Space = StateSpace>
  const typename Space::State* getSubState(
    const StateSpace::State* _state, size_t _index) const;

  /// Gets state handle of type by subspace index.
  template <class Space = StateSpace>
  typename Space::StateHandle getSubStateHandle(
    StateSpace::State* _state, size_t _index) const;

  /// Gets state handle of type by subspace index.
  template <class Space = StateSpace>
  typename Space::StateHandleConst getSubStateHandle(
    const StateSpace::State* _state, size_t _index) const;

  // Documentation inherited.
  size_t getStateSizeInBytes() const override;

  // Documentation inherited.
  StateSpace::State* allocateStateInBuffer(void* _buffer) const override;

  // Documentation inherited.
  void freeStateInBuffer(StateSpace::State* _state) const override;

  // Documentation inherited.
  SampleableConstraintPtr createSampleableConstraint(
    std::unique_ptr<util::RNG> _rng) const override;

  // Documentation inherited.
  void compose(
    const StateSpace::State* _state1, const StateSpace::State* _state2,
    StateSpace::State* _out) const override;

  // Documentation inherited. _tangent should be 3d twist.
  void expMap(
    const Eigen::VectorXd& _tangent, StateSpace::State* _out) const override;

  // Documentation inherited.
  int getDimension() const override;

private:
  std::vector<StateSpacePtr> mSubspaces;
  std::vector<std::size_t> mOffsets;
  size_t mSizeInBytes;
};

} // namespace statespace
} // namespace aikido

#include "detail/CompoundStateSpace.hpp"

#endif
<commit_msg>fixed shared_from on CompoundStateSpace<commit_after>#ifndef AIKIDO_STATESPACE_COMPOUNDSTATESPACE_H
#define AIKIDO_STATESPACE_COMPOUNDSTATESPACE_H
#include <vector>
#include "StateSpace.hpp"
#include "ScopedState.hpp"

namespace aikido {
namespace statespace {

// Defined in detail/CompoundStateSpace.hpp
template <class> class CompoundStateHandle;

/// Represents the Cartesian product of other StateSpaces.
class CompoundStateSpace
  : public std::enable_shared_from_this<CompoundStateSpace>
  , public virtual StateSpace
{
public:
  /// A tuple of states where the i-th state is from the i-th subspace.
  class State : public StateSpace::State
  {
  protected:
    State() = default;
    ~State() = default;

    friend class CompoundStateSpace;
  };

  using StateHandle = CompoundStateHandle<State>;
  using StateHandleConst = CompoundStateHandle<const State>;

  using ScopedState = statespace::ScopedState<StateHandle>;
  using ScopedStateConst = statespace::ScopedState<StateHandleConst>;

  /// Construct the Cartesian product of a vector of subspaces.
  explicit CompoundStateSpace(const std::vector<StateSpacePtr>& _subspaces);

  /// Helper function to create a ScopedState.
  ScopedState createState() const;

  /// Gets number of subspaces.
  size_t getNumStates() const;

  /// Gets subspace by index.
  template <class Space = StateSpace>
  const Space* getSubSpace(size_t _index) const;

  /// Gets state of type by subspace index.
  template <class Space = StateSpace>
  typename Space::State* getSubState(
    StateSpace::State* _state, size_t _index) const;

  /// Gets state of type by subspace index.
  template <class Space = StateSpace>
  const typename Space::State* getSubState(
    const StateSpace::State* _state, size_t _index) const;

  /// Gets state handle of type by subspace index.
  template <class Space = StateSpace>
  typename Space::StateHandle getSubStateHandle(
    StateSpace::State* _state, size_t _index) const;

  /// Gets state handle of type by subspace index.
  template <class Space = StateSpace>
  typename Space::StateHandleConst getSubStateHandle(
    const StateSpace::State* _state, size_t _index) const;

  // Documentation inherited.
  size_t getStateSizeInBytes() const override;

  // Documentation inherited.
  StateSpace::State* allocateStateInBuffer(void* _buffer) const override;

  // Documentation inherited.
  void freeStateInBuffer(StateSpace::State* _state) const override;

  // Documentation inherited.
  SampleableConstraintPtr createSampleableConstraint(
    std::unique_ptr<util::RNG> _rng) const override;

  // Documentation inherited.
  void compose(
    const StateSpace::State* _state1, const StateSpace::State* _state2,
    StateSpace::State* _out) const override;

  // Documentation inherited. _tangent should be 3d twist.
  void expMap(
    const Eigen::VectorXd& _tangent, StateSpace::State* _out) const override;

  // Documentation inherited.
  int getDimension() const override;

private:
  std::vector<StateSpacePtr> mSubspaces;
  std::vector<std::size_t> mOffsets;
  size_t mSizeInBytes;
};

} // namespace statespace
} // namespace aikido

#include "detail/CompoundStateSpace.hpp"

#endif
<|endoftext|>


<commit_before>#include "GLPKInterface.h"
#if HAVE_GLPK

#include <utils.h>
#include <utils/SignalHandler.h>
#include <signal.h>
#include <iostream>
#include <stdexcept>
extern "C"
{
#include <glpk.h>
}
using namespace Optimization;
using namespace std;

#if GLP_MAJOR_VERSION < 4 || GLP_MINOR_VERSION < 20
#error "Require GLPK 4.20 or above"
#endif

const static Real kZeroTol = 1e-6;

GLPKInterface::GLPKInterface()
:lp(NULL)
{}

GLPKInterface::~GLPKInterface()
{
  SafeDeleteProc(lp,glp_delete_prob);
}

inline int BoundType(Real low,Real high)
{
  if(IsInf(low)==-1) {
    if(IsInf(high) == 1) return GLP_FR;
    return GLP_UP;
  }
  else if(IsInf(high) == 1) {
    return GLP_LO;
  }
  else {
    if(low==high) return GLP_FX;
    else return GLP_DB;
  }
}

int BoundTypeToGLP(LinearProgram::BoundType b)
{
  switch(b) {
  case LinearProgram::Free:       return GLP_FR;
  case LinearProgram::LowerBound: return GLP_LO;
  case LinearProgram::UpperBound: return GLP_UP;
  case LinearProgram::Bounded:    return GLP_DB;
  case LinearProgram::Fixed:      return GLP_FX;
  default: abort(); return GLP_FR;
  }
}

void GLPKInterface::Set(const LinearProgram& LP)
{
  SafeDeleteProc(lp,glp_delete_prob);
  lp = glp_create_prob();
  if(LP.minimize) glp_set_obj_dir(lp,GLP_MIN);
  else glp_set_obj_dir(lp,GLP_MAX);

  glp_add_rows(lp,LP.A.m);
  for(int i=0;i<LP.A.m;i++) {
    glp_set_row_bnds(lp,i+1,BoundTypeToGLP(LP.ConstraintType(i)),LP.q(i),LP.p(i));
  }
  glp_add_cols(lp,LP.A.n);
  for(int i=0;i<LP.A.n;i++) {
    glp_set_col_bnds(lp,i+1,BoundTypeToGLP(LP.VariableType(i)),LP.l(i),LP.u(i));
  }
  for(int i=0;i<LP.A.n;i++)
    glp_set_obj_coef(lp,i+1,LP.c(i));

  vector<int> itemp(LP.A.n+1);
  dVector temp(LP.A.n+1);
  for(int i=0;i<LP.A.m;i++) {
    //pick nonzero entries
    int nnz=0;
    for(int j=0;j<LP.A.n;j++) {
      if(!FuzzyZero(LP.A(i,j),kZeroTol)) {
        itemp[nnz+1] = j+1;
        temp(nnz+1) = LP.A(i,j);
        nnz++;
      }
    }
    glp_set_mat_row(lp,i+1,nnz,&itemp[0],temp);
  }
}

void GLPKInterface::Set(const LinearProgram_Sparse& LP)
{
  SafeDeleteProc(lp,glp_delete_prob);
  lp = glp_create_prob();
  if(LP.minimize) glp_set_obj_dir(lp,GLP_MIN);
  else glp_set_obj_dir(lp,GLP_MAX);

  glp_add_rows(lp,LP.A.m);
  for(int i=0;i<LP.A.m;i++) {
    glp_set_row_bnds(lp,i+1,BoundTypeToGLP(LP.ConstraintType(i)),LP.q(i),LP.p(i));
  }
  glp_add_cols(lp,LP.A.n);
  for(int i=0;i<LP.A.n;i++) {
    glp_set_col_bnds(lp,i+1,BoundTypeToGLP(LP.VariableType(i)),LP.l(i),LP.u(i));
  }
  for(int i=0;i<LP.A.n;i++)
    glp_set_obj_coef(lp,i+1,LP.c(i));

  vector<int> itemp(LP.A.n+1);
  dVector temp(LP.A.n+1);
  for(int i=0;i<LP.A.m;i++) {
    //pick nonzero entries
    int nnz=0;
    for(SparseMatrix::RowT::const_iterator j=LP.A.rows[i].begin();j!=LP.A.rows[i].end();j++) {
      if(!FuzzyZero(j->second,kZeroTol)) {
        itemp[nnz+1] = j->first+1;
        temp(nnz+1) = j->second;
        nnz++;
      }
    }
    glp_set_mat_row(lp,i+1,nnz,&itemp[0],temp);
  }
}

void GLPKInterface::Clear()
{
  SafeDeleteProc(lp,glp_delete_prob);
}

void GLPKInterface::Create(int m,int n)
{
  SafeDeleteProc(lp,glp_delete_prob);
  lp = glp_create_prob();
  glp_add_rows(lp,m);
  glp_add_cols(lp,n);
}

void GLPKInterface::SetObjective(const Vector& obj,bool minimize)
{
  for(int i=0;i<obj.n;i++)
    glp_set_obj_coef(lp,i+1,obj(i));
  if(minimize) glp_set_obj_dir(lp,GLP_MIN);
  else glp_set_obj_dir(lp,GLP_MAX);
}

void GLPKInterface::SetRow(int i,const Vector& Ai)
{
  vector<int> itemp(Ai.n+1);
  dVector temp(Ai.n+1);
  //pick nonzero entries
  int nnz=0;
  for(int j=0;j<Ai.n;j++) {
    if(!FuzzyZero(Ai(j),kZeroTol)) {
      itemp[nnz+1] = j+1;
      temp(nnz+1) = Ai(j);
      nnz++;
    }
  }
  glp_set_mat_row(lp,i+1,nnz,&itemp[0],temp);
}

void GLPKInterface::SetRowBounds(int i,Real low,Real high)
{
  glp_set_row_bnds(lp,i+1,BoundType(low,high),low,high);
}

void GLPKInterface::SetVariableBounds(int j,Real low,Real high)
{
  glp_set_col_bnds(lp,j+1,BoundType(low,high),low,high);
}

void GLPKInterface::SetRowBasic(int i)
{
  glp_set_row_stat(lp,i+1,GLP_BS);
}

bool GLPKInterface::GetRowBasic(int i)
{
  return glp_get_row_stat(lp,i+1)==GLP_BS;
}

double GLPKInterface::GetRowDual(int i){
	return glp_get_row_dual(lp, i+1);
}

double GLPKInterface::GetVariableDual(int j){
	return glp_get_col_dual(lp, j+1);
}

void GLPKInterface::SetRowNonBasic(int i,bool upper)
{
  if(upper) glp_set_row_stat(lp,i+1,GLP_NU);
  else glp_set_row_stat(lp,i+1,GLP_NL);
}

void GLPKInterface::SetVariableBasic(int j)
{
  glp_set_col_stat(lp,j+1,GLP_BS);
}

bool GLPKInterface::GetVariableBasic(int j)
{
  return glp_get_col_stat(lp,j+1)==GLP_BS;
}

void GLPKInterface::SetVariableNonBasic(int j,bool upper)
{
  if(upper) glp_set_col_stat(lp,j+1,GLP_NU);
  else glp_set_col_stat(lp,j+1,GLP_NL);
}

int my_gglp_fault_handler(void* info,const char* msg)
{
  printf("GLPK error message %s\n",msg);
  //printf("GLPK fatal error %s\n",msg);
  //printf("jumping...\n");
  //throw(std::runtime_error(msg));
  /*
  printf("GLPK fatal error, dumping!\n");
  GLP* lp=(GLP*)info;
  glp_write_cpxlp(lp,"temp_lp.txt");
  */
  return 0;
}

void my_gglp_fault_handler2(void* info)
{
  printf("GLPK error, quitting\n");
}

struct GLPKInterruptHandler : public SignalHandler
{
public:
  GLPKInterruptHandler(GLPKInterface* _glpk)
    :glpk(_glpk)
  {}

  virtual void OnRaise(int signum)
  {
    printf("Interrupt called during GLPK solve... possible infinite loop\n");
    glp_prob* lp=glpk->lp;
#if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION >= 40)
    glp_write_lp(lp,NULL,"temp_lp.txt");
#endif
    throw(std::runtime_error("Interrupt called during GLPK solve"));
    //exit(-1);
  }

  GLPKInterface* glpk;
};

LinearProgram::Result GLPKInterface::Solve(Vector& xopt)
{
  assert(lp != NULL);
  //glp_write_cpxlp(lp,"temp_lp.txt");
  //glp_print_prob(lp,"temp_lp.txt");
#if GLP_MINOR_VERSION >= 43
  glp_error_hook(my_gglp_fault_handler2,0);
#endif

  glp_smcp params;
  glp_init_smcp(&params);
  params.msg_lev = GLP_MSG_ERR;
  params.presolve = GLP_OFF;

  GLPKInterruptHandler handler(this);
  handler.SetCurrent(SIGINT);
  //handler.SetCurrent(SIGABRT);
  int res;
  try {
    res=glp_simplex(lp,&params);
  }
  catch(const std::exception& e) {
    printf("GLPK internal error: ");
    printf(e.what());
    return LinearProgram::Error;
  }
  catch (...) {
    printf("Unknown error occurred\n");
    return LinearProgram::Error;
  }
#if GLP_MINOR_VERSION >= 43
  glp_error_hook(0,0);
#endif
  handler.UnsetCurrent(SIGINT);
  switch(res) {
  case 0:
    break;
  case GLP_EFAIL:
    cout<<"Error in matrix construction!"<<endl;
    return LinearProgram::Error;
  case GLP_EOBJLL:
    cout<<"Objective reached lower limit!"<<endl;
    return LinearProgram::Error;
  case GLP_EOBJUL:
    cout<<"Objective reached upper limit!"<<endl;
    return LinearProgram::Error;
  case GLP_ENOPFS:
    cout<<"Linear program has no primary feasible solution!"<<endl;
    return LinearProgram::Infeasible;
  case GLP_ENODFS:
    cout<<"Linear program has no dual feasible solution!"<<endl;
    return LinearProgram::Infeasible;
  case GLP_EITLIM:
    cout<<"Max iterations reached!"<<endl;
    return LinearProgram::Error;
  case GLP_ETMLIM:
    cout<<"Time limit reached!"<<endl;
    return LinearProgram::Error;
  case GLP_ESING:
    cout<<"Singularity reached!"<<endl;
    return LinearProgram::Error;
  default:
	  cout<<"Unknown error"<<endl;
	  return LinearProgram::Error;
  }

  int stat=glp_get_status(lp);
  int n=glp_get_num_cols(lp);
  xopt.resize(n);
  for(int i=0;i<n;i++)
    xopt(i) = (Real)glp_get_col_prim(lp,i+1);

  switch(stat) {
  case GLP_OPT:
  case GLP_FEAS:
    return LinearProgram::Feasible;
  case GLP_INFEAS:
  case GLP_NOFEAS:
    return LinearProgram::Infeasible;
  case GLP_UNBND:
    return LinearProgram::Unbounded;
  case GLP_UNDEF:
    cout<<"Solution is undefined!"<<endl;
    return LinearProgram::Error;
  default:
    cout<<"Shouldn't get here!"<<endl;
    return LinearProgram::Error;
  }
}

bool GLPKInterface::Enabled() { return true; }

#else

using namespace Optimization;
using namespace std;

GLPKInterface::GLPKInterface()
{
}

GLPKInterface::~GLPKInterface()
{
}

void GLPKInterface::Set(const LinearProgram& LP)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::Set(const LinearProgram_Sparse& LP)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::Create(int m,int n)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::Clear()
{
}

void GLPKInterface::SetRow(int i,const Vector& Ai)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetRowBounds(int i,Real low,Real high)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetVariableBounds(int j,Real low,Real high)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetRowBasic(int i)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

bool GLPKInterface::GetRowBasic(int i)
{
  cerr<<"Warning, GLPK not defined"<<endl;
  return false;
}

double GLPKInterface::GetRowDual(int i){
  cerr<<"Warning, GLPK not defined"<<endl;
  return 0;
}

void GLPKInterface::SetRowNonBasic(int i,bool upper)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetVariableBasic(int j)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

bool GLPKInterface::GetVariableBasic(int i)
{
  cerr<<"Warning, GLPK not defined"<<endl;
  return false;
}

void GLPKInterface::SetVariableNonBasic(int j,bool upper)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetObjective(const Vector& c,bool minimize)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

LinearProgram::Result GLPKInterface::Solve(Vector& xopt)
{
  cerr<<"Warning, GLPK not defined"<<endl;
  return LinearProgram::Error;
}

bool GLPKInterface::Enabled() { return false; }

void GLPKInterface::SelfTest()
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

#endif //HAVE_GLPK
<commit_msg>Fix compile error from not having GLPK.<commit_after>#include "GLPKInterface.h"
#if HAVE_GLPK

#include <utils.h>
#include <utils/SignalHandler.h>
#include <signal.h>
#include <iostream>
#include <stdexcept>
extern "C"
{
#include <glpk.h>
}
using namespace Optimization;
using namespace std;

#if GLP_MAJOR_VERSION < 4 || GLP_MINOR_VERSION < 20
#error "Require GLPK 4.20 or above"
#endif

const static Real kZeroTol = 1e-6;

GLPKInterface::GLPKInterface()
:lp(NULL)
{}

GLPKInterface::~GLPKInterface()
{
  SafeDeleteProc(lp,glp_delete_prob);
}

inline int BoundType(Real low,Real high)
{
  if(IsInf(low)==-1) {
    if(IsInf(high) == 1) return GLP_FR;
    return GLP_UP;
  }
  else if(IsInf(high) == 1) {
    return GLP_LO;
  }
  else {
    if(low==high) return GLP_FX;
    else return GLP_DB;
  }
}

int BoundTypeToGLP(LinearProgram::BoundType b)
{
  switch(b) {
  case LinearProgram::Free:       return GLP_FR;
  case LinearProgram::LowerBound: return GLP_LO;
  case LinearProgram::UpperBound: return GLP_UP;
  case LinearProgram::Bounded:    return GLP_DB;
  case LinearProgram::Fixed:      return GLP_FX;
  default: abort(); return GLP_FR;
  }
}

void GLPKInterface::Set(const LinearProgram& LP)
{
  SafeDeleteProc(lp,glp_delete_prob);
  lp = glp_create_prob();
  if(LP.minimize) glp_set_obj_dir(lp,GLP_MIN);
  else glp_set_obj_dir(lp,GLP_MAX);

  glp_add_rows(lp,LP.A.m);
  for(int i=0;i<LP.A.m;i++) {
    glp_set_row_bnds(lp,i+1,BoundTypeToGLP(LP.ConstraintType(i)),LP.q(i),LP.p(i));
  }
  glp_add_cols(lp,LP.A.n);
  for(int i=0;i<LP.A.n;i++) {
    glp_set_col_bnds(lp,i+1,BoundTypeToGLP(LP.VariableType(i)),LP.l(i),LP.u(i));
  }
  for(int i=0;i<LP.A.n;i++)
    glp_set_obj_coef(lp,i+1,LP.c(i));

  vector<int> itemp(LP.A.n+1);
  dVector temp(LP.A.n+1);
  for(int i=0;i<LP.A.m;i++) {
    //pick nonzero entries
    int nnz=0;
    for(int j=0;j<LP.A.n;j++) {
      if(!FuzzyZero(LP.A(i,j),kZeroTol)) {
        itemp[nnz+1] = j+1;
        temp(nnz+1) = LP.A(i,j);
        nnz++;
      }
    }
    glp_set_mat_row(lp,i+1,nnz,&itemp[0],temp);
  }
}

void GLPKInterface::Set(const LinearProgram_Sparse& LP)
{
  SafeDeleteProc(lp,glp_delete_prob);
  lp = glp_create_prob();
  if(LP.minimize) glp_set_obj_dir(lp,GLP_MIN);
  else glp_set_obj_dir(lp,GLP_MAX);

  glp_add_rows(lp,LP.A.m);
  for(int i=0;i<LP.A.m;i++) {
    glp_set_row_bnds(lp,i+1,BoundTypeToGLP(LP.ConstraintType(i)),LP.q(i),LP.p(i));
  }
  glp_add_cols(lp,LP.A.n);
  for(int i=0;i<LP.A.n;i++) {
    glp_set_col_bnds(lp,i+1,BoundTypeToGLP(LP.VariableType(i)),LP.l(i),LP.u(i));
  }
  for(int i=0;i<LP.A.n;i++)
    glp_set_obj_coef(lp,i+1,LP.c(i));

  vector<int> itemp(LP.A.n+1);
  dVector temp(LP.A.n+1);
  for(int i=0;i<LP.A.m;i++) {
    //pick nonzero entries
    int nnz=0;
    for(SparseMatrix::RowT::const_iterator j=LP.A.rows[i].begin();j!=LP.A.rows[i].end();j++) {
      if(!FuzzyZero(j->second,kZeroTol)) {
        itemp[nnz+1] = j->first+1;
        temp(nnz+1) = j->second;
        nnz++;
      }
    }
    glp_set_mat_row(lp,i+1,nnz,&itemp[0],temp);
  }
}

void GLPKInterface::Clear()
{
  SafeDeleteProc(lp,glp_delete_prob);
}

void GLPKInterface::Create(int m,int n)
{
  SafeDeleteProc(lp,glp_delete_prob);
  lp = glp_create_prob();
  glp_add_rows(lp,m);
  glp_add_cols(lp,n);
}

void GLPKInterface::SetObjective(const Vector& obj,bool minimize)
{
  for(int i=0;i<obj.n;i++)
    glp_set_obj_coef(lp,i+1,obj(i));
  if(minimize) glp_set_obj_dir(lp,GLP_MIN);
  else glp_set_obj_dir(lp,GLP_MAX);
}

void GLPKInterface::SetRow(int i,const Vector& Ai)
{
  vector<int> itemp(Ai.n+1);
  dVector temp(Ai.n+1);
  //pick nonzero entries
  int nnz=0;
  for(int j=0;j<Ai.n;j++) {
    if(!FuzzyZero(Ai(j),kZeroTol)) {
      itemp[nnz+1] = j+1;
      temp(nnz+1) = Ai(j);
      nnz++;
    }
  }
  glp_set_mat_row(lp,i+1,nnz,&itemp[0],temp);
}

void GLPKInterface::SetRowBounds(int i,Real low,Real high)
{
  glp_set_row_bnds(lp,i+1,BoundType(low,high),low,high);
}

void GLPKInterface::SetVariableBounds(int j,Real low,Real high)
{
  glp_set_col_bnds(lp,j+1,BoundType(low,high),low,high);
}

void GLPKInterface::SetRowBasic(int i)
{
  glp_set_row_stat(lp,i+1,GLP_BS);
}

bool GLPKInterface::GetRowBasic(int i)
{
  return glp_get_row_stat(lp,i+1)==GLP_BS;
}

double GLPKInterface::GetRowDual(int i){
	return glp_get_row_dual(lp, i+1);
}

double GLPKInterface::GetVariableDual(int j){
	return glp_get_col_dual(lp, j+1);
}

void GLPKInterface::SetRowNonBasic(int i,bool upper)
{
  if(upper) glp_set_row_stat(lp,i+1,GLP_NU);
  else glp_set_row_stat(lp,i+1,GLP_NL);
}

void GLPKInterface::SetVariableBasic(int j)
{
  glp_set_col_stat(lp,j+1,GLP_BS);
}

bool GLPKInterface::GetVariableBasic(int j)
{
  return glp_get_col_stat(lp,j+1)==GLP_BS;
}

void GLPKInterface::SetVariableNonBasic(int j,bool upper)
{
  if(upper) glp_set_col_stat(lp,j+1,GLP_NU);
  else glp_set_col_stat(lp,j+1,GLP_NL);
}

int my_gglp_fault_handler(void* info,const char* msg)
{
  printf("GLPK error message %s\n",msg);
  //printf("GLPK fatal error %s\n",msg);
  //printf("jumping...\n");
  //throw(std::runtime_error(msg));
  /*
  printf("GLPK fatal error, dumping!\n");
  GLP* lp=(GLP*)info;
  glp_write_cpxlp(lp,"temp_lp.txt");
  */
  return 0;
}

void my_gglp_fault_handler2(void* info)
{
  printf("GLPK error, quitting\n");
}

struct GLPKInterruptHandler : public SignalHandler
{
public:
  GLPKInterruptHandler(GLPKInterface* _glpk)
    :glpk(_glpk)
  {}

  virtual void OnRaise(int signum)
  {
    printf("Interrupt called during GLPK solve... possible infinite loop\n");
    glp_prob* lp=glpk->lp;
#if GLP_MAJOR_VERSION > 4 || (GLP_MAJOR_VERSION == 4 && GLP_MINOR_VERSION >= 40)
    glp_write_lp(lp,NULL,"temp_lp.txt");
#endif
    throw(std::runtime_error("Interrupt called during GLPK solve"));
    //exit(-1);
  }

  GLPKInterface* glpk;
};

LinearProgram::Result GLPKInterface::Solve(Vector& xopt)
{
  assert(lp != NULL);
  //glp_write_cpxlp(lp,"temp_lp.txt");
  //glp_print_prob(lp,"temp_lp.txt");
#if GLP_MINOR_VERSION >= 43
  glp_error_hook(my_gglp_fault_handler2,0);
#endif

  glp_smcp params;
  glp_init_smcp(&params);
  params.msg_lev = GLP_MSG_ERR;
  params.presolve = GLP_OFF;

  GLPKInterruptHandler handler(this);
  handler.SetCurrent(SIGINT);
  //handler.SetCurrent(SIGABRT);
  int res;
  try {
    res=glp_simplex(lp,&params);
  }
  catch(const std::exception& e) {
    printf("GLPK internal error: ");
    printf(e.what());
    return LinearProgram::Error;
  }
  catch (...) {
    printf("Unknown error occurred\n");
    return LinearProgram::Error;
  }
#if GLP_MINOR_VERSION >= 43
  glp_error_hook(0,0);
#endif
  handler.UnsetCurrent(SIGINT);
  switch(res) {
  case 0:
    break;
  case GLP_EFAIL:
    cout<<"Error in matrix construction!"<<endl;
    return LinearProgram::Error;
  case GLP_EOBJLL:
    cout<<"Objective reached lower limit!"<<endl;
    return LinearProgram::Error;
  case GLP_EOBJUL:
    cout<<"Objective reached upper limit!"<<endl;
    return LinearProgram::Error;
  case GLP_ENOPFS:
    cout<<"Linear program has no primary feasible solution!"<<endl;
    return LinearProgram::Infeasible;
  case GLP_ENODFS:
    cout<<"Linear program has no dual feasible solution!"<<endl;
    return LinearProgram::Infeasible;
  case GLP_EITLIM:
    cout<<"Max iterations reached!"<<endl;
    return LinearProgram::Error;
  case GLP_ETMLIM:
    cout<<"Time limit reached!"<<endl;
    return LinearProgram::Error;
  case GLP_ESING:
    cout<<"Singularity reached!"<<endl;
    return LinearProgram::Error;
  default:
	  cout<<"Unknown error"<<endl;
	  return LinearProgram::Error;
  }

  int stat=glp_get_status(lp);
  int n=glp_get_num_cols(lp);
  xopt.resize(n);
  for(int i=0;i<n;i++)
    xopt(i) = (Real)glp_get_col_prim(lp,i+1);

  switch(stat) {
  case GLP_OPT:
  case GLP_FEAS:
    return LinearProgram::Feasible;
  case GLP_INFEAS:
  case GLP_NOFEAS:
    return LinearProgram::Infeasible;
  case GLP_UNBND:
    return LinearProgram::Unbounded;
  case GLP_UNDEF:
    cout<<"Solution is undefined!"<<endl;
    return LinearProgram::Error;
  default:
    cout<<"Shouldn't get here!"<<endl;
    return LinearProgram::Error;
  }
}

bool GLPKInterface::Enabled() { return true; }

#else

#include <iostream>

using namespace Optimization;
using namespace std;

GLPKInterface::GLPKInterface()
{
}

GLPKInterface::~GLPKInterface()
{
}

void GLPKInterface::Set(const LinearProgram& LP)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::Set(const LinearProgram_Sparse& LP)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::Create(int m,int n)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::Clear()
{
}

void GLPKInterface::SetRow(int i,const Vector& Ai)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetRowBounds(int i,Real low,Real high)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetVariableBounds(int j,Real low,Real high)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetRowBasic(int i)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

bool GLPKInterface::GetRowBasic(int i)
{
  cerr<<"Warning, GLPK not defined"<<endl;
  return false;
}

double GLPKInterface::GetRowDual(int i){
  cerr<<"Warning, GLPK not defined"<<endl;
  return 0;
}

void GLPKInterface::SetRowNonBasic(int i,bool upper)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetVariableBasic(int j)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

bool GLPKInterface::GetVariableBasic(int i)
{
  cerr<<"Warning, GLPK not defined"<<endl;
  return false;
}

void GLPKInterface::SetVariableNonBasic(int j,bool upper)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

void GLPKInterface::SetObjective(const Vector& c,bool minimize)
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

LinearProgram::Result GLPKInterface::Solve(Vector& xopt)
{
  cerr<<"Warning, GLPK not defined"<<endl;
  return LinearProgram::Error;
}

bool GLPKInterface::Enabled() { return false; }

void GLPKInterface::SelfTest()
{
  cerr<<"Warning, GLPK not defined"<<endl;
}

#endif //HAVE_GLPK
<|endoftext|>


<commit_before>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <amr_single_step.h>
#include <fclaw2d_clawpack.H>
#include <fclaw2d_map.h>
#include <p4est_connectivity.h>

#include <amr_forestclaw.H>
#include <amr_utils.H>
#include <fclaw2d_map_query.h>

#include "cubed_sphere_user.H"

int
main (int argc, char **argv)
{
  int			lp;
  int                   example;
  sc_MPI_Comm           mpicomm;
  sc_options_t          *options;
  p4est_connectivity_t  *conn = NULL;
  fclaw2d_map_context_t *cont = NULL;
  fclaw2d_domain_t	*domain = NULL;
  amr_options_t         samr_options, *gparms = &samr_options;
  fclaw2d_clawpack_parms_t* clawpack_parms;

  double scale, theta, phi;
  double rotate[2];

#ifdef TRAPFPE
  printf("Enabling floating point traps\n");
  feenableexcept(FE_INVALID);
#endif

  lp = SC_LP_PRODUCTION;
  mpicomm = sc_MPI_COMM_WORLD;
  fclaw_mpi_init (&argc, &argv, mpicomm, lp);

  /* ---------------------------------------------------------------
     Read in parameters and options
     --------------------------------------------------------------- */
  options = sc_options_new (argv[0]);
  sc_options_add_int (options, 0, "example", &example, 0,
                      "1 for pillow grid, "\
                      "2 for cubed sphere ");

  sc_options_add_double (options, 0, "scale", &scale, 1.0,
                         "Scale unit sphere (e.g. set radius [1])");
  sc_options_add_double (options, 0, "theta", &theta, 0,
                         "Rotation angle theta (degrees) about z axis [0]");

  sc_options_add_double (options, 0, "phi", &phi, 0,
                         "Rotation angle phi (degrees) about x axis [0]");

  /* Read parameters from .ini file */
  gparms = amr_options_new (options); // Sets default values
  clawpack_parms = fclaw2d_clawpack_parms_new(options);

  amr_options_parse (options, argc, argv, lp);  // Reads options from a file

  amr_postprocess_parms (gparms);
  fclaw2d_clawpack_postprocess_parms(clawpack_parms);

  /* Read in clawpack parms, process and check them */
  amr_checkparms (gparms);
  fclaw2d_clawpack_checkparms(clawpack_parms,gparms);

  /* ---------------------------------------------------------------
     Domain geometry
     --------------------------------------------------------------- */

  double pi = M_PI;
  rotate[0] = pi*theta/180.0;
  rotate[1] = pi*phi/180.0;

  switch (example) {
  case 1:
      conn = p4est_connectivity_new_pillow();
      cont = fclaw2d_map_new_pillowsphere(rotate,scale);
      break;
  case 2:
      conn = p4est_connectivity_new_cubed();
      cont = fclaw2d_map_new_cubedsphere(rotate,scale);
      break;
    default:
      sc_abort_collective ("Parameter example must be 1 (pillow sphere) or 2 (cubed sphere)");
  }

  domain = fclaw2d_domain_new_conn_map (mpicomm, gparms->minlevel, conn, cont);

  /* ----------------------------------------------------------
     Set mapping context for Fortran.  The context will now be
     available via get_context(), as a integer*8.  This argument
     will show up as a (fclaw2d_map_context_t**) in C/C++.
     From Fortran, use

     c      # From fortran :
            integer*8 cont
            integer blockno

     c      # .......

            cont = get_context()
            blockno = get_block()

     c      # Call the mapping function
            call fclaw2d_map_c2m(cont,blockno,xc,yc,xp,yp,zp)

     c      # .......

     to retrieve the context.  Note that this is only be used for
     passing the context to a C/C++ routine.  Do not expect to be
     able to access fields of the cont structure.
     ---------------------------------------------------------- */
    SET_CONTEXT(&cont);

  /* ---------------------------------------------------------------
     Print some diagnostics.  TODO: Should this really be in main()?
     --------------------------------------------------------------- */

  if (gparms->verbosity > 0)
  {
      fclaw2d_domain_list_levels(domain, lp);
      fclaw2d_domain_list_neighbors(domain, lp);
  }

  /* ---------------------------------------------------------------
     Set domain data.
     --------------------------------------------------------------- */
  init_domain_data(domain);

  /* Store parameters */
  set_domain_parms(domain,gparms);
  set_clawpack_parms(domain,clawpack_parms);

  /* Link solvers to the domain */
  link_problem_setup(domain,cubed_sphere_problem_setup);

  cubed_sphere_link_solvers(domain);

  /* --------------------------------------------------
     Initialize and run the simulation
     -------------------------------------------------- */
  amrinit(&domain);
  amrrun(&domain);
  amrreset(&domain);

  /* --------------------------------------------------
     Clean up.
     -------------------------------------------------- */
  fclaw2d_map_destroy (cont);
  amr_options_destroy(gparms);
  sc_options_destroy(options);
  fclaw2d_clawpack_parms_delete(clawpack_parms);

  fclaw_mpi_finalize ();

  return 0;
}
<commit_msg>Comments<commit_after>/*
Copyright (c) 2012 Carsten Burstedde, Donna Calhoun
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include <amr_single_step.h>
#include <fclaw2d_clawpack.H>
#include <fclaw2d_map.h>
#include <p4est_connectivity.h>

#include <amr_forestclaw.H>
#include <amr_utils.H>
#include <fclaw2d_map_query.h>

#include "cubed_sphere_user.H"

int
main (int argc, char **argv)
{
  int			lp;
  int                   example;
  sc_MPI_Comm           mpicomm;
  sc_options_t          *options;
  p4est_connectivity_t  *conn = NULL;
  fclaw2d_map_context_t *cont = NULL;
  fclaw2d_domain_t	*domain = NULL;
  amr_options_t         samr_options, *gparms = &samr_options;
  fclaw2d_clawpack_parms_t* clawpack_parms;

  double scale, theta, phi;
  double rotate[2];

#ifdef TRAPFPE
  printf("Enabling floating point traps\n");
  feenableexcept(FE_INVALID);
#endif

  lp = SC_LP_PRODUCTION;
  mpicomm = sc_MPI_COMM_WORLD;
  fclaw_mpi_init (&argc, &argv, mpicomm, lp);

  /* ---------------------------------------------------------------
     Read in parameters and options
     --------------------------------------------------------------- */
  options = sc_options_new (argv[0]);
  sc_options_add_int (options, 0, "example", &example, 0,
                      "1 for pillow grid, "\
                      "2 for cubed sphere ");

  sc_options_add_double (options, 0, "scale", &scale, 1.0,
                         "Scale unit sphere (e.g. set radius [1])");
  sc_options_add_double (options, 0, "theta", &theta, 0,
                         "Rotation angle theta (degrees) about z axis [0]");

  sc_options_add_double (options, 0, "phi", &phi, 0,
                         "Rotation angle phi (degrees) about x axis [0]");

  /* Read parameters from .ini file */
  gparms = amr_options_new (options); // Sets default values
  clawpack_parms = fclaw2d_clawpack_parms_new(options);

  amr_options_parse (options, argc, argv, lp);  // Reads options from a file

  amr_postprocess_parms (gparms);
  fclaw2d_clawpack_postprocess_parms(clawpack_parms);

  /* Read in clawpack parms, process and check them */
  amr_checkparms (gparms);
  fclaw2d_clawpack_checkparms(clawpack_parms,gparms);

  /* ---------------------------------------------------------------
     Domain geometry
     --------------------------------------------------------------- */

  double pi = M_PI;
  rotate[0] = pi*theta/180.0;
  rotate[1] = pi*phi/180.0;

  switch (example) {
  case 1:
      conn = p4est_connectivity_new_pillow();
      cont = fclaw2d_map_new_pillowsphere(rotate,scale);
      break;
  case 2:
      conn = p4est_connectivity_new_cubed();
      cont = fclaw2d_map_new_cubedsphere(rotate,scale);
      break;
    default:
      sc_abort_collective ("Parameter example must be 1 (pillow sphere) or 2 (cubed sphere)");
  }

  domain = fclaw2d_domain_new_conn_map (mpicomm, gparms->minlevel, conn, cont);

  /* ----------------------------------------------------------
     Set mapping context for Fortran.  The context will now be
     available via get_context(), as a integer*8.  This argument
     will show up as a (fclaw2d_map_context_t**) in C/C++.
     From Fortran, use

     c      # From fortran :
            integer*8 cont
            integer blockno

     c      # .......

            cont = get_context()
            blockno = get_block()

     c      # Call the mapping function
            call fclaw2d_map_c2m(cont,blockno,xc,yc,xp,yp,zp)

     c      # .......

     to retrieve the context.  Note that this is only be used for
     passing the context to a C/C++ routine.  Do not expect to be
     able to access fields of the cont structure from Fortran.
     ---------------------------------------------------------- */
    SET_CONTEXT(&cont);

  /* ---------------------------------------------------------------
     Print some diagnostics.  TODO: Should this really be in main()?
     --------------------------------------------------------------- */

  if (gparms->verbosity > 0)
  {
      fclaw2d_domain_list_levels(domain, lp);
      fclaw2d_domain_list_neighbors(domain, lp);
  }

  /* ---------------------------------------------------------------
     Set domain data.
     --------------------------------------------------------------- */
  init_domain_data(domain);

  /* Store parameters */
  set_domain_parms(domain,gparms);
  set_clawpack_parms(domain,clawpack_parms);

  /* Link solvers to the domain */
  link_problem_setup(domain,cubed_sphere_problem_setup);

  cubed_sphere_link_solvers(domain);

  /* --------------------------------------------------
     Initialize and run the simulation
     -------------------------------------------------- */
  amrinit(&domain);
  amrrun(&domain);
  amrreset(&domain);

  /* --------------------------------------------------
     Clean up.
     -------------------------------------------------- */
  fclaw2d_map_destroy (cont);
  amr_options_destroy(gparms);
  sc_options_destroy(options);
  fclaw2d_clawpack_parms_delete(clawpack_parms);

  fclaw_mpi_finalize ();

  return 0;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

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 "paddle/fluid/memory/detail/system_allocator.h"
#include "paddle/fluid/platform/assert.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/platform/gpu_info.h"

#include <stdlib.h>    // for malloc and free
#include <sys/mman.h>  // for mlock and munlock
#include <algorithm>   // for std::max

#include "gflags/gflags.h"

// If use_pinned_memory is true, CPUAllocator calls mlock, which
// returns pinned and locked memory as staging areas for data exchange
// between host and device.  Allocates too much would reduce the amount
// of memory available to the system for paging.  So, by default, we
// should set false to use_pinned_memory.
DEFINE_bool(use_pinned_memory, true, "If set, allocate cpu pinned memory.");
DECLARE_double(fraction_of_gpu_memory_to_use);
namespace paddle {
namespace memory {
namespace detail {

void* CPUAllocator::Alloc(size_t& index, size_t size) {
  // According to http://www.cplusplus.com/reference/cstdlib/malloc/,
  // malloc might not return nullptr if size is zero, but the returned
  // pointer shall not be dereferenced -- so we make it nullptr.
  if (size <= 0) return nullptr;

  index = 0;  // unlock memory

  void* p;

#ifdef PADDLE_WITH_MKLDNN
  // refer to https://github.com/01org/mkl-dnn/blob/master/include/mkldnn.hpp
  // memory alignment
  PADDLE_ENFORCE_EQ(posix_memalign(&p, 4096ul, size), 0);
#else
  PADDLE_ENFORCE_EQ(posix_memalign(&p, 32ul, size), 0);
#endif
  PADDLE_ENFORCE(p, "Fail to allocate CPU memory: size = %d .", size);

  if (p != nullptr) {
    if (FLAGS_use_pinned_memory) {
      index = 1;
      mlock(p, size);  // lock memory
    }
  }

  return p;
}

void CPUAllocator::Free(void* p, size_t size, size_t index) {
  if (p != nullptr && index == 1) {
    munlock(p, size);
  }
  free(p);
}

bool CPUAllocator::UseGpu() const { return false; }

#ifdef PADDLE_WITH_CUDA

void* GPUAllocator::Alloc(size_t& index, size_t size) {
  // CUDA documentation doesn't explain if cudaMalloc returns nullptr
  // if size is 0.  We just make sure it does.
  if (size <= 0) return nullptr;
  void* p;
  cudaError_t result = cudaMalloc(&p, size);
  if (result == cudaSuccess) {
    index = 0;
    gpu_alloc_size_ += size;
    return p;
  } else {
    LOG(WARNING)
        << "Cannot malloc " << size / 1024.0 / 1024.0
        << " MB GPU memory. Please shrink FLAGS_fraction_of_gpu_memory_to_use "
           "environment variable to a lower value. Current value is "
        << FLAGS_fraction_of_gpu_memory_to_use;
    return nullptr;
  }
}

void GPUAllocator::Free(void* p, size_t size, size_t index) {
  cudaError_t err;

  if (index == 0) {
    PADDLE_ASSERT(gpu_alloc_size_ >= size);
    gpu_alloc_size_ -= size;
    err = cudaFree(p);
  } else {
    PADDLE_ASSERT(fallback_alloc_size_ >= size);
    fallback_alloc_size_ -= size;
    err = cudaFreeHost(p);
  }

  // Purposefully allow cudaErrorCudartUnloading, because
  // that is returned if you ever call cudaFree after the
  // driver has already shutdown. This happens only if the
  // process is terminating, in which case we don't care if
  // cudaFree succeeds.
  if (err != cudaErrorCudartUnloading) {
    PADDLE_ENFORCE(err, "cudaFree{Host} failed in GPUAllocator::Free.");
  }
}

bool GPUAllocator::UseGpu() const { return true; }

void* CUDAPinnedAllocator::Alloc(size_t& index, size_t size) {
  if (size <= 0) return nullptr;
  void* p;
  // NOTE: here, we use GpuMaxAllocSize() as the maximum memory size
  // of host pinned allocation. Allocates too much would reduce
  // the amount of memory available to the underlying system for paging.
  // Because the memory is in CPU side, other device can access it too.

  size_t usable = paddle::platform::GpuMaxAllocSize() - fallback_alloc_size_;

  if (size > usable) return nullptr;

  cudaError_t result = cudaMallocHost(&p, size);
  if (result == cudaSuccess) {
    index = 1;
    fallback_alloc_size_ += size;
    return p;
  }

  return nullptr;
}

void CUDAPinnedAllocator::Free(void* p, size_t size, size_t index) {
  cudaError_t err;
  PADDLE_ASSERT(index == 1);

  PADDLE_ASSERT(fallback_alloc_size_ >= size);
  fallback_alloc_size_ -= size;
  err = cudaFreeHost(p);

  // Purposefully allow cudaErrorCudartUnloading, because
  // that is returned if you ever call cudaFreeHost after the
  // driver has already shutdown. This happens only if the
  // process is terminating, in which case we don't care if
  // cudaFreeHost succeeds.
  if (err != cudaErrorCudartUnloading) {
    PADDLE_ENFORCE(err, "cudaFreeHost failed in GPUPinnedAllocator::Free.");
  }
}

bool CUDAPinnedAllocator::UseGpu() const { return true; }

#endif

}  // namespace detail
}  // namespace memory
}  // namespace paddle
<commit_msg>Add note for cudaMallocHost<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

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 "paddle/fluid/memory/detail/system_allocator.h"
#include "paddle/fluid/platform/assert.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/platform/gpu_info.h"

#include <stdlib.h>    // for malloc and free
#include <sys/mman.h>  // for mlock and munlock
#include <algorithm>   // for std::max

#include "gflags/gflags.h"

// If use_pinned_memory is true, CPUAllocator calls mlock, which
// returns pinned and locked memory as staging areas for data exchange
// between host and device.  Allocates too much would reduce the amount
// of memory available to the system for paging.  So, by default, we
// should set false to use_pinned_memory.
DEFINE_bool(use_pinned_memory, true, "If set, allocate cpu pinned memory.");
DECLARE_double(fraction_of_gpu_memory_to_use);
namespace paddle {
namespace memory {
namespace detail {

void* CPUAllocator::Alloc(size_t& index, size_t size) {
  // According to http://www.cplusplus.com/reference/cstdlib/malloc/,
  // malloc might not return nullptr if size is zero, but the returned
  // pointer shall not be dereferenced -- so we make it nullptr.
  if (size <= 0) return nullptr;

  index = 0;  // unlock memory

  void* p;

#ifdef PADDLE_WITH_MKLDNN
  // refer to https://github.com/01org/mkl-dnn/blob/master/include/mkldnn.hpp
  // memory alignment
  PADDLE_ENFORCE_EQ(posix_memalign(&p, 4096ul, size), 0);
#else
  PADDLE_ENFORCE_EQ(posix_memalign(&p, 32ul, size), 0);
#endif
  PADDLE_ENFORCE(p, "Fail to allocate CPU memory: size = %d .", size);

  if (p != nullptr) {
    if (FLAGS_use_pinned_memory) {
      index = 1;
      mlock(p, size);  // lock memory
    }
  }

  return p;
}

void CPUAllocator::Free(void* p, size_t size, size_t index) {
  if (p != nullptr && index == 1) {
    munlock(p, size);
  }
  free(p);
}

bool CPUAllocator::UseGpu() const { return false; }

#ifdef PADDLE_WITH_CUDA

void* GPUAllocator::Alloc(size_t& index, size_t size) {
  // CUDA documentation doesn't explain if cudaMalloc returns nullptr
  // if size is 0.  We just make sure it does.
  if (size <= 0) return nullptr;
  void* p;
  cudaError_t result = cudaMalloc(&p, size);
  if (result == cudaSuccess) {
    index = 0;
    gpu_alloc_size_ += size;
    return p;
  } else {
    LOG(WARNING)
        << "Cannot malloc " << size / 1024.0 / 1024.0
        << " MB GPU memory. Please shrink FLAGS_fraction_of_gpu_memory_to_use "
           "environment variable to a lower value. Current value is "
        << FLAGS_fraction_of_gpu_memory_to_use;
    return nullptr;
  }
}

void GPUAllocator::Free(void* p, size_t size, size_t index) {
  cudaError_t err;

  if (index == 0) {
    PADDLE_ASSERT(gpu_alloc_size_ >= size);
    gpu_alloc_size_ -= size;
    err = cudaFree(p);
  } else {
    PADDLE_ASSERT(fallback_alloc_size_ >= size);
    fallback_alloc_size_ -= size;
    err = cudaFreeHost(p);
  }

  // Purposefully allow cudaErrorCudartUnloading, because
  // that is returned if you ever call cudaFree after the
  // driver has already shutdown. This happens only if the
  // process is terminating, in which case we don't care if
  // cudaFree succeeds.
  if (err != cudaErrorCudartUnloading) {
    PADDLE_ENFORCE(err, "cudaFree{Host} failed in GPUAllocator::Free.");
  }
}

bool GPUAllocator::UseGpu() const { return true; }

// PINNED memory allows direct DMA transfers by the GPU to and from system
// memory. It’s locked to a physical address.
void* CUDAPinnedAllocator::Alloc(size_t& index, size_t size) {
  if (size <= 0) return nullptr;
  void* p;
  // NOTE: here, we use GpuMaxAllocSize() as the maximum memory size
  // of host pinned allocation. Allocates too much would reduce
  // the amount of memory available to the underlying system for paging.

  size_t usable = paddle::platform::GpuMaxAllocSize() - fallback_alloc_size_;

  if (size > usable) return nullptr;

  // PINNED memory is visible to all CUDA contexts.
  cudaError_t result = cudaMallocHost(&p, size);
  if (result == cudaSuccess) {
    index = 1;
    fallback_alloc_size_ += size;
    return p;
  }

  return nullptr;
}

void CUDAPinnedAllocator::Free(void* p, size_t size, size_t index) {
  cudaError_t err;
  PADDLE_ASSERT(index == 1);

  PADDLE_ASSERT(fallback_alloc_size_ >= size);
  fallback_alloc_size_ -= size;
  err = cudaFreeHost(p);

  // Purposefully allow cudaErrorCudartUnloading, because
  // that is returned if you ever call cudaFreeHost after the
  // driver has already shutdown. This happens only if the
  // process is terminating, in which case we don't care if
  // cudaFreeHost succeeds.
  if (err != cudaErrorCudartUnloading) {
    PADDLE_ENFORCE(err, "cudaFreeHost failed in GPUPinnedAllocator::Free.");
  }
}

bool CUDAPinnedAllocator::UseGpu() const { return true; }

#endif

}  // namespace detail
}  // namespace memory
}  // namespace paddle
<|endoftext|>