<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

// This one has to come first (includes the config.h)!
#include <dune/stuff/test/test_common.hh>

#include <memory>
#include <vector>

#include <dune/common/typetraits.hh>

#if HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H
#define ENABLE_ALUGRID 1
#include <dune/grid/alugrid.hh>
#endif
#include <dune/grid/sgrid.hh>
#include <dune/grid/yaspgrid.hh>

#include <dune/grid/part/leaf.hh>

#include <dune/stuff/grid/provider/cube.hh>

#include <dune/gdt/space/continuouslagrange/fem.hh>
#include <dune/gdt/space/continuouslagrange/fem-localfunctions.hh>
#include <dune/gdt/space/discontinuouslagrange/fem-localfunctions.hh>
#include <dune/gdt/mapper/interface.hh>
#include <dune/gdt/basefunctionset/interface.hh>

// +------------------------------------------------+
// | Definition of all possible Grids and GridParts |
// +------------------------------------------------+
typedef Dune::SGrid<1, 1> S1dGridType;
typedef Dune::grid::Part::Leaf::Const<S1dGridType> S1dGridPartType;
typedef Dune::SGrid<2, 2> S2dGridType;
typedef Dune::grid::Part::Leaf::Const<S2dGridType> S2dGridPartType;
typedef Dune::SGrid<3, 3> S3dGridType;
typedef Dune::grid::Part::Leaf::Const<S3dGridType> S3dGridPartType;

typedef Dune::YaspGrid<1> Yasp1dGridType;
typedef Dune::grid::Part::Leaf::Const<Yasp1dGridType> Yasp1dGridPartType;
typedef Dune::YaspGrid<2> Yasp2dGridType;
typedef Dune::grid::Part::Leaf::Const<Yasp2dGridType> Yasp2dGridPartType;
typedef Dune::YaspGrid<3> Yasp3dGridType;
typedef Dune::grid::Part::Leaf::Const<Yasp3dGridType> Yasp3dGridPartType;

#if HAVE_ALUGRID
typedef Dune::ALUConformGrid<2, 2> AluConform2dGridType;
typedef Dune::grid::Part::Leaf::Const<AluConform2dGridType> AluConform2dGridPartType;
typedef Dune::ALUSimplexGrid<2, 2> AluSimplex2dGridType;
typedef Dune::grid::Part::Leaf::Const<AluSimplex2dGridType> AluSimplex2dGridPartType;
typedef Dune::ALUSimplexGrid<3, 3> AluSimplex3dGridType;
typedef Dune::grid::Part::Leaf::Const<AluSimplex3dGridType> AluSimplex3dGridPartType;
typedef Dune::ALUCubeGrid<3, 3> AluCube3dGridType;
typedef Dune::grid::Part::Leaf::Const<AluCube3dGridType> AluCube3dGridPartType;
#endif

typedef testing::
    Types<Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S1dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S1dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S3dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp1dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp1dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp3dGridPartType, 1, double, 3>
#if HAVE_ALUGRID
          ,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluConform2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluConform2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluConform2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex3dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluCube3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluCube3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluCube3dGridPartType, 1, double, 3>

          ,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<S1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<Yasp1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<AluConform2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex3dGridPartType, 1, double, 1>

          ,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<S1dGridPartType, 1, double, 1>,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<Yasp1dGridPartType, 1, double, 1>,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<AluConform2dGridPartType, 1, double, 1>,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex2dGridPartType, 1, double, 1>,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex3dGridPartType, 1, double, 1>
#endif
          > SpaceTypes;

template <class SpaceType>
struct Spaces : public ::testing::Test
{
  typedef typename SpaceType::GridPartType GridPartType;
  typedef typename GridPartType::GridType GridType;
  typedef Dune::Stuff::GridProviderCube<GridType> GridProviderType;

  void static_crtp_check() const
  {
    // grid
    const GridProviderType grid_provider(0.0, 1.0, 4u);
    const auto grid_ptr  = grid_provider.grid();
    const auto grid_part = std::make_shared<const GridPartType>(*grid_ptr);
    // check the space
    const SpaceType space(grid_part);
    // check for static information
    typedef typename SpaceType::Traits Traits;
    typedef typename SpaceType::GridPartType S_GridPartType;
    typedef typename SpaceType::DomainFieldType S_DomainFieldType;
    static const unsigned int s_dimDomain = SpaceType::dimDomain;
    typedef typename SpaceType::RangeFieldType S_RangeFieldType;
    static const unsigned int s_dimRange     = SpaceType::dimRange;
    static const unsigned int s_dimRangeCols = SpaceType::dimRangeCols;
    static const int DUNE_UNUSED(s_polOrder) = SpaceType::polOrder;
    typedef typename SpaceType::BackendType S_BackendType;
    typedef typename SpaceType::MapperType MapperType;
    typedef typename SpaceType::BaseFunctionSetType BaseFunctionSetType;
    typedef typename SpaceType::EntityType EntityType;
    typedef typename SpaceType::PatternType PatternType;
    // check for functionality
    const auto entityIt      = grid_part->template begin<0>();
    const EntityType& entity = *entityIt;
    typedef typename Dune::GDT::SpaceInterface<Traits> SpaceInterfaceType;
    const SpaceInterfaceType& spaceAsInterface = static_cast<const SpaceInterfaceType&>(space);
    const std::shared_ptr<const S_GridPartType> DUNE_UNUSED(s_gridPart) = spaceAsInterface.gridPart();
    const S_BackendType& DUNE_UNUSED(s_backend) = spaceAsInterface.backend();
    const bool DUNE_UNUSED(s_continuous) = spaceAsInterface.continuous();
    const MapperType& mapper                  = spaceAsInterface.mapper();
    const BaseFunctionSetType baseFunctionSet = spaceAsInterface.baseFunctionSet(entity);
    const std::unique_ptr<const PatternType> pattern(spaceAsInterface.computePattern());

    // check the mapper for static information
    typedef typename MapperType::Traits M_Traits;
    typedef typename M_Traits::BackendType M_BackendType;
    // check the mapper for functionality
    typedef Dune::GDT::MapperInterface<M_Traits> MapperInterfaceType;
    const MapperInterfaceType& mapperAsInterface = static_cast<const MapperInterfaceType&>(mapper);
    const M_BackendType& DUNE_UNUSED(m_backend) = mapperAsInterface.backend();
    const size_t m_maxNumDofs = mapperAsInterface.maxNumDofs();
    const size_t DUNE_UNUSED(m_numDofs) = mapperAsInterface.numDofs(entity);
    Dune::DynamicVector<size_t> globalIndices(m_maxNumDofs, size_t(0));
    mapperAsInterface.globalIndices(entity, globalIndices);
    const size_t DUNE_UNUSED(globalIndex) = mapperAsInterface.mapToGlobal(entity, 0);

    // check the basefunctionset for static information
    typedef typename BaseFunctionSetType::Traits B_Traits;
    typedef typename B_Traits::BackendType B_BackendType;
    typedef typename B_Traits::EntityType B_EntityType;
    typedef typename BaseFunctionSetType::DomainType B_DomainType;
    typedef typename BaseFunctionSetType::RangeType B_RangeType;
    typedef typename BaseFunctionSetType::JacobianRangeType B_JacobianRangeType;
    // check the basefunctionset for functionality
    typedef Dune::GDT::
        BaseFunctionSetInterface<B_Traits, S_DomainFieldType, s_dimDomain, S_RangeFieldType, s_dimRange, s_dimRangeCols>
            BaseFunctionSetInterfaceType;
    const BaseFunctionSetInterfaceType& baseFunctionSetAsInterface =
        static_cast<const BaseFunctionSetInterfaceType&>(baseFunctionSet);
    const B_EntityType& DUNE_UNUSED(b_entity) = baseFunctionSetAsInterface.entity();
    const B_BackendType& DUNE_UNUSED(b_backend) = baseFunctionSetAsInterface.backend();
    const size_t b_size = baseFunctionSetAsInterface.size();
    const size_t DUNE_UNUSED(b_order) = baseFunctionSetAsInterface.order();
    const B_DomainType x = entity.geometry().center();
    std::vector<B_RangeType> values(b_size, B_RangeType(0));
    std::vector<B_JacobianRangeType> jacobians(b_size, B_JacobianRangeType(0));
    baseFunctionSetAsInterface.evaluate(x, values);
    baseFunctionSetAsInterface.jacobian(x, jacobians);
  } // ... check()
}; // struct Spaces

TYPED_TEST_CASE(Spaces, SpaceTypes);
TYPED_TEST(Spaces, static_crtp)
{
  this->static_crtp_check();
}

int main(int argc, char** argv)
{
  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
  } catch (Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
}
<commit_msg>[tests.spaces] added tests for continuouslagrange.pdelab<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

// This one has to come first (includes the config.h)!
#include <dune/stuff/test/test_common.hh>

#include <memory>
#include <vector>

#include <dune/common/typetraits.hh>

#if HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H
#define ENABLE_ALUGRID 1
#include <dune/grid/alugrid.hh>
#endif
#include <dune/grid/sgrid.hh>
#include <dune/grid/yaspgrid.hh>

#include <dune/grid/part/leaf.hh>

#include <dune/stuff/grid/provider/cube.hh>

#include <dune/gdt/space/continuouslagrange/fem.hh>
#include <dune/gdt/space/continuouslagrange/pdelab.hh>
#include <dune/gdt/space/continuouslagrange/fem-localfunctions.hh>
#include <dune/gdt/space/discontinuouslagrange/fem-localfunctions.hh>
#include <dune/gdt/mapper/interface.hh>
#include <dune/gdt/basefunctionset/interface.hh>

// +---------------------------------------------------+
// | Definition of all Grids and GridParts of interest |
// +---------------------------------------------------+
typedef Dune::SGrid<1, 1> S1dGridType;
typedef Dune::grid::Part::Leaf::Const<S1dGridType> S1dGridPartType;
typedef Dune::SGrid<2, 2> S2dGridType;
typedef Dune::grid::Part::Leaf::Const<S2dGridType> S2dGridPartType;
typedef Dune::SGrid<3, 3> S3dGridType;
typedef Dune::grid::Part::Leaf::Const<S3dGridType> S3dGridPartType;

typedef Dune::YaspGrid<1> Yasp1dGridType;
typedef Dune::grid::Part::Leaf::Const<Yasp1dGridType> Yasp1dGridPartType;
typedef Dune::YaspGrid<2> Yasp2dGridType;
typedef Dune::grid::Part::Leaf::Const<Yasp2dGridType> Yasp2dGridPartType;
typedef Dune::YaspGrid<3> Yasp3dGridType;
typedef Dune::grid::Part::Leaf::Const<Yasp3dGridType> Yasp3dGridPartType;

#if HAVE_ALUGRID
typedef Dune::ALUConformGrid<2, 2> AluConform2dGridType;
typedef Dune::grid::Part::Leaf::Const<AluConform2dGridType> AluConform2dGridPartType;
typedef Dune::ALUSimplexGrid<2, 2> AluSimplex2dGridType;
typedef Dune::grid::Part::Leaf::Const<AluSimplex2dGridType> AluSimplex2dGridPartType;
typedef Dune::ALUSimplexGrid<3, 3> AluSimplex3dGridType;
typedef Dune::grid::Part::Leaf::Const<AluSimplex3dGridType> AluSimplex3dGridPartType;
typedef Dune::ALUCubeGrid<3, 3> AluCube3dGridType;
typedef Dune::grid::Part::Leaf::Const<AluCube3dGridType> AluCube3dGridPartType;
#endif

typedef testing::
    Types<Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S1dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S1dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<S3dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp1dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp1dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<Yasp3dGridPartType, 1, double, 3>
#if HAVE_ALUGRID
          ,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluConform2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluConform2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluConform2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex2dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex2dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluSimplex3dGridPartType, 1, double, 3>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluCube3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluCube3dGridPartType, 1, double, 2>,
          Dune::GDT::ContinuousLagrangeSpace::FemWrapper<AluCube3dGridPartType, 1, double, 3>
#endif
          ,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<S1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<S2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<S3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<Yasp1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<Yasp2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<Yasp3dGridPartType, 1, double, 1>
#if HAVE_ALUGRID
          ,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<AluConform2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<AluSimplex2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<AluSimplex3dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::PdelabWrapper<AluCube3dGridPartType, 1, double, 1>
#endif
          ,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<S1dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<Yasp1dGridPartType, 1, double, 1>
#ifdef HAVE_ALUGRID
          ,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<AluConform2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex2dGridPartType, 1, double, 1>,
          Dune::GDT::ContinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex3dGridPartType, 1, double, 1>
#endif
          ,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<S1dGridPartType, 1, double, 1>,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<Yasp1dGridPartType, 1, double, 1>
#ifdef HAVE_ALUGRID
          ,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<AluConform2dGridPartType, 1, double, 1>,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex2dGridPartType, 1, double, 1>,
          Dune::GDT::DiscontinuousLagrangeSpace::FemLocalfunctionsWrapper<AluSimplex3dGridPartType, 1, double, 1>
#endif
          > SpaceTypes;

template <class SpaceType>
struct Spaces : public ::testing::Test
{
  typedef typename SpaceType::GridPartType GridPartType;
  typedef typename GridPartType::GridType GridType;
  typedef Dune::Stuff::GridProviderCube<GridType> GridProviderType;

  void crtp_check() const
  {
    // grid
    const GridProviderType grid_provider(0.0, 1.0, 4u);
    const auto grid_ptr  = grid_provider.grid();
    const auto grid_part = std::make_shared<const GridPartType>(*grid_ptr);
    // check the space
    const SpaceType space(grid_part);
    // check for static information
    typedef typename SpaceType::Traits Traits;
    typedef typename SpaceType::GridPartType S_GridPartType;
    typedef typename SpaceType::DomainFieldType S_DomainFieldType;
    static const unsigned int s_dimDomain = SpaceType::dimDomain;
    typedef typename SpaceType::RangeFieldType S_RangeFieldType;
    static const unsigned int s_dimRange     = SpaceType::dimRange;
    static const unsigned int s_dimRangeCols = SpaceType::dimRangeCols;
    static const int DUNE_UNUSED(s_polOrder) = SpaceType::polOrder;
    typedef typename SpaceType::BackendType S_BackendType;
    typedef typename SpaceType::MapperType MapperType;
    typedef typename SpaceType::BaseFunctionSetType BaseFunctionSetType;
    typedef typename SpaceType::EntityType EntityType;
    typedef typename SpaceType::PatternType PatternType;
    // check for functionality
    const auto entityIt      = grid_part->template begin<0>();
    const EntityType& entity = *entityIt;
    typedef typename Dune::GDT::SpaceInterface<Traits> SpaceInterfaceType;
    const SpaceInterfaceType& spaceAsInterface = static_cast<const SpaceInterfaceType&>(space);
    const std::shared_ptr<const S_GridPartType> DUNE_UNUSED(s_gridPart) = spaceAsInterface.gridPart();
    const S_BackendType& DUNE_UNUSED(s_backend) = spaceAsInterface.backend();
    const bool DUNE_UNUSED(s_continuous) = spaceAsInterface.continuous();
    const MapperType& mapper                  = spaceAsInterface.mapper();
    const BaseFunctionSetType baseFunctionSet = spaceAsInterface.baseFunctionSet(entity);
    const std::unique_ptr<const PatternType> pattern(spaceAsInterface.computePattern());

    // check the mapper for static information
    typedef typename MapperType::Traits M_Traits;
    typedef typename M_Traits::BackendType M_BackendType;
    // check the mapper for functionality
    typedef Dune::GDT::MapperInterface<M_Traits> MapperInterfaceType;
    const MapperInterfaceType& mapperAsInterface = static_cast<const MapperInterfaceType&>(mapper);
    const M_BackendType& DUNE_UNUSED(m_backend) = mapperAsInterface.backend();
    const size_t m_maxNumDofs = mapperAsInterface.maxNumDofs();
    const size_t DUNE_UNUSED(m_numDofs) = mapperAsInterface.numDofs(entity);
    Dune::DynamicVector<size_t> globalIndices(m_maxNumDofs, size_t(0));
    mapperAsInterface.globalIndices(entity, globalIndices);
    const size_t DUNE_UNUSED(globalIndex) = mapperAsInterface.mapToGlobal(entity, 0);

    // check the basefunctionset for static information
    typedef typename BaseFunctionSetType::Traits B_Traits;
    typedef typename B_Traits::BackendType B_BackendType;
    typedef typename B_Traits::EntityType B_EntityType;
    typedef typename BaseFunctionSetType::DomainType B_DomainType;
    typedef typename BaseFunctionSetType::RangeType B_RangeType;
    typedef typename BaseFunctionSetType::JacobianRangeType B_JacobianRangeType;
    // check the basefunctionset for functionality
    typedef Dune::GDT::
        BaseFunctionSetInterface<B_Traits, S_DomainFieldType, s_dimDomain, S_RangeFieldType, s_dimRange, s_dimRangeCols>
            BaseFunctionSetInterfaceType;
    const BaseFunctionSetInterfaceType& baseFunctionSetAsInterface =
        static_cast<const BaseFunctionSetInterfaceType&>(baseFunctionSet);
    const B_EntityType& DUNE_UNUSED(b_entity) = baseFunctionSetAsInterface.entity();
    const B_BackendType& DUNE_UNUSED(b_backend) = baseFunctionSetAsInterface.backend();
    const size_t b_size = baseFunctionSetAsInterface.size();
    const size_t DUNE_UNUSED(b_order) = baseFunctionSetAsInterface.order();
    const B_DomainType x = entity.geometry().center();
    std::vector<B_RangeType> values(b_size, B_RangeType(0));
    std::vector<B_JacobianRangeType> jacobians(b_size, B_JacobianRangeType(0));
    baseFunctionSetAsInterface.evaluate(x, values);
    baseFunctionSetAsInterface.jacobian(x, jacobians);
  } // ... crtp_check()
}; // struct Spaces

TYPED_TEST_CASE(Spaces, SpaceTypes);
TYPED_TEST(Spaces, crtp_check)
{
  this->crtp_check();
}

int main(int argc, char** argv)
{
  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
  } catch (Dune::Exception& e) {
    std::cerr << "Dune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
}
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow 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 "tensorflow/compiler/xla/service/hlo_module_config.h"

#include <vector>

#include "tensorflow/compiler/xla/shape_layout.h"
#include "tensorflow/compiler/xla/types.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/lib/strings/strcat.h"

namespace xla {

HloModuleConfig::HloModuleConfig(const ProgramShape& program_shape)
    : entry_computation_layout_(program_shape) {}

string HloModuleConfig::compilation_cache_key() const {
  string key = tensorflow::strings::StrCat("profiling=", hlo_profiling_enabled_,
                                           "::", "hybrid=", has_hybrid_result_);
  tensorflow::strings::StrAppend(&key, "::(");
  std::vector<string> params;
  for (const ShapeLayout& param_layout :
       entry_computation_layout_.parameter_layouts()) {
    params.push_back(param_layout.shape().SerializeAsString());
  }
  tensorflow::strings::StrAppend(
      &key, tensorflow::str_util::Join(params, ", "), ") => ",
      entry_computation_layout_.result_shape().SerializeAsString());
  if (seed_ != 0) {
    // TODO(b/32083678): force recompilation to reset global state.
    static int counter = 0;
    tensorflow::strings::StrAppend(&key, "forcing recompile ", counter++);
  }
  if (replica_count() != 1) {
    tensorflow::strings::StrAppend(&key, "::replica_count=", replica_count());
  }
  return key;
}

}  // namespace xla
<commit_msg>[XLA] Use an atomic int in hlo_module_config.cc for the seed.<commit_after>/* Copyright 2017 The TensorFlow 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 "tensorflow/compiler/xla/service/hlo_module_config.h"

#include <atomic>
#include <vector>

#include "tensorflow/compiler/xla/shape_layout.h"
#include "tensorflow/compiler/xla/types.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/lib/strings/strcat.h"

namespace xla {

HloModuleConfig::HloModuleConfig(const ProgramShape& program_shape)
    : entry_computation_layout_(program_shape) {}

string HloModuleConfig::compilation_cache_key() const {
  string key = tensorflow::strings::StrCat("profiling=", hlo_profiling_enabled_,
                                           "::", "hybrid=", has_hybrid_result_);
  tensorflow::strings::StrAppend(&key, "::(");
  std::vector<string> params;
  for (const ShapeLayout& param_layout :
       entry_computation_layout_.parameter_layouts()) {
    params.push_back(param_layout.shape().SerializeAsString());
  }
  tensorflow::strings::StrAppend(
      &key, tensorflow::str_util::Join(params, ", "), ") => ",
      entry_computation_layout_.result_shape().SerializeAsString());
  if (seed_ != 0) {
    // TODO(b/32083678): force recompilation to reset global state.
    static std::atomic<int> counter{0};
    tensorflow::strings::StrAppend(&key, "forcing recompile ", counter++);
  }
  if (replica_count() != 1) {
    tensorflow::strings::StrAppend(&key, "::replica_count=", replica_count());
  }
  return key;
}

}  // namespace xla
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow 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 "tensorflow/compiler/xla/service/transpose_folding.h"

#include <vector>

#include "tensorflow/compiler/xla/service/dfs_hlo_visitor_with_default.h"
#include "tensorflow/compiler/xla/service/hlo_computation.h"
#include "tensorflow/compiler/xla/service/hlo_instruction.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/status_macros.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/platform/logging.h"

namespace xla {

namespace {

TransposeFolding::OperandIndices CanFoldOperandsIntoDot(
    const HloInstruction& dot,
    const TransposeFolding::TransposableGemmOperandsFn&
        transposable_gemm_operands) {
  if (HloOpcode::kDot != dot.opcode()) {
    return {};
  }

  TransposeFolding::OperandIndices operand_set;
  for (int64 i = 0; i < dot.operand_count(); ++i) {
    auto& operand = *dot.operand(i);
    if (operand.IsRank2Transpose() && operand.user_count() == 1) {
      operand_set.push_back(i);
    }
  }

  return transposable_gemm_operands(dot, operand_set);
}

TransposeFolding::OperandIndices CanFoldOperandsIntoConvolution(
    const HloInstruction& convolution,
    const TransposeFolding::TransposableConvOperandsFn&
        transposable_conv_operands) {
  if (HloOpcode::kConvolution != convolution.opcode()) {
    return {};
  }

  TransposeFolding::OperandIndices operand_set;
  for (int64 i = 0; i < convolution.operand_count(); ++i) {
    auto& operand = *convolution.operand(i);
    if (operand.opcode() == HloOpcode::kTranspose &&
        operand.user_count() == 1) {
      operand_set.push_back(i);
    }
  }

  return transposable_conv_operands(convolution, operand_set);
}

using InstructionOperandsPair =
    std::pair<HloInstruction*, TransposeFolding::OperandIndices>;

// Folds the operands of `dot` that are foldable transposes. `computation` is
// the parent HLO computation of `dot`.
//
// Returns whether the module is changed.
bool FoldTransposeIntoDot(InstructionOperandsPair pair) {
  auto* dot = pair.first;
  std::vector<HloInstruction*> instructions_to_fuse(1, dot);
  for (const int64 operand_index : pair.second) {
    instructions_to_fuse.push_back(dot->mutable_operand(operand_index));
  }

  // Early-exit if no operands are foldable.
  if (instructions_to_fuse.size() == 1) {
    return false;
  }

  dot->parent()->CreateFusionInstruction(
      instructions_to_fuse, HloInstruction::FusionKind::kTransposeDot);
  return true;
}

// Folds the operands of `convolution` that are foldable transposes.
// `computation` is the parent HLO computation of `convolution`.
//
// Returns whether the module is changed.
bool FoldTransposeIntoConvolution(InstructionOperandsPair pair) {
  auto& convolution = *pair.first;
  auto& operand_indices = pair.second;

  if (operand_indices.empty()) {
    return false;
  }

  const ConvolutionDimensionNumbers& dnums =
      convolution.convolution_dimension_numbers();
  ConvolutionDimensionNumbers new_dnums = dnums;

  HloInstruction* new_lhs;
  const int64 kLhsIdx = 0;
  if (std::find(operand_indices.begin(), operand_indices.end(), kLhsIdx) !=
      operand_indices.end()) {
    HloInstruction& transpose = *convolution.mutable_operand(kLhsIdx);
    const auto& transpose_dimensions = transpose.dimensions();
    HloInstruction& transpose_operand = *transpose.mutable_operand(0);

    // Everything remains the same except for the input/output dimension
    // numbers. We need to apply the transpose permutation to the original shape
    // to figure out what the new logical dimensions are.
    new_dnums.set_input_batch_dimension(
        transpose_dimensions[dnums.input_batch_dimension()]);
    new_dnums.set_input_feature_dimension(
        transpose_dimensions[dnums.input_feature_dimension()]);
    for (auto& input_spatial_dimension :
         *new_dnums.mutable_input_spatial_dimensions()) {
      input_spatial_dimension = transpose_dimensions[input_spatial_dimension];
    }
    new_lhs = &transpose_operand;
  } else {
    new_lhs = convolution.mutable_operand(kLhsIdx);
  }

  HloInstruction* new_rhs;
  const int64 kRhsIdx = 1;
  if (std::find(operand_indices.begin(), operand_indices.end(), kRhsIdx) !=
      operand_indices.end()) {
    HloInstruction& transpose = *convolution.mutable_operand(kRhsIdx);
    const auto& transpose_dimensions = transpose.dimensions();
    HloInstruction& transpose_operand = *transpose.mutable_operand(0);

    // Everything remains the same except for the kernel dimension numbers. We
    // need to apply the transpose permutation to the original shape to figure
    // out what the new logical dimensions are.
    new_dnums.set_kernel_input_feature_dimension(
        transpose_dimensions[dnums.kernel_input_feature_dimension()]);
    new_dnums.set_kernel_output_feature_dimension(
        transpose_dimensions[dnums.kernel_output_feature_dimension()]);
    for (auto& kernel_spatial_dimension :
         *new_dnums.mutable_kernel_spatial_dimensions()) {
      kernel_spatial_dimension = transpose_dimensions[kernel_spatial_dimension];
    }
    new_rhs = &transpose_operand;
  } else {
    new_rhs = convolution.mutable_operand(kRhsIdx);
  }

  auto new_conv = HloInstruction::CreateConvolve(
      convolution.shape(), new_lhs, new_rhs, convolution.window(), new_dnums);
  TF_CHECK_OK(convolution.parent()->ReplaceWithNewInstruction(
      &convolution, std::move(new_conv)));

  return true;
}

}  // namespace

TransposeFolding::TransposeFolding(
    TransposableGemmOperandsFn transposable_gemm_operands,
    TransposableConvOperandsFn transposable_conv_operands)
    : transposable_gemm_operands_(std::move(transposable_gemm_operands)),
      transposable_conv_operands_(std::move(transposable_conv_operands)) {}

StatusOr<bool> TransposeFolding::Run(HloModule* module) {
  // Modifying the graph while traversing is dangerous, so we find all folding
  // opportunities before actually folding them.
  std::vector<std::pair<HloInstruction*, OperandIndices>> foldable_dots;
  std::vector<std::pair<HloInstruction*, OperandIndices>> foldable_convolutions;
  auto visit_fn = [this, &foldable_dots,
                   &foldable_convolutions](HloInstruction* instruction) {
    {
      OperandIndices operand_indices =
          CanFoldOperandsIntoDot(*instruction, transposable_gemm_operands_);
      if (!operand_indices.empty()) {
        foldable_dots.emplace_back(instruction, operand_indices);
      }
    }
    {
      OperandIndices operand_indices = CanFoldOperandsIntoConvolution(
          *instruction, transposable_conv_operands_);
      if (!operand_indices.empty()) {
        foldable_convolutions.emplace_back(
            std::make_pair(instruction, operand_indices));
      }
    }
    return tensorflow::Status::OK();
  };

  for (auto* comp : module->MakeNonfusionComputations()) {
    TF_RETURN_IF_ERROR(comp->Accept(visit_fn));
  }

  bool changed = false;
  for (InstructionOperandsPair& pair : foldable_dots) {
    changed |= FoldTransposeIntoDot(pair);
  }
  for (InstructionOperandsPair& pair : foldable_convolutions) {
    changed |= FoldTransposeIntoConvolution(pair);
  }
  return changed;
}

}  // namespace xla
<commit_msg>[XLA] Always fold transposes into convs or dots regardless of use count<commit_after>/* Copyright 2017 The TensorFlow 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 "tensorflow/compiler/xla/service/transpose_folding.h"

#include <vector>

#include "tensorflow/compiler/xla/service/dfs_hlo_visitor_with_default.h"
#include "tensorflow/compiler/xla/service/hlo_computation.h"
#include "tensorflow/compiler/xla/service/hlo_instruction.h"
#include "tensorflow/compiler/xla/shape_util.h"
#include "tensorflow/compiler/xla/status_macros.h"
#include "tensorflow/compiler/xla/util.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/platform/logging.h"

namespace xla {

namespace {

TransposeFolding::OperandIndices CanFoldOperandsIntoDot(
    const HloInstruction& dot,
    const TransposeFolding::TransposableGemmOperandsFn&
        transposable_gemm_operands) {
  if (HloOpcode::kDot != dot.opcode()) {
    return {};
  }

  TransposeFolding::OperandIndices operand_set;
  for (int64 i = 0; i < dot.operand_count(); ++i) {
    auto& operand = *dot.operand(i);
    if (operand.IsRank2Transpose()) {
      operand_set.push_back(i);
    }
  }

  return transposable_gemm_operands(dot, operand_set);
}

TransposeFolding::OperandIndices CanFoldOperandsIntoConvolution(
    const HloInstruction& convolution,
    const TransposeFolding::TransposableConvOperandsFn&
        transposable_conv_operands) {
  if (HloOpcode::kConvolution != convolution.opcode()) {
    return {};
  }

  TransposeFolding::OperandIndices operand_set;
  for (int64 i = 0; i < convolution.operand_count(); ++i) {
    auto& operand = *convolution.operand(i);
    if (operand.opcode() == HloOpcode::kTranspose) {
      operand_set.push_back(i);
    }
  }

  return transposable_conv_operands(convolution, operand_set);
}

using InstructionOperandsPair =
    std::pair<HloInstruction*, TransposeFolding::OperandIndices>;

// Folds the operands of `dot` that are foldable transposes. `computation` is
// the parent HLO computation of `dot`.
//
// Returns whether the module is changed.
bool FoldTransposeIntoDot(InstructionOperandsPair pair) {
  auto* dot = pair.first;
  std::vector<HloInstruction*> instructions_to_fuse(1, dot);
  for (const int64 operand_index : pair.second) {
    instructions_to_fuse.push_back(dot->mutable_operand(operand_index));
  }

  // Early-exit if no operands are foldable.
  if (instructions_to_fuse.size() == 1) {
    return false;
  }

  dot->parent()->CreateFusionInstruction(
      instructions_to_fuse, HloInstruction::FusionKind::kTransposeDot);
  return true;
}

// Folds the operands of `convolution` that are foldable transposes.
// `computation` is the parent HLO computation of `convolution`.
//
// Returns whether the module is changed.
bool FoldTransposeIntoConvolution(InstructionOperandsPair pair) {
  auto& convolution = *pair.first;
  auto& operand_indices = pair.second;

  if (operand_indices.empty()) {
    return false;
  }

  const ConvolutionDimensionNumbers& dnums =
      convolution.convolution_dimension_numbers();
  ConvolutionDimensionNumbers new_dnums = dnums;

  HloInstruction* new_lhs;
  const int64 kLhsIdx = 0;
  if (std::find(operand_indices.begin(), operand_indices.end(), kLhsIdx) !=
      operand_indices.end()) {
    HloInstruction& transpose = *convolution.mutable_operand(kLhsIdx);
    const auto& transpose_dimensions = transpose.dimensions();
    HloInstruction& transpose_operand = *transpose.mutable_operand(0);

    // Everything remains the same except for the input/output dimension
    // numbers. We need to apply the transpose permutation to the original shape
    // to figure out what the new logical dimensions are.
    new_dnums.set_input_batch_dimension(
        transpose_dimensions[dnums.input_batch_dimension()]);
    new_dnums.set_input_feature_dimension(
        transpose_dimensions[dnums.input_feature_dimension()]);
    for (auto& input_spatial_dimension :
         *new_dnums.mutable_input_spatial_dimensions()) {
      input_spatial_dimension = transpose_dimensions[input_spatial_dimension];
    }
    new_lhs = &transpose_operand;
  } else {
    new_lhs = convolution.mutable_operand(kLhsIdx);
  }

  HloInstruction* new_rhs;
  const int64 kRhsIdx = 1;
  if (std::find(operand_indices.begin(), operand_indices.end(), kRhsIdx) !=
      operand_indices.end()) {
    HloInstruction& transpose = *convolution.mutable_operand(kRhsIdx);
    const auto& transpose_dimensions = transpose.dimensions();
    HloInstruction& transpose_operand = *transpose.mutable_operand(0);

    // Everything remains the same except for the kernel dimension numbers. We
    // need to apply the transpose permutation to the original shape to figure
    // out what the new logical dimensions are.
    new_dnums.set_kernel_input_feature_dimension(
        transpose_dimensions[dnums.kernel_input_feature_dimension()]);
    new_dnums.set_kernel_output_feature_dimension(
        transpose_dimensions[dnums.kernel_output_feature_dimension()]);
    for (auto& kernel_spatial_dimension :
         *new_dnums.mutable_kernel_spatial_dimensions()) {
      kernel_spatial_dimension = transpose_dimensions[kernel_spatial_dimension];
    }
    new_rhs = &transpose_operand;
  } else {
    new_rhs = convolution.mutable_operand(kRhsIdx);
  }

  auto new_conv = HloInstruction::CreateConvolve(
      convolution.shape(), new_lhs, new_rhs, convolution.window(), new_dnums);
  TF_CHECK_OK(convolution.parent()->ReplaceWithNewInstruction(
      &convolution, std::move(new_conv)));

  return true;
}

}  // namespace

TransposeFolding::TransposeFolding(
    TransposableGemmOperandsFn transposable_gemm_operands,
    TransposableConvOperandsFn transposable_conv_operands)
    : transposable_gemm_operands_(std::move(transposable_gemm_operands)),
      transposable_conv_operands_(std::move(transposable_conv_operands)) {}

StatusOr<bool> TransposeFolding::Run(HloModule* module) {
  // Modifying the graph while traversing is dangerous, so we find all folding
  // opportunities before actually folding them.
  std::vector<std::pair<HloInstruction*, OperandIndices>> foldable_dots;
  std::vector<std::pair<HloInstruction*, OperandIndices>> foldable_convolutions;
  auto visit_fn = [this, &foldable_dots,
                   &foldable_convolutions](HloInstruction* instruction) {
    {
      OperandIndices operand_indices =
          CanFoldOperandsIntoDot(*instruction, transposable_gemm_operands_);
      if (!operand_indices.empty()) {
        foldable_dots.emplace_back(instruction, operand_indices);
      }
    }
    {
      OperandIndices operand_indices = CanFoldOperandsIntoConvolution(
          *instruction, transposable_conv_operands_);
      if (!operand_indices.empty()) {
        foldable_convolutions.emplace_back(
            std::make_pair(instruction, operand_indices));
      }
    }
    return tensorflow::Status::OK();
  };

  for (auto* comp : module->MakeNonfusionComputations()) {
    TF_RETURN_IF_ERROR(comp->Accept(visit_fn));
  }

  bool changed = false;
  for (InstructionOperandsPair& pair : foldable_dots) {
    changed |= FoldTransposeIntoDot(pair);
  }
  for (InstructionOperandsPair& pair : foldable_convolutions) {
    changed |= FoldTransposeIntoConvolution(pair);
  }
  return changed;
}

}  // namespace xla
<|endoftext|>


<commit_before>#include <Matrix.h>
#include <SteepestDescent.h>
#include <Vector.h>
#include <gtest/gtest.h>

TEST(SteepestDescentTest, Solve4x4LinearSystem)
{
    /* linear system matrix */
    freeaml::Matrix<double> A = {{10.0, -1.0, 2.0, 0.0},
                                 {-1.0, 11.0, -1.0, 3.0},
                                 {2.0, -1.0, 10.0, -1.0},
                                 {0.0, 3.0, -1.0, 8.0}};

    /* solution vector (initially set to zero) */
    freeaml::Vector<double> x = {0.0, 0.0, 0.0, 0.0};

    /* right-hand side */
    freeaml::Vector<double> b = {6.0, 25.0, -11.0, 15.0};

    /*
     * linear system solver: steepest descent
     * maximum number of iterations: 25
     * residual tolerance: 1e-7
     */
    freeaml::SteepestDescent<double> lss(25, 1e-7);

    /* solve the linear system */
    bool status = lss.solve(A, x, b);

    EXPECT_TRUE(status);

    double residual = (A * x - b).l2_norm();

    EXPECT_LE(residual, lss.residual_tolerance());
    EXPECT_LE(lss.num_iterations(), lss.max_iterations());

    /* exact solution */
    freeaml::Vector<double> y = {1.0, 2.0, -1.0, 1.0};

    EXPECT_LE((x - y).l2_norm(), 1.e-7);
}

TEST(SteepestDescentTest, Solve5x5LinearSystem)
{
    /* linear system matrix */
    freeaml::Matrix<double> A = {{5.85, 1.05, 1.80, 0.78, 1.16},
                                 {1.05, 6.52, 0.57, 1.09, 0.34},
                                 {1.80, 0.57, 7.47, 1.01, 1.31},
                                 {0.78, 1.09, 1.01, 4.07, 0.15},
                                 {1.16, 0.34, 1.31, 0.15, 4.37}};

    /* solution vector (initially set to zero) */
    freeaml::Vector<double> x = {0.0, 0.0, 0.0, 0.0, 0.0};

    /* right-hand side */
    freeaml::Vector<double> b = {13.13, 18.15, 3.74, 14.76, 18.46};

    /*
     * linear system solver: steepest descent
     * maximum number of iterations: 40
     * residual tolerance: 1e-8
     */
    freeaml::SteepestDescent<double> lss(40, 1e-8);

    /* solve the linear system */
    bool status = lss.solve(A, x, b);

    EXPECT_TRUE(status);

    double residual = (A * x - b).l2_norm();

    EXPECT_LE(residual, lss.residual_tolerance());
    EXPECT_LE(lss.num_iterations(), lss.max_iterations());

    /* exact solution */
    freeaml::Vector<double> y = {1.0, 2.0, -1.0, 3.0, 4.0};

    EXPECT_LE((x - y).l2_norm(), 1.e-7);
}
<commit_msg>tests steepest descent solver with a sparse matrix as well<commit_after>#include <Matrix.h>
#include <SparseMatrix.h>
#include <SteepestDescent.h>
#include <Vector.h>
#include <gtest/gtest.h>

TEST(SteepestDescentTest, Solve4x4LinearSystem)
{
    /* linear system matrix */
    freeaml::SparseMatrix<double> A = {{10.0, -1.0, 2.0, 0.0},
                                       {-1.0, 11.0, -1.0, 3.0},
                                       {2.0, -1.0, 10.0, -1.0},
                                       {0.0, 3.0, -1.0, 8.0}};

    /* solution vector (initially set to zero) */
    freeaml::Vector<double> x = {0.0, 0.0, 0.0, 0.0};

    /* right-hand side */
    freeaml::Vector<double> b = {6.0, 25.0, -11.0, 15.0};

    /*
     * linear system solver: steepest descent
     * maximum number of iterations: 25
     * residual tolerance: 1e-7
     */
    freeaml::SteepestDescent<double> lss(25, 1e-7);

    /* solve the linear system */
    bool status = lss.solve(A, x, b);

    EXPECT_TRUE(status);

    double residual = (A * x - b).l2_norm();

    EXPECT_LE(residual, lss.residual_tolerance());
    EXPECT_LE(lss.num_iterations(), lss.max_iterations());

    /* exact solution */
    freeaml::Vector<double> y = {1.0, 2.0, -1.0, 1.0};

    EXPECT_LE((x - y).l2_norm(), 1.e-7);
}

TEST(SteepestDescentTest, Solve5x5LinearSystem)
{
    /* linear system matrix */
    freeaml::Matrix<double> A = {{5.85, 1.05, 1.80, 0.78, 1.16},
                                 {1.05, 6.52, 0.57, 1.09, 0.34},
                                 {1.80, 0.57, 7.47, 1.01, 1.31},
                                 {0.78, 1.09, 1.01, 4.07, 0.15},
                                 {1.16, 0.34, 1.31, 0.15, 4.37}};

    /* solution vector (initially set to zero) */
    freeaml::Vector<double> x = {0.0, 0.0, 0.0, 0.0, 0.0};

    /* right-hand side */
    freeaml::Vector<double> b = {13.13, 18.15, 3.74, 14.76, 18.46};

    /*
     * linear system solver: steepest descent
     * maximum number of iterations: 40
     * residual tolerance: 1e-8
     */
    freeaml::SteepestDescent<double> lss(40, 1e-8);

    /* solve the linear system */
    bool status = lss.solve(A, x, b);

    EXPECT_TRUE(status);

    double residual = (A * x - b).l2_norm();

    EXPECT_LE(residual, lss.residual_tolerance());
    EXPECT_LE(lss.num_iterations(), lss.max_iterations());

    /* exact solution */
    freeaml::Vector<double> y = {1.0, 2.0, -1.0, 3.0, 4.0};

    EXPECT_LE((x - y).l2_norm(), 1.e-7);
}
<|endoftext|>


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

#include "net/test/test_server.h"

#include <windows.h>
#include <wincrypt.h>

#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_handle.h"

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

namespace {

// Writes |size| bytes to |handle| and sets |*unblocked| to true.
// Used as a crude timeout mechanism by ReadData().
void UnblockPipe(HANDLE handle, DWORD size, bool* unblocked) {
  std::string unblock_data(size, '\0');
  // Unblock the ReadFile in TestServer::WaitToStart by writing to the pipe.
  // Make sure the call succeeded, otherwise we are very likely to hang.
  DWORD bytes_written = 0;
  LOG(WARNING) << "Timeout reached; unblocking pipe by writing "
               << size << " bytes";
  CHECK(WriteFile(handle, unblock_data.data(), size, &bytes_written,
                  NULL));
  CHECK_EQ(size, bytes_written);
  *unblocked = true;
}

// Given a file handle, reads into |buffer| until |bytes_max| bytes
// has been read or an error has been encountered.  Returns
// true if the read was successful.
bool ReadData(HANDLE read_fd, HANDLE write_fd,
              DWORD bytes_max, uint8* buffer) {
  base::Thread thread("test_server_watcher");
  if (!thread.Start())
    return false;

  // Prepare a timeout in case the server fails to start.
  bool unblocked = false;
  thread.message_loop()->PostDelayedTask(
      FROM_HERE,
      NewRunnableFunction(UnblockPipe, write_fd, bytes_max, &unblocked),
      TestTimeouts::action_timeout_ms());

  DWORD bytes_read = 0;
  while (bytes_read < bytes_max) {
    DWORD num_bytes;
    if (!ReadFile(read_fd, buffer + bytes_read, bytes_max - bytes_read,
                  &num_bytes, NULL)) {
      PLOG(ERROR) << "ReadFile failed";
      return false;
    }
    if (num_bytes <= 0) {
      LOG(ERROR) << "ReadFile returned invalid byte count: " << num_bytes;
      return false;
    }
    bytes_read += num_bytes;
  }

  thread.Stop();
  // If the timeout kicked in, abort.
  if (unblocked) {
    LOG(ERROR) << "Timeout exceeded for ReadData";
    return false;
  }

  return true;
}

}  // namespace

namespace net {

bool TestServer::LaunchPython(const FilePath& testserver_path) {
  FilePath python_exe;
  if (!PathService::Get(base::DIR_SOURCE_ROOT, &python_exe))
    return false;
  python_exe = python_exe
      .Append(FILE_PATH_LITERAL("third_party"))
      .Append(FILE_PATH_LITERAL("python_26"))
      .Append(FILE_PATH_LITERAL("python.exe"));

  CommandLine python_command(python_exe);
  python_command.AppendArgPath(testserver_path);
  if (!AddCommandLineArguments(&python_command))
    return false;

  HANDLE child_read = NULL;
  HANDLE child_write = NULL;
  if (!CreatePipe(&child_read, &child_write, NULL, 0)) {
    PLOG(ERROR) << "Failed to create pipe";
    return false;
  }
  child_read_fd_.Set(child_read);
  child_write_fd_.Set(child_write);

  // Have the child inherit the write half.
  if (!SetHandleInformation(child_write, HANDLE_FLAG_INHERIT,
                            HANDLE_FLAG_INHERIT)) {
    PLOG(ERROR) << "Failed to enable pipe inheritance";
    return false;
  }

  // Pass the handle on the command-line. Although HANDLE is a
  // pointer, truncating it on 64-bit machines is okay. See
  // http://msdn.microsoft.com/en-us/library/aa384203.aspx
  //
  // "64-bit versions of Windows use 32-bit handles for
  // interoperability. When sharing a handle between 32-bit and 64-bit
  // applications, only the lower 32 bits are significant, so it is
  // safe to truncate the handle (when passing it from 64-bit to
  // 32-bit) or sign-extend the handle (when passing it from 32-bit to
  // 64-bit)."
  python_command.AppendArg("--startup-pipe=" +
      base::IntToString(reinterpret_cast<uintptr_t>(child_write)));

  job_handle_.Set(CreateJobObject(NULL, NULL));
  if (!job_handle_.IsValid()) {
    LOG(ERROR) << "Could not create JobObject.";
    return false;
  }

  JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0};
  limit_info.BasicLimitInformation.LimitFlags =
      JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
  if (0 == SetInformationJobObject(job_handle_.Get(),
    JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info))) {
    LOG(ERROR) << "Could not SetInformationJobObject.";
    return false;
  }

  base::LaunchOptions launch_options;
  launch_options.inherit_handles = true;
  launch_options.job_handle = job_handle_.Get();
  if (!base::LaunchProcess(python_command, launch_options, &process_handle_)) {
    LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString();
    return false;
  }

  return true;
}

bool TestServer::WaitToStart() {
  base::win::ScopedHandle read_fd(child_read_fd_.Take());
  base::win::ScopedHandle write_fd(child_write_fd_.Take());

  uint32 server_data_len = 0;
  if (!ReadData(read_fd.Get(), write_fd.Get(), sizeof(server_data_len),
                reinterpret_cast<uint8*>(&server_data_len))) {
    LOG(ERROR) << "Could not read server_data_len";
    DebugBreakProcess(process_handle_);
    return false;
  }
  std::string server_data(server_data_len, '\0');
  if (!ReadData(read_fd.Get(), write_fd.Get(), server_data_len,
                reinterpret_cast<uint8*>(&server_data[0]))) {
    LOG(ERROR) << "Could not read server_data (" << server_data_len
               << " bytes)";
    return false;
  }

  if (!ParseServerData(server_data)) {
    LOG(ERROR) << "Could not parse server_data: " << server_data;
    return false;
  }

  return true;
}

}  // namespace net
<commit_msg>Restore test server launch timeout to 45 secs.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/test/test_server.h"

#include <windows.h>
#include <wincrypt.h>

#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_handle.h"

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

namespace {

// Writes |size| bytes to |handle| and sets |*unblocked| to true.
// Used as a crude timeout mechanism by ReadData().
void UnblockPipe(HANDLE handle, DWORD size, bool* unblocked) {
  std::string unblock_data(size, '\0');
  // Unblock the ReadFile in TestServer::WaitToStart by writing to the pipe.
  // Make sure the call succeeded, otherwise we are very likely to hang.
  DWORD bytes_written = 0;
  LOG(WARNING) << "Timeout reached; unblocking pipe by writing "
               << size << " bytes";
  CHECK(WriteFile(handle, unblock_data.data(), size, &bytes_written,
                  NULL));
  CHECK_EQ(size, bytes_written);
  *unblocked = true;
}

// Given a file handle, reads into |buffer| until |bytes_max| bytes
// has been read or an error has been encountered.  Returns
// true if the read was successful.
bool ReadData(HANDLE read_fd, HANDLE write_fd,
              DWORD bytes_max, uint8* buffer) {
  base::Thread thread("test_server_watcher");
  if (!thread.Start())
    return false;

  // Prepare a timeout in case the server fails to start.
  bool unblocked = false;
  thread.message_loop()->PostDelayedTask(
      FROM_HERE,
      NewRunnableFunction(UnblockPipe, write_fd, bytes_max, &unblocked),
      45000);

  DWORD bytes_read = 0;
  while (bytes_read < bytes_max) {
    DWORD num_bytes;
    if (!ReadFile(read_fd, buffer + bytes_read, bytes_max - bytes_read,
                  &num_bytes, NULL)) {
      PLOG(ERROR) << "ReadFile failed";
      return false;
    }
    if (num_bytes <= 0) {
      LOG(ERROR) << "ReadFile returned invalid byte count: " << num_bytes;
      return false;
    }
    bytes_read += num_bytes;
  }

  thread.Stop();
  // If the timeout kicked in, abort.
  if (unblocked) {
    LOG(ERROR) << "Timeout exceeded for ReadData";
    return false;
  }

  return true;
}

}  // namespace

namespace net {

bool TestServer::LaunchPython(const FilePath& testserver_path) {
  FilePath python_exe;
  if (!PathService::Get(base::DIR_SOURCE_ROOT, &python_exe))
    return false;
  python_exe = python_exe
      .Append(FILE_PATH_LITERAL("third_party"))
      .Append(FILE_PATH_LITERAL("python_26"))
      .Append(FILE_PATH_LITERAL("python.exe"));

  CommandLine python_command(python_exe);
  python_command.AppendArgPath(testserver_path);
  if (!AddCommandLineArguments(&python_command))
    return false;

  HANDLE child_read = NULL;
  HANDLE child_write = NULL;
  if (!CreatePipe(&child_read, &child_write, NULL, 0)) {
    PLOG(ERROR) << "Failed to create pipe";
    return false;
  }
  child_read_fd_.Set(child_read);
  child_write_fd_.Set(child_write);

  // Have the child inherit the write half.
  if (!SetHandleInformation(child_write, HANDLE_FLAG_INHERIT,
                            HANDLE_FLAG_INHERIT)) {
    PLOG(ERROR) << "Failed to enable pipe inheritance";
    return false;
  }

  // Pass the handle on the command-line. Although HANDLE is a
  // pointer, truncating it on 64-bit machines is okay. See
  // http://msdn.microsoft.com/en-us/library/aa384203.aspx
  //
  // "64-bit versions of Windows use 32-bit handles for
  // interoperability. When sharing a handle between 32-bit and 64-bit
  // applications, only the lower 32 bits are significant, so it is
  // safe to truncate the handle (when passing it from 64-bit to
  // 32-bit) or sign-extend the handle (when passing it from 32-bit to
  // 64-bit)."
  python_command.AppendArg("--startup-pipe=" +
      base::IntToString(reinterpret_cast<uintptr_t>(child_write)));

  job_handle_.Set(CreateJobObject(NULL, NULL));
  if (!job_handle_.IsValid()) {
    LOG(ERROR) << "Could not create JobObject.";
    return false;
  }

  JOBOBJECT_EXTENDED_LIMIT_INFORMATION limit_info = {0};
  limit_info.BasicLimitInformation.LimitFlags =
      JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
  if (0 == SetInformationJobObject(job_handle_.Get(),
    JobObjectExtendedLimitInformation, &limit_info, sizeof(limit_info))) {
    LOG(ERROR) << "Could not SetInformationJobObject.";
    return false;
  }

  base::LaunchOptions launch_options;
  launch_options.inherit_handles = true;
  launch_options.job_handle = job_handle_.Get();
  if (!base::LaunchProcess(python_command, launch_options, &process_handle_)) {
    LOG(ERROR) << "Failed to launch " << python_command.GetCommandLineString();
    return false;
  }

  return true;
}

bool TestServer::WaitToStart() {
  base::win::ScopedHandle read_fd(child_read_fd_.Take());
  base::win::ScopedHandle write_fd(child_write_fd_.Take());

  uint32 server_data_len = 0;
  if (!ReadData(read_fd.Get(), write_fd.Get(), sizeof(server_data_len),
                reinterpret_cast<uint8*>(&server_data_len))) {
    LOG(ERROR) << "Could not read server_data_len";
    return false;
  }
  std::string server_data(server_data_len, '\0');
  if (!ReadData(read_fd.Get(), write_fd.Get(), server_data_len,
                reinterpret_cast<uint8*>(&server_data[0]))) {
    LOG(ERROR) << "Could not read server_data (" << server_data_len
               << " bytes)";
    return false;
  }

  if (!ParseServerData(server_data)) {
    LOG(ERROR) << "Could not parse server_data: " << server_data;
    return false;
  }

  return true;
}

}  // namespace net
<|endoftext|>


<commit_before>#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QTimer>

#include <QtDBus/QtDBus>

#include <QtTest/QtTest>

class TestDoNothing : public QObject
{
    Q_OBJECT

public:
    TestDoNothing(QObject *parent = 0)
        : QObject(parent), mLoop(new QEventLoop(this))
    { }

private:
    QEventLoop *mLoop;

private slots:
    void initTestCase();
    void init();

    void doNothing();
    void doNothing2();

    void cleanup();
    void cleanupTestCase();
};

void TestDoNothing::initTestCase()
{
  QVERIFY(QDBusConnection::sessionBus().isConnected());
}

void TestDoNothing::init()
{
}

void TestDoNothing::doNothing()
{
  QTimer::singleShot(0, mLoop, SLOT(quit()));
  QCOMPARE(mLoop->exec(), 0);
}

void TestDoNothing::doNothing2()
{
  QTimer::singleShot(0, mLoop, SLOT(quit()));
  QCOMPARE(mLoop->exec(), 0);
}

void TestDoNothing::cleanup()
{
}

void TestDoNothing::cleanupTestCase()
{
}

QTEST_MAIN(TestDoNothing)

#include "_gen/do-nothing.cpp.moc.hpp"
<commit_msg>Changed tests/dbus/do-nothing.cpp to inherit Test.<commit_after>#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QTimer>

#include <QtDBus/QtDBus>

#include <QtTest/QtTest>

#include <tests/lib/test.h>

class TestDoNothing : public Test
{
    Q_OBJECT

public:
    TestDoNothing(QObject *parent = 0)
        : Test(parent)
    { }

private slots:
    void initTestCase();
    void init();

    void doNothing();
    void doNothing2();

    void cleanup();
    void cleanupTestCase();
};

void TestDoNothing::initTestCase()
{
    initTestCaseImpl();
}

void TestDoNothing::init()
{
    initImpl();
}

void TestDoNothing::doNothing()
{
    QTimer::singleShot(0, mLoop, SLOT(quit()));
    QCOMPARE(mLoop->exec(), 0);
}

void TestDoNothing::doNothing2()
{
    QTimer::singleShot(0, mLoop, SLOT(quit()));
    QCOMPARE(mLoop->exec(), 0);
}

void TestDoNothing::cleanup()
{
    cleanupImpl();
}

void TestDoNothing::cleanupTestCase()
{
    cleanupTestCaseImpl();
}

QTEST_MAIN(TestDoNothing)
#include "_gen/do-nothing.cpp.moc.hpp"
<|endoftext|>


<commit_before>#include <QtCore/QDebug>
#include <QtCore/QTimer>

#include <QtDBus/QtDBus>

#include <QtTest/QtTest>

#define TP_QT_ENABLE_LOWLEVEL_API

#include <TelepathyQt/ChannelFactory>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ConnectionLowlevel>
#include <TelepathyQt/ContactFactory>
#include <TelepathyQt/PendingChannel>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/Debug>

#include <telepathy-glib/dbus.h>
#include <telepathy-glib/debug.h>
#include <telepathy-glib/svc-generic.h>

#include <tests/lib/glib/contacts-conn.h>
#include <tests/lib/test.h>

using namespace Tp;

class TestProperties : public Test
{
    Q_OBJECT

public:
    TestProperties(QObject *parent = 0)
        : Test(parent), mConnService(0)
    { }

private Q_SLOTS:
    void initTestCase();
    void init();

    void testPropertiesMonitoring();
    void testPropertiesMonitoringFailure();

    void cleanup();
    void cleanupTestCase();

private:
    QString mConnName, mConnPath;
    TpTestsContactsConnection *mConnService;
    Client::ConnectionInterface *mConn;
};

void TestProperties::initTestCase()
{
    initTestCaseImpl();

    g_type_init();
    g_set_prgname("properties");
    tp_debug_set_flags("all");
    dbus_g_bus_get(DBUS_BUS_STARTER, 0);
}

void TestProperties::init()
{
    initImpl();

    gchar *name;
    gchar *connPath;
    GError *error = 0;

    mConnService = TP_TESTS_CONTACTS_CONNECTION(g_object_new(
            TP_TESTS_TYPE_CONTACTS_CONNECTION,
            "account", "me@example.com",
            "protocol", "contacts",
            NULL));
    QVERIFY(mConnService != 0);
    QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService),
                "contacts", &name, &connPath, &error));
    QVERIFY(error == 0);

    QVERIFY(name != 0);
    QVERIFY(connPath != 0);

    mConnName = QLatin1String(name);
    mConnPath = QLatin1String(connPath);

    g_free(name);
    g_free(connPath);

    mConn = new Client::ConnectionInterface(mConnName, mConnPath,
            this);

    QVERIFY(mConn->isValid());
}

void TestProperties::testPropertiesMonitoring()
{
    QCOMPARE(mConn->isMonitoringProperties(), false);
    mConn->setMonitorProperties(true);

    QSignalSpy spy(mConn, SIGNAL(propertiesChanged(QVariantMap,QStringList)));
    connect(mConn, SIGNAL(propertiesChanged(QVariantMap,QStringList)),
            mLoop, SLOT(quit()));

    GHashTable *changed = tp_asv_new(
                "test-prop", G_TYPE_STRING, "I am actually different than I used to be.",
                "test-again", G_TYPE_UINT, 0xff0000ffU,
                NULL
                );

    tp_svc_dbus_properties_emit_properties_changed (mConnService,
            mConn->interface().toAscii().data(), changed, NULL);

    mLoop->exec();

    QCOMPARE(spy.count(), 1);

    QList<QVariant> arguments = spy.takeFirst();
    QVERIFY(arguments.at(0).type() == QVariant::Map);
    QVERIFY(arguments.at(1).type() == QVariant::StringList);

    QVariantMap resultMap = arguments.at(0).toMap();
    QCOMPARE(resultMap.size(), 2);
    QCOMPARE(resultMap[QLatin1String("test-prop")].toString(), QLatin1String("I am actually different than I used to be."));
    QCOMPARE(resultMap[QLatin1String("test-again")].toUInt(), 0xff0000ffU);

    tp_svc_dbus_properties_emit_properties_changed (mConnService,
            "a.random.interface", changed, NULL);

    QCOMPARE(spy.count(), 0);

    g_hash_table_destroy (changed);
}

void TestProperties::testPropertiesMonitoringFailure()
{
    QCOMPARE(mConn->isMonitoringProperties(), false);

    QSignalSpy spy(mConn, SIGNAL(propertiesChanged(QMap<QString,QVariant>,QStringList)));

    GHashTable *changed = tp_asv_new(
                "test-prop", G_TYPE_STRING, "I am actually different than I used to be.",
                "test-again", G_TYPE_UINT, 0xff0000ffU,
                NULL
                );

    tp_svc_dbus_properties_emit_properties_changed (mConnService,
            mConn->interface().toAscii().data(), changed, NULL);

    QCOMPARE(spy.count(), 0);

    g_hash_table_destroy (changed);
}

void TestProperties::cleanup()
{
    cleanupImpl();
}

void TestProperties::cleanupTestCase()
{
    cleanupTestCaseImpl();
}

QTEST_MAIN(TestProperties)
#include "_gen/properties.cpp.moc.hpp"
<commit_msg>monitor-properties: Check the invalid interface before the other one<commit_after>#include <QtCore/QDebug>
#include <QtCore/QTimer>

#include <QtDBus/QtDBus>

#include <QtTest/QtTest>

#define TP_QT_ENABLE_LOWLEVEL_API

#include <TelepathyQt/ChannelFactory>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ConnectionLowlevel>
#include <TelepathyQt/ContactFactory>
#include <TelepathyQt/PendingChannel>
#include <TelepathyQt/PendingReady>
#include <TelepathyQt/Debug>

#include <telepathy-glib/dbus.h>
#include <telepathy-glib/debug.h>
#include <telepathy-glib/svc-generic.h>

#include <tests/lib/glib/contacts-conn.h>
#include <tests/lib/test.h>

using namespace Tp;

class TestProperties : public Test
{
    Q_OBJECT

public:
    TestProperties(QObject *parent = 0)
        : Test(parent), mConnService(0)
    { }

private Q_SLOTS:
    void initTestCase();
    void init();

    void testPropertiesMonitoring();
    void testPropertiesMonitoringFailure();

    void cleanup();
    void cleanupTestCase();

private:
    QString mConnName, mConnPath;
    TpTestsContactsConnection *mConnService;
    Client::ConnectionInterface *mConn;
};

void TestProperties::initTestCase()
{
    initTestCaseImpl();

    g_type_init();
    g_set_prgname("properties");
    tp_debug_set_flags("all");
    dbus_g_bus_get(DBUS_BUS_STARTER, 0);
}

void TestProperties::init()
{
    initImpl();

    gchar *name;
    gchar *connPath;
    GError *error = 0;

    mConnService = TP_TESTS_CONTACTS_CONNECTION(g_object_new(
            TP_TESTS_TYPE_CONTACTS_CONNECTION,
            "account", "me@example.com",
            "protocol", "contacts",
            NULL));
    QVERIFY(mConnService != 0);
    QVERIFY(tp_base_connection_register(TP_BASE_CONNECTION(mConnService),
                "contacts", &name, &connPath, &error));
    QVERIFY(error == 0);

    QVERIFY(name != 0);
    QVERIFY(connPath != 0);

    mConnName = QLatin1String(name);
    mConnPath = QLatin1String(connPath);

    g_free(name);
    g_free(connPath);

    mConn = new Client::ConnectionInterface(mConnName, mConnPath,
            this);

    QVERIFY(mConn->isValid());
}

void TestProperties::testPropertiesMonitoring()
{
    QCOMPARE(mConn->isMonitoringProperties(), false);
    mConn->setMonitorProperties(true);

    QSignalSpy spy(mConn, SIGNAL(propertiesChanged(QVariantMap,QStringList)));
    connect(mConn, SIGNAL(propertiesChanged(QVariantMap,QStringList)),
            mLoop, SLOT(quit()));

    GHashTable *changed = tp_asv_new(
                "test-prop", G_TYPE_STRING, "I am actually different than I used to be.",
                "test-again", G_TYPE_UINT, 0xff0000ffU,
                NULL
                );

    tp_svc_dbus_properties_emit_properties_changed (mConnService,
            "a.random.interface", changed, NULL);

    tp_svc_dbus_properties_emit_properties_changed (mConnService,
            mConn->interface().toAscii().data(), changed, NULL);

    QCOMPARE(spy.count(), 0);

    mLoop->exec();

    QCOMPARE(spy.count(), 1);

    QList<QVariant> arguments = spy.takeFirst();
    QVERIFY(arguments.at(0).type() == QVariant::Map);
    QVERIFY(arguments.at(1).type() == QVariant::StringList);

    QVariantMap resultMap = arguments.at(0).toMap();
    QCOMPARE(resultMap.size(), 2);
    QCOMPARE(resultMap[QLatin1String("test-prop")].toString(), QLatin1String("I am actually different than I used to be."));
    QCOMPARE(resultMap[QLatin1String("test-again")].toUInt(), 0xff0000ffU);

    QCOMPARE(spy.count(), 0);

    g_hash_table_destroy (changed);
}

void TestProperties::testPropertiesMonitoringFailure()
{
    QCOMPARE(mConn->isMonitoringProperties(), false);

    QSignalSpy spy(mConn, SIGNAL(propertiesChanged(QMap<QString,QVariant>,QStringList)));

    GHashTable *changed = tp_asv_new(
                "test-prop", G_TYPE_STRING, "I am actually different than I used to be.",
                "test-again", G_TYPE_UINT, 0xff0000ffU,
                NULL
                );

    tp_svc_dbus_properties_emit_properties_changed (mConnService,
            mConn->interface().toAscii().data(), changed, NULL);

    QCOMPARE(spy.count(), 0);

    g_hash_table_destroy (changed);
}

void TestProperties::cleanup()
{
    cleanupImpl();
}

void TestProperties::cleanupTestCase()
{
    cleanupTestCaseImpl();
}

QTEST_MAIN(TestProperties)
#include "_gen/properties.cpp.moc.hpp"
<|endoftext|>


<commit_before>/*
  Copyright (C) 2005-2021 Steven L. Scott

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

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

  You should have received a copy of the GNU Lesser General Public License along
  with this library; if not, write to the Free Software Foundation, Inc., 51
  Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/

#include "numopt/linear_assignment/lap.h"

#include "LinAlg/Matrix.hpp"
#include "LinAlg/Vector.hpp"

namespace BOOM {

  // A solver for the linear assignment problem.  Given a square matrix of costs
  // describing how much it will cost row[i] to perform the task in column j,
  // and under the constraint that all tasks must be performed by exactly one
  // row, find the permutation of the indices {0, ..., dim - 1} (call it ans),
  // so that the minimum costs is achieved if row j performs task ans[j].
  class LinearAssignment {
   public:

    // Args:
    //   cost_matrix: Element (i, j) is the cost if row i performs task j.
    LinearAssignment(const Matrix &cost_matrix) {
      cost_matrix_ = cost_matrix;
    }

    // Args:
    //   assignment: The total cost of assigning task assignment[i] to worker i
    //     (summed over i).
    double cost(const std::vector<int> &assignment) const {
      double ans = 0;
      for (size_t i = 0; i < assignment.size(); ++i) {
        ans += cost_matrix_(i, assignment[i]);
      }
      return ans;
    }

    // Find the optimal solution.
    double solve() {
      int dim = cost_matrix_.nrow();
      row_solution_.resize(dim);
      col_solution_.resize(dim);
      Vector row_dual_variables(dim);
      Vector col_dual_variables(dim);

      Matrix cost = cost_matrix_.transpose();

      return lap(
          cost.nrow(),
          cost.data(),
          row_solution_.data(),
          col_solution_.data(),
          row_dual_variables.data(),
          col_dual_variables.data());
    }

    // The optimal assignment of tasks to workers.  Assigning task
    // row_solution[j] to worker j minimizes cost.
    const std::vector<long> &row_solution() {return row_solution_;}

    // The optimal assignment of workers to tasks.  Assigning task j to
    // col_solution[j] minimizes costs.
    const std::vector<long> &col_solution() {return col_solution_;}

   private:
    Matrix cost_matrix_;
    std::vector<long> row_solution_;
    std::vector<long> col_solution_;
  };

}  // namespace BOOM
<commit_msg>Add include guards.<commit_after>#ifndef BOOM_NUMOPT_LINEAR_ASSIGNMENT_HPP_
#define BOOM_NUMOPT_LINEAR_ASSIGNMENT_HPP_
/*
  Copyright (C) 2005-2021 Steven L. Scott

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

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

  You should have received a copy of the GNU Lesser General Public License along
  with this library; if not, write to the Free Software Foundation, Inc., 51
  Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/

#include "numopt/linear_assignment/lap.h"

#include "LinAlg/Matrix.hpp"
#include "LinAlg/Vector.hpp"

namespace BOOM {

  // A solver for the linear assignment problem.  Given a square matrix of costs
  // describing how much it will cost row[i] to perform the task in column j,
  // and under the constraint that all tasks must be performed by exactly one
  // row, find the permutation of the indices {0, ..., dim - 1} (call it ans),
  // so that the minimum costs is achieved if row j performs task ans[j].
  class LinearAssignment {
   public:

    // Args:
    //   cost_matrix: Element (i, j) is the cost if row i performs task j.
    explicit LinearAssignment(const Matrix &cost_matrix)
        : cost_matrix_(cost_matrix)
    {}

    // Args:
    //   assignment: The total cost of assigning task assignment[i] to worker i
    //     (summed over i).
    double cost(const std::vector<int> &assignment) const {
      double ans = 0;
      for (size_t i = 0; i < assignment.size(); ++i) {
        ans += cost_matrix_(i, assignment[i]);
      }
      return ans;
    }

    // Find the optimal solution.
    double solve() {
      int dim = cost_matrix_.nrow();
      row_solution_.resize(dim);
      col_solution_.resize(dim);
      Vector row_dual_variables(dim);
      Vector col_dual_variables(dim);

      Matrix cost = cost_matrix_.transpose();

      return lap(
          cost.nrow(),
          cost.data(),
          row_solution_.data(),
          col_solution_.data(),
          row_dual_variables.data(),
          col_dual_variables.data());
    }

    // The optimal assignment of tasks to workers.  Assigning task
    // row_solution[j] to worker j minimizes cost.
    const std::vector<long> &row_solution() {return row_solution_;}

    // The optimal assignment of workers to tasks.  Assigning task j to
    // col_solution[j] minimizes costs.
    const std::vector<long> &col_solution() {return col_solution_;}

   private:
    Matrix cost_matrix_;
    std::vector<long> row_solution_;
    std::vector<long> col_solution_;
  };

}  // namespace BOOM
#endif // BOOM_NUMOPT_LINEAR_ASSIGNMENT_HPP_
<|endoftext|>


<commit_before>/*
 * testSoruceActor.cpp
 *
 *  Created on: 13 okt. 2015
 *      Author: Daniel
 */

#include "gtest/gtest.h"
#include "../src/CalvinInProgress/SourceActor.h"

class testSourceActor : public ::testing::Test {
protected:
	virtual void SetUp() {}
	virtual void TearDown() {}
};

TEST(testSoruceActor,testSetup)
{
	SourceActor mini;
	EXPECT_EQ(0,mini.actorInit());
}

TEST(testSourceActor,testIntFifo){
	SourceActor mini;
	intFifo testFifo;
	mini.initFifo(&testFifo);
	EXPECT_EQ(SUCCESS,mini.fifoAdd(&testFifo,1337));
	EXPECT_EQ(1337,mini.fifoPop(&testFifo));
}

<commit_msg>Integer fifo added<commit_after>/*
 * testSoruceActor.cpp
 *
 *  Created on: 13 okt. 2015
 *      Author: Daniel
 */

#include "gtest/gtest.h"
#include "../src/CalvinInProgress/SourceActor.h"

class testSourceActor : public ::testing::Test {
protected:
	virtual void SetUp() {}
	virtual void TearDown() {}
};

TEST(testSoruceActor,testSetup)
{
	SourceActor mini;
	EXPECT_EQ(0,mini.actorInit());
}

TEST(testSourceActor,testIntFifo){
	SourceActor mini;
	intFifo testFifo;
	mini.initFifo(&testFifo);
	EXPECT_EQ(SUCCESS,mini.fifoAdd(&testFifo,1337));
	EXPECT_EQ(1337,mini.fifoPop(&testFifo));

	EXPECT_EQ(FAIL,mini.fifoPop(&testFifo));

	for(int i = 0; i < 7; i++){
		EXPECT_EQ(SUCCESS,mini.fifoAdd(&testFifo,i));
	}
	EXPECT_EQ(FAIL,mini.fifoAdd(&testFifo,1337));

	for(int i = 0; i < 7; i++){
			EXPECT_EQ(i,mini.fifoPop(&testFifo));
	}

}

<|endoftext|>


<commit_before>/*
 * SchemeEval.c
 *
 * Simple scheme evaluator
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_GUILE

#include "SchemeEval.h"

#include <libguile.h>
#include <libguile/backtrace.h>
#include <libguile/debug.h>
#include <libguile/lang.h>
#include <pthread.h>

#include <opencog/util/platform.h>
#include "SchemeSmob.h"

using namespace opencog;

void SchemeEval::init(void)
{
	SchemeSmob::init();

	outport = scm_open_output_string();
	scm_set_current_output_port(outport);

	pending_input = false;
	caught_error = false;
	input_line = "";
	error_string_port = SCM_EOL;
	captured_stack = SCM_BOOL_F;
	pexpr = NULL;
}

void * SchemeEval::c_wrap_init(void *p)
{
	SchemeEval *self = (SchemeEval *) p;
	self->init();
	return self;
}

#define WORK_AROUND_GUILE_185_BUG
#ifdef WORK_AROUND_GUILE_185_BUG
void * SchemeEval::c_wrap_init_bogus(void *p)
{
	scm_c_eval_string ("(+ 2 2)\n");
	return p;
}
void * SchemeEval::c_wrap_init_thread(void *p)
{
	scm_with_guile(c_wrap_init_bogus, p);
	return p;
}

/* We need to bounce to a different thread, in order to work around
 * a guile bug (as of 1.8.5) where current-module is wrong, and
 * simply saying "(set-current-module the-root-module)" is not enough
 * to fix it.
 */
#endif /* WORK_AROUND_GUILE_185_BUG */

SchemeEval::SchemeEval(void)
{
#ifdef WORK_AROUND_GUILE_185_BUG
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_t t;
	pthread_create(&t, &attr, c_wrap_init_thread, this);
	pthread_join(t, NULL);
#endif
	scm_with_guile(c_wrap_init, this);
}

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

std::string SchemeEval::prt(SCM node)
{
	if (SCM_SMOB_PREDICATE(SchemeSmob::cog_handle_tag, node))
	{
		return SchemeSmob::handle_to_string(node);
	}

	else if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, node))
	{
		return SchemeSmob::misc_to_string(node);
	}

	else if (scm_is_eq(node, SCM_UNSPECIFIED))
	{
		return "";
	}
#if CUSTOM_PRINTING_WHY_DO_WE_HAVE_THIS_DELETE_ME
	else if (scm_is_pair(node))
	{
		std::string str = "(";
      SCM node_list = node;
		const char * sp = "";
      do
      {
			str += sp;
			sp = " ";
         node = SCM_CAR (node_list);
         str += prt (node);
         node_list = SCM_CDR (node_list);
      }
      while (scm_is_pair(node_list));

		// Print the rest -- the CDR part
		if (!scm_is_null(node_list))
		{
			str += " . ";
			str += prt (node_list);
		}
		str += ")";
		return str;
   }
	else if (scm_is_true(scm_symbol_p(node)))
	{
		node = scm_symbol_to_string(node);
		char * str = scm_to_locale_string(node);
		// std::string rv = "'";  // print the symbol escape
		std::string rv = "";      // err .. don't print it
		rv += str;
		free(str);
		return rv;
	}
	else if (scm_is_true(scm_string_p(node)))
	{
		char * str = scm_to_locale_string(node);
		std::string rv = "\"";
		rv += str;
		rv += "\"";
		free(str);
		return rv;
	}
	else if (scm_is_number(node))
	{
		#define NUMBUFSZ 60
		char buff[NUMBUFSZ];
		if (scm_is_signed_integer(node, INT_MIN, INT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%ld", (long) scm_to_long(node));
		}
		else if (scm_is_unsigned_integer(node, 0, UINT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%lu", (unsigned long) scm_to_ulong(node));
		}
		else if (scm_is_real(node))
		{
			snprintf (buff, NUMBUFSZ, "%g", scm_to_double(node));
		}
		else if (scm_is_complex(node))
		{
			snprintf (buff, NUMBUFSZ, "%g +i %g",
				scm_c_real_part(node),
				scm_c_imag_part(node));
		}
		else if (scm_is_rational(node))
		{
			std::string rv;
			rv = prt(scm_numerator(node));
			rv += "/";
			rv += prt(scm_denominator(node));
			return rv;
		}
		return buff;
	}
	else if (scm_is_true(scm_char_p(node)))
	{
		std::string rv;
		rv = (char) scm_to_char(node);
		return rv;
	}
	else if (scm_is_true(scm_boolean_p(node)))
	{
		if (scm_to_bool(node)) return "#t";
		return "#f";
	}
	else if (SCM_NULL_OR_NIL_P(node))
	{
		// scm_is_null(x) is true when x is SCM_EOL
		// SCM_NILP(x) is true when x is SCM_ELISP_NIL
		return "()";
	}
	else if (scm_is_eq(node, SCM_UNDEFINED))
	{
		return "undefined";
	}
	else if (scm_is_eq(node, SCM_EOF_VAL))
	{
		return "eof";
	}
#endif
	else
	{
		// Let SCM display do the rest of the work.
		SCM port = scm_open_output_string();
		scm_display (node, port);
		SCM rc = scm_get_output_string(port);
		char * str = scm_to_locale_string(rc);
		std::string rv = str;
		free(str);
		scm_close_port(port);
		return rv;
	}

	return "";
}

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

SCM SchemeEval::preunwind_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->preunwind_handler(tag, throw_args);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->catch_handler(tag, throw_args);
}

SCM SchemeEval::preunwind_handler (SCM tag, SCM throw_args)
{
	// We can only record the stack before it is unwound.
	// The normal catch handler body runs only *after* the stack
	// has been unwound.
	captured_stack = scm_make_stack (SCM_BOOL_T, SCM_EOL);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler (SCM tag, SCM throw_args)
{
	// Check for read error. If a read error, then wait for user to correct it.
	SCM re = scm_symbol_to_string(tag);
	char * restr = scm_to_locale_string(re);
	pending_input = false;
	if (0 == strcmp(restr, "read-error"))
	{
		pending_input = true;
		free(restr);
		return SCM_EOL;
	}

	// If its not a read error, then its a regular error; report it.
	caught_error = true;

	/* get string port into which we write the error message and stack. */
	error_string_port = scm_open_output_string();
	SCM port = error_string_port;

	if (scm_is_true(scm_list_p(throw_args)) && (scm_ilength(throw_args) >= 1))
	{
		long nargs = scm_ilength(throw_args);
		SCM subr    = SCM_CAR (throw_args);
		SCM message = SCM_EOL;
		if (nargs >= 2)
			message = SCM_CADR (throw_args);
		SCM parts   = SCM_EOL;
		if (nargs >= 3)
			parts   = SCM_CADDR (throw_args);
		SCM rest    = SCM_EOL;
		if (nargs >= 4)
			rest    = SCM_CADDDR (throw_args);

		if (scm_is_true (captured_stack))
		{
			SCM highlights;

			if (scm_is_eq (tag, scm_arg_type_key) ||
			    scm_is_eq (tag, scm_out_of_range_key))
				highlights = rest;
			else
				highlights = SCM_EOL;

			scm_puts ("Backtrace:\n", port);
			scm_display_backtrace_with_highlights (captured_stack, port,
			      SCM_BOOL_F, SCM_BOOL_F, highlights);
			scm_newline (port);
		}
		scm_display_error (captured_stack, port, subr, message, parts, rest);
	}
	else
	{
		scm_puts ("ERROR: thow args are unexpectedly short!\n", port);
	}
	scm_puts("ABORT: ", port);
	scm_puts(restr, port);
	free(restr);

	return SCM_BOOL_F;
}

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

/**
 * Evaluate the expression
 */
std::string SchemeEval::eval(const std::string &expr)
{
	pexpr = &expr;
	scm_with_guile(c_wrap_eval, this);
	return answer;
}

void * SchemeEval::c_wrap_eval(void * p)
{
	SchemeEval *self = (SchemeEval *) p;
	self->answer = self->do_eval(*(self->pexpr));
	return self;
}

std::string SchemeEval::do_eval(const std::string &expr)
{
	// XXX This is a defacto string buffer copy, could probably be avoided
	// in most cases. FIXME.  i.e. no copy needed when no peding input.
	input_line += expr;

	caught_error = false;
	pending_input = false;
#if 0
	SCM rc = scm_internal_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this);
#endif
	captured_stack = SCM_BOOL_F;
	SCM rc = scm_c_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this,
	            SchemeEval::preunwind_handler_wrapper, this);

	if (pending_input)
	{
		return "";
	}
	pending_input = false;
	input_line = "";

	if (caught_error)
	{
		std::string rv;
		rc = scm_get_output_string(error_string_port);
		char * str = scm_to_locale_string(rc);
		rv = str;
		free(str);
		scm_close_port(error_string_port);
		error_string_port = SCM_EOL;
		captured_stack = SCM_BOOL_F;

		scm_truncate_file(outport, scm_from_uint16(0));

		rv += "\n";
		return rv;
	}
	else
	{
		std::string rv;
		// First, we get the contents of the output port,
		// and pass that on.
		SCM out = scm_get_output_string(outport);
		char * str = scm_to_locale_string(out);
		rv = str;
		free(str);
		scm_truncate_file(outport, scm_from_uint16(0));

		// Next, we append the "interpreter" output
		rv += prt(rc);
		rv += "\n";

		return rv;
	}
	return "#<Error: Unreachable statement reached>";
}

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

/**
 * Return true if the expression was incomplete, and more is expected
 * (for example, more closing parens are expected)
 */
bool SchemeEval::input_pending(void)
{
	return pending_input;
}

/**
 * Return true if an error occured during the evaluation of the expression
 */
bool SchemeEval::eval_error(void)
{
	return caught_error;
}

/**
 * Clear the error state, the input buffers, etc.
 */
void SchemeEval::clear_pending(void)
{
	input_line = "";
	pending_input = false;
	caught_error = false;
}

#endif
/* ===================== END OF FILE ============================ */
<commit_msg>Work around another guile-1.8.5 threading bug.<commit_after>/*
 * SchemeEval.c
 *
 * Simple scheme evaluator
 * Copyright (c) 2008 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_GUILE

#include "SchemeEval.h"

#include <libguile.h>
#include <libguile/backtrace.h>
#include <libguile/debug.h>
#include <libguile/lang.h>
#include <pthread.h>

#include <opencog/util/platform.h>
#include "SchemeSmob.h"

using namespace opencog;

void SchemeEval::init(void)
{
	SchemeSmob::init();

	outport = scm_open_output_string();
	scm_set_current_output_port(outport);

	pending_input = false;
	caught_error = false;
	input_line = "";
	error_string_port = SCM_EOL;
	captured_stack = SCM_BOOL_F;
	pexpr = NULL;
}

void * SchemeEval::c_wrap_init(void *p)
{
	SchemeEval *self = (SchemeEval *) p;
	self->init();
	return self;
}

#define WORK_AROUND_GUILE_185_BUG
#ifdef WORK_AROUND_GUILE_185_BUG
void * SchemeEval::c_wrap_init_bogus(void *p)
{
	scm_c_eval_string ("(+ 2 2)\n");
	return p;
}
void * SchemeEval::c_wrap_init_thread(void *p)
{
	scm_with_guile(c_wrap_init_bogus, p);
	return p;
}

/* We need to bounce to a different thread, in order to work around
 * a guile bug (as of 1.8.5) where current-module is wrong, and
 * simply saying "(set-current-module the-root-module)" is not enough
 * to fix it.
 */
#endif /* WORK_AROUND_GUILE_185_BUG */

SchemeEval::SchemeEval(void)
{
#ifdef WORK_AROUND_GUILE_185_BUG
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_t t;
	pthread_create(&t, &attr, c_wrap_init_thread, this);
	pthread_join(t, NULL);
#endif
	scm_with_guile(c_wrap_init, this);
}

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

std::string SchemeEval::prt(SCM node)
{
	if (SCM_SMOB_PREDICATE(SchemeSmob::cog_handle_tag, node))
	{
		return SchemeSmob::handle_to_string(node);
	}

	else if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, node))
	{
		return SchemeSmob::misc_to_string(node);
	}

	else if (scm_is_eq(node, SCM_UNSPECIFIED))
	{
		return "";
	}
#if CUSTOM_PRINTING_WHY_DO_WE_HAVE_THIS_DELETE_ME
	else if (scm_is_pair(node))
	{
		std::string str = "(";
      SCM node_list = node;
		const char * sp = "";
      do
      {
			str += sp;
			sp = " ";
         node = SCM_CAR (node_list);
         str += prt (node);
         node_list = SCM_CDR (node_list);
      }
      while (scm_is_pair(node_list));

		// Print the rest -- the CDR part
		if (!scm_is_null(node_list))
		{
			str += " . ";
			str += prt (node_list);
		}
		str += ")";
		return str;
   }
	else if (scm_is_true(scm_symbol_p(node)))
	{
		node = scm_symbol_to_string(node);
		char * str = scm_to_locale_string(node);
		// std::string rv = "'";  // print the symbol escape
		std::string rv = "";      // err .. don't print it
		rv += str;
		free(str);
		return rv;
	}
	else if (scm_is_true(scm_string_p(node)))
	{
		char * str = scm_to_locale_string(node);
		std::string rv = "\"";
		rv += str;
		rv += "\"";
		free(str);
		return rv;
	}
	else if (scm_is_number(node))
	{
		#define NUMBUFSZ 60
		char buff[NUMBUFSZ];
		if (scm_is_signed_integer(node, INT_MIN, INT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%ld", (long) scm_to_long(node));
		}
		else if (scm_is_unsigned_integer(node, 0, UINT_MAX))
		{
			snprintf (buff, NUMBUFSZ, "%lu", (unsigned long) scm_to_ulong(node));
		}
		else if (scm_is_real(node))
		{
			snprintf (buff, NUMBUFSZ, "%g", scm_to_double(node));
		}
		else if (scm_is_complex(node))
		{
			snprintf (buff, NUMBUFSZ, "%g +i %g",
				scm_c_real_part(node),
				scm_c_imag_part(node));
		}
		else if (scm_is_rational(node))
		{
			std::string rv;
			rv = prt(scm_numerator(node));
			rv += "/";
			rv += prt(scm_denominator(node));
			return rv;
		}
		return buff;
	}
	else if (scm_is_true(scm_char_p(node)))
	{
		std::string rv;
		rv = (char) scm_to_char(node);
		return rv;
	}
	else if (scm_is_true(scm_boolean_p(node)))
	{
		if (scm_to_bool(node)) return "#t";
		return "#f";
	}
	else if (SCM_NULL_OR_NIL_P(node))
	{
		// scm_is_null(x) is true when x is SCM_EOL
		// SCM_NILP(x) is true when x is SCM_ELISP_NIL
		return "()";
	}
	else if (scm_is_eq(node, SCM_UNDEFINED))
	{
		return "undefined";
	}
	else if (scm_is_eq(node, SCM_EOF_VAL))
	{
		return "eof";
	}
#endif
	else
	{
		// Let SCM display do the rest of the work.
		SCM port = scm_open_output_string();
		scm_display (node, port);
		SCM rc = scm_get_output_string(port);
		char * str = scm_to_locale_string(rc);
		std::string rv = str;
		free(str);
		scm_close_port(port);
		return rv;
	}

	return "";
}

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

SCM SchemeEval::preunwind_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->preunwind_handler(tag, throw_args);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler_wrapper (void *data, SCM tag, SCM throw_args)
{
	SchemeEval *ss = (SchemeEval *)data;
	return ss->catch_handler(tag, throw_args);
}

SCM SchemeEval::preunwind_handler (SCM tag, SCM throw_args)
{
	// We can only record the stack before it is unwound.
	// The normal catch handler body runs only *after* the stack
	// has been unwound.
	captured_stack = scm_make_stack (SCM_BOOL_T, SCM_EOL);
	return SCM_EOL;
}

SCM SchemeEval::catch_handler (SCM tag, SCM throw_args)
{
	// Check for read error. If a read error, then wait for user to correct it.
	SCM re = scm_symbol_to_string(tag);
	char * restr = scm_to_locale_string(re);
	pending_input = false;
	if (0 == strcmp(restr, "read-error"))
	{
		pending_input = true;
		free(restr);
		return SCM_EOL;
	}

	// If its not a read error, then its a regular error; report it.
	caught_error = true;

	/* get string port into which we write the error message and stack. */
	error_string_port = scm_open_output_string();
	SCM port = error_string_port;

	if (scm_is_true(scm_list_p(throw_args)) && (scm_ilength(throw_args) >= 1))
	{
		long nargs = scm_ilength(throw_args);
		SCM subr    = SCM_CAR (throw_args);
		SCM message = SCM_EOL;
		if (nargs >= 2)
			message = SCM_CADR (throw_args);
		SCM parts   = SCM_EOL;
		if (nargs >= 3)
			parts   = SCM_CADDR (throw_args);
		SCM rest    = SCM_EOL;
		if (nargs >= 4)
			rest    = SCM_CADDDR (throw_args);

		if (scm_is_true (captured_stack))
		{
			SCM highlights;

			if (scm_is_eq (tag, scm_arg_type_key) ||
			    scm_is_eq (tag, scm_out_of_range_key))
				highlights = rest;
			else
				highlights = SCM_EOL;

			scm_puts ("Backtrace:\n", port);
			scm_display_backtrace_with_highlights (captured_stack, port,
			      SCM_BOOL_F, SCM_BOOL_F, highlights);
			scm_newline (port);
		}
		scm_display_error (captured_stack, port, subr, message, parts, rest);
	}
	else
	{
		scm_puts ("ERROR: thow args are unexpectedly short!\n", port);
	}
	scm_puts("ABORT: ", port);
	scm_puts(restr, port);
	free(restr);

	return SCM_BOOL_F;
}

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

/**
 * Evaluate the expression
 */
std::string SchemeEval::eval(const std::string &expr)
{
	pexpr = &expr;
	scm_with_guile(c_wrap_eval, this);
	return answer;
}

void * SchemeEval::c_wrap_eval(void * p)
{
	SchemeEval *self = (SchemeEval *) p;
	self->answer = self->do_eval(*(self->pexpr));
	return self;
}

std::string SchemeEval::do_eval(const std::string &expr)
{
	// XXX This is a defacto string buffer copy, could probably be avoided
	// in most cases. FIXME.  i.e. no copy needed when no peding input.
	input_line += expr;

#define GUIL_185_CURRENT_PORT_BUG
#ifdef GUIL_185_CURRENT_PORT_BUG
	// It appears that guile-1.8.5 looses track of the current port
	// setting with each new thread. So, for every new thread, we
	// need to set this.  Doing this on every call has some performance
	// impact.
	scm_set_current_output_port(outport);
#endif

	caught_error = false;
	pending_input = false;
#if 0
	SCM rc = scm_internal_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this);
#endif
	captured_stack = SCM_BOOL_F;
	SCM rc = scm_c_catch (SCM_BOOL_T,
	            (scm_t_catch_body) scm_c_eval_string, (void *) input_line.c_str(),
	            SchemeEval::catch_handler_wrapper, this,
	            SchemeEval::preunwind_handler_wrapper, this);

	if (pending_input)
	{
		return "";
	}
	pending_input = false;
	input_line = "";

	if (caught_error)
	{
		std::string rv;
		rc = scm_get_output_string(error_string_port);
		char * str = scm_to_locale_string(rc);
		rv = str;
		free(str);
		scm_close_port(error_string_port);
		error_string_port = SCM_EOL;
		captured_stack = SCM_BOOL_F;

		scm_truncate_file(outport, scm_from_uint16(0));

		rv += "\n";
		return rv;
	}
	else
	{
		std::string rv;
		// First, we get the contents of the output port,
		// and pass that on.
		SCM out = scm_get_output_string(outport);
		char * str = scm_to_locale_string(out);
		rv = str;
		free(str);
		scm_truncate_file(outport, scm_from_uint16(0));

		// Next, we append the "interpreter" output
		rv += prt(rc);
		rv += "\n";

		return rv;
	}
	return "#<Error: Unreachable statement reached>";
}

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

/**
 * Return true if the expression was incomplete, and more is expected
 * (for example, more closing parens are expected)
 */
bool SchemeEval::input_pending(void)
{
	return pending_input;
}

/**
 * Return true if an error occured during the evaluation of the expression
 */
bool SchemeEval::eval_error(void)
{
	return caught_error;
}

/**
 * Clear the error state, the input buffers, etc.
 */
void SchemeEval::clear_pending(void)
{
	input_line = "";
	pending_input = false;
	caught_error = false;
}

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