<commit_before>//
// Copyright (c) 2017 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core 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
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#ifndef HPP_CORE_STEERING_METHOD_CONSTANT_CURVATURE_HH
# define HPP_CORE_STEERING_METHOD_CONSTANT_CURVATURE_HH

# include <hpp/core/fwd.hh>
# include <hpp/core/path.hh>
# include <hpp/core/steering-method/fwd.hh>

namespace hpp {
  namespace core {
    namespace steeringMethod {
      /// Path of constant curvature for a carlike robot
      /// \todo this class ought to be replaced by a straight using a different
      ///       LiegroupSpace (as an interpolation and differentiation method).
      ///       This would remove the need for the two lengths
      ///       (pathLength and curveLength)
      class ConstantCurvature : public Path {
      public:
        typedef Path parent_t;
        virtual ~ConstantCurvature () throw () {}
         /// Create instance and return shared pointer.
        /// \param robot the carlike robot,
        /// \param init Initial configuration of the path,
        /// \param curvature curvature of the path,
        /// \param length length of the path, negative values correspond to
        ///        backward motions
        /// \param xyId id of degrees of freedom corresponding to (x,y)
        /// coordinates of robot,
        /// \param rzId id of degrees of freedom corresponding to orientation
        /// of robot.
        /// \param rz joint corresponding to orientation of robot,
        /// \param vector of joints corresponding to wheels.
        static ConstantCurvaturePtr_t create
        (const DevicePtr_t& robot, ConfigurationIn_t init,
         ConfigurationIn_t end,
         value_type curveLength, value_type pathLength,
         value_type curvature, size_type xyId, size_type rzId,
         const JointPtr_t rz, const std::vector<JointPtr_t> wheels,
         const ConstraintSetPtr_t& constraints);

         /// Create instance and return shared pointer.
        static ConstantCurvaturePtr_t createCopy
        (const ConstantCurvaturePtr_t& other);

        /// Create instance and return shared pointer.
        static ConstantCurvaturePtr_t createCopy
        (const ConstantCurvaturePtr_t& other,
         const ConstraintSetPtr_t& constraints);

        /// Return a shared pointer to a copy of this
        virtual PathPtr_t copy () const;

        /// Return a shared pointer to a copy of this with constraints
        /// \param constraints constraints to apply to the copy
        /// \pre *this should not have constraints.
        virtual PathPtr_t copy (const ConstraintSetPtr_t& constraints) const
        {
	  return createCopy (weak_.lock (), constraints);
        }

       /// Get the initial configuration
        inline Configuration_t initial () const
        {
          return initial_;
        }

        /// Get the final configuration
        inline Configuration_t end () const
        {
          return end_;
        }

      protected:
        /// Print path in a stream
        virtual std::ostream& print (std::ostream &os) const;

        /// Constructor
        /// \param robot the carlike robot,
        /// \param init Initial configuration of the path,
        /// \param curvature curvature of the path,
        /// \param length length of the path, negative values correspond to
        ///        backward motions
        /// \param xyId id of degrees of freedom corresponding to (x,y)
        /// coordinates of robot,
        /// \param rzId id of degrees of freedom corresponding to orientation
        /// of robot.
        /// \param rz joint corresponding to orientation of robot,
        /// \param vector of joints corresponding to wheels.
        ConstantCurvature (const DevicePtr_t& robot, ConfigurationIn_t init,
                           ConfigurationIn_t end,
                           value_type curveLength, value_type pathLength,
                           value_type curvature, size_type xyId,
                           size_type rzId, const JointPtr_t rz,
                           const std::vector<JointPtr_t> wheels);

        /// Constructor
        /// \param robot the carlike robot,
        /// \param init Initial configuration of the path,
        /// \param length length of the path, negative values correspond to
        ///        backward motions
        /// \param curvature curvature of the path,
        /// \param xyId id of degrees of freedom corresponding to (x,y)
        /// coordinates of robot,
        /// \param rzId id of degrees of freedom corresponding to orientation
        /// of robot.
        /// \param rz joint corresponding to orientation of robot,
        /// \param vector of joints corresponding to wheels,
        /// \param constraints set of contraints the path is suject to.
        ConstantCurvature (const DevicePtr_t& robot, ConfigurationIn_t init,
                           ConfigurationIn_t end,
                           value_type curveLength, value_type pathLength,
                           value_type curvature, size_type xyId, size_type rzId,
                           const JointPtr_t rz,
                           const std::vector<JointPtr_t> wheels,
                           ConstraintSetPtr_t constraints);

        /// Copy constructor
        ConstantCurvature (const ConstantCurvature& other);

        /// Copy constructor with constraints
        ConstantCurvature (const ConstantCurvature& other,
                           const ConstraintSetPtr_t& constraints);

        virtual bool impl_compute (ConfigurationOut_t result,
                                   value_type param) const;
        /// Virtual implementation of derivative
        virtual void impl_derivative
        (vectorOut_t result, const value_type& param, size_type order) const;

        /// store weak pointer to itself
        void init (const ConstantCurvatureWkPtr_t& weak)
        {
          parent_t::init (weak);
          weak_ = weak;
        }
    private:
        /// Set the wheel joints for a car-like vehicle.
        ///
        /// \param rz joint from which the turning radius was computed.
        /// \param wheels bounded rotation joints.
        void setWheelJoints (const JointPtr_t rz,
                             const std::vector<JointPtr_t> wheels);

        const DevicePtr_t robot_;
        const Configuration_t initial_;
        Configuration_t end_;
        const value_type curveLength_, curvature_;
        const size_type xyId_,rzId_;
        size_type dxyId_,drzId_;
        const value_type forward_;
        struct Wheels_t {
          value_type value; // Constant value of the wheel angle
          JointPtr_t j;
          Wheels_t () : j () {}
        };
        std::vector<Wheels_t> wheels_;
        ConstantCurvatureWkPtr_t weak_;
      }; // class ConstantCurvature
    } // namespace steeringMethod
  } // namespace core
} // namespace hpp

#endif // HPP_CORE_STEERING_METHOD_CONSTANT_CURVATURE_HH
<commit_msg>[doc] Make documentation of ConstantCurvature more accurate.<commit_after>//
// Copyright (c) 2017 CNRS
// Authors: Florent Lamiraux
//
// This file is part of hpp-core
// hpp-core 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
// 3 of the License, or (at your option) any later version.
//
// hpp-core is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Lesser Public License for more details.  You should have
// received a copy of the GNU Lesser General Public License along with
// hpp-core  If not, see
// <http://www.gnu.org/licenses/>.

#ifndef HPP_CORE_STEERING_METHOD_CONSTANT_CURVATURE_HH
# define HPP_CORE_STEERING_METHOD_CONSTANT_CURVATURE_HH

# include <hpp/core/fwd.hh>
# include <hpp/core/path.hh>
# include <hpp/core/steering-method/fwd.hh>

namespace hpp {
  namespace core {
    namespace steeringMethod {
      /// Path of constant curvature for a carlike robot
      class ConstantCurvature : public Path {
      public:
        typedef Path parent_t;
        virtual ~ConstantCurvature () throw () {}
         /// Create instance and return shared pointer.
        /// \param robot the carlike robot,
        /// \param init, end Initial and final configurations of the path,
        /// \param curveLength distance traveled by the middle of the rear
        ///        wheel axis, negative values correspond to backward motions
        /// \param pathLength length of the interval of definition. Should be
        ///        positive,
        /// \param curvature curvature of the path,
        /// \param xyId id of degrees of freedom corresponding to (x,y)
        /// coordinates of robot,
        /// \param rzId id of degrees of freedom corresponding to orientation
        /// of robot.
        /// \param rz joint corresponding to orientation of robot,
        /// \param wheels vector of joints corresponding to wheels,
        /// \param constraints set of contraints the path is suject to.
        static ConstantCurvaturePtr_t create
        (const DevicePtr_t& robot, ConfigurationIn_t init,
         ConfigurationIn_t end,
         value_type curveLength, value_type pathLength,
         value_type curvature, size_type xyId, size_type rzId,
         const JointPtr_t rz, const std::vector<JointPtr_t> wheels,
         const ConstraintSetPtr_t& constraints);

         /// Create instance and return shared pointer.
        static ConstantCurvaturePtr_t createCopy
        (const ConstantCurvaturePtr_t& other);

        /// Create instance and return shared pointer.
        static ConstantCurvaturePtr_t createCopy
        (const ConstantCurvaturePtr_t& other,
         const ConstraintSetPtr_t& constraints);

        /// Return a shared pointer to a copy of this
        virtual PathPtr_t copy () const;

        /// Return a shared pointer to a copy of this with constraints
        /// \param constraints constraints to apply to the copy
        /// \pre *this should not have constraints.
        virtual PathPtr_t copy (const ConstraintSetPtr_t& constraints) const
        {
	  return createCopy (weak_.lock (), constraints);
        }

       /// Get the initial configuration
        inline Configuration_t initial () const
        {
          return initial_;
        }

        /// Get the final configuration
        inline Configuration_t end () const
        {
          return end_;
        }

      protected:
        /// Print path in a stream
        virtual std::ostream& print (std::ostream &os) const;

        /// Constructor
        /// \param robot the carlike robot,
        /// \param init, end Initial and final configurations of the path,
        /// \param curveLength distance traveled by the middle of the rear
        ///        wheel axis, negative values correspond to backward motions
        /// \param pathLength length of the interval of definition. Should be
        ///        positive,
        /// \param curvature curvature of the path,
        /// \param xyId id of degrees of freedom corresponding to (x,y)
        /// coordinates of robot,
        /// \param rzId id of degrees of freedom corresponding to orientation
        /// of robot.
        /// \param rz joint corresponding to orientation of robot,
        /// \param wheels vector of joints corresponding to wheels.
        ConstantCurvature (const DevicePtr_t& robot, ConfigurationIn_t init,
                           ConfigurationIn_t end,
                           value_type curveLength, value_type pathLength,
                           value_type curvature, size_type xyId,
                           size_type rzId, const JointPtr_t rz,
                           const std::vector<JointPtr_t> wheels);

        /// Constructor
        /// \param robot the carlike robot,
        /// \param init, end Initial and final configurations of the path,
        /// \param curveLength distance traveled by the middle of the rear
        ///        wheel axis, negative values correspond to backward motions
        /// \param pathLength length of the interval of definition. Should be
        ///        positive,
        /// \param curvature curvature of the path,
        /// \param xyId id of degrees of freedom corresponding to (x,y)
        /// coordinates of robot,
        /// \param rzId id of degrees of freedom corresponding to orientation
        /// of robot.
        /// \param rz joint corresponding to orientation of robot,
        /// \param wheels vector of joints corresponding to wheels,
        /// \param constraints set of contraints the path is suject to.
        ConstantCurvature (const DevicePtr_t& robot, ConfigurationIn_t init,
                           ConfigurationIn_t end,
                           value_type curveLength, value_type pathLength,
                           value_type curvature, size_type xyId, size_type rzId,
                           const JointPtr_t rz,
                           const std::vector<JointPtr_t> wheels,
                           ConstraintSetPtr_t constraints);

        /// Copy constructor
        ConstantCurvature (const ConstantCurvature& other);

        /// Copy constructor with constraints
        ConstantCurvature (const ConstantCurvature& other,
                           const ConstraintSetPtr_t& constraints);

        virtual bool impl_compute (ConfigurationOut_t result,
                                   value_type param) const;
        /// Virtual implementation of derivative
        virtual void impl_derivative
        (vectorOut_t result, const value_type& param, size_type order) const;

        /// store weak pointer to itself
        void init (const ConstantCurvatureWkPtr_t& weak)
        {
          parent_t::init (weak);
          weak_ = weak;
        }
    private:
        /// Set the wheel joints for a car-like vehicle.
        ///
        /// \param rz joint from which the turning radius was computed.
        /// \param wheels bounded rotation joints.
        void setWheelJoints (const JointPtr_t rz,
                             const std::vector<JointPtr_t> wheels);

        const DevicePtr_t robot_;
        const Configuration_t initial_;
        Configuration_t end_;
        const value_type curveLength_, curvature_;
        const size_type xyId_,rzId_;
        size_type dxyId_,drzId_;
        const value_type forward_;
        struct Wheels_t {
          value_type value; // Constant value of the wheel angle
          JointPtr_t j;
          Wheels_t () : j () {}
        };
        std::vector<Wheels_t> wheels_;
        ConstantCurvatureWkPtr_t weak_;
      }; // class ConstantCurvature
    } // namespace steeringMethod
  } // namespace core
} // namespace hpp

#endif // HPP_CORE_STEERING_METHOD_CONSTANT_CURVATURE_HH
<|endoftext|>


<commit_before>#ifndef OPENGM_NEW_VISITOR_HXX
#define OPENGM_NEW_VISITOR_HXX

#include <iostream>
#include <opengm/opengm.hxx>
#include <opengm/utilities/timer.hxx>

namespace opengm{
namespace visitors{

struct VisitorReturnFlag{
  const static size_t ContinueInf          = 0;
   const static size_t StopInfBoundReached  = 1;
   const static size_t StopInfTimeout       = 2;
};

template<class INFERENCE>
class EmptyVisitor{
public:
  EmptyVisitor(){
  }
  void begin(INFERENCE & inf){}
  size_t operator()(INFERENCE & inf){
    return VisitorReturnFlag::ContinueInf;
  }
  void end(INFERENCE & inf){
  }
};

template<class INFERENCE>
class ExplicitEmptyVisitor{
public:
   ExplicitEmptyVisitor(){
   }
   void begin(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){}
   size_t operator()(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      return VisitorReturnFlag::ContinueInf;
   }
   void end(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
   }
};

template<class INFERENCE>
class VerboseVisitor{
public:
  VerboseVisitor(const size_t visithNth=1,const bool multiline=false)
  :   iteration_(0),
    visithNth_(visithNth),
    multiline_(multiline){
  }
  void begin(INFERENCE & inf){
      std::cout<<"begin: value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
      ++iteration_;
   }
  size_t operator()(INFERENCE & inf){
    if((iteration_)%visithNth_==0){
      std::cout<<"step: "<<iteration_<<" value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
    }
    ++iteration_;
    return VisitorReturnFlag::ContinueInf;
  }
  void end(INFERENCE & inf){
    std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
  }
private:
  size_t iteration_;
  size_t visithNth_;
  bool   multiline_;
};

template<class INFERENCE>
class ExplicitVerboseVisitor{
public:
   ExplicitVerboseVisitor(const size_t visithNth=1,const bool multiline=false)
   :  iteration_(0),
      visithNth_(visithNth),
      multiline_(multiline){
   }
   void begin(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      std::cout<<"begin: value "<< value <<" bound "<< bound <<"\n";
      ++iteration_;
   }
   size_t operator()(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      if((iteration_)%visithNth_==0){
         std::cout<<"step: "<<iteration_<<" value "<< value <<" bound "<< bound <<"\n";
      }
      ++iteration_;
      return VisitorReturnFlag::ContinueInf;
   }
   void end(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      std::cout<<"value "<< value <<" bound "<< bound <<"\n";
   }
private:
   size_t iteration_;
   size_t visithNth_;
   bool   multiline_;
};

template<class INFERENCE>
class TimingVisitor{
public:
  typedef typename  INFERENCE::ValueType ValueType;

  TimingVisitor(
    const size_t visithNth=1,
    const size_t reserve=0,
    const bool   verbose=true,
    const bool   multiline=true,
    const double timeLimit=std::numeric_limits<double>::infinity(),
    const double gapLimit=0.0
  )
  :
    protocolMap_(),
    times_(),
    values_(),
    bounds_(),
    iterations_(),
    timer_(),
    iteration_(0),
    visithNth_(visithNth),
    verbose_(verbose),
    multiline_(multiline),
    timeLimit_(timeLimit),
    gapLimit_(gapLimit),
    totalTime_(0.0)
  {
    // allocate all protocolated items
    ctime_    = & protocolMap_["ctime"]    ;
    times_      = & protocolMap_["times"]    ;
    values_     = & protocolMap_["values"]   ;
    bounds_     = & protocolMap_["bounds"]   ;
    iterations_ = & protocolMap_["iteration"];

    // reservations
    if(reserve>0){
      times_->reserve(reserve);
      values_->reserve(reserve);
      bounds_->reserve(reserve);
      iterations_->reserve(reserve);
    }

    // start timer to measure time from
    // constructor call to "begin" call
    timer_.tic();
  }

  void begin(INFERENCE & inf){
      // stop timer which measured time from
      // constructor call to this "begin" call
      timer_.toc();
      // store values bound time and iteration number
      const ValueType val=inf.value();
      const ValueType bound=inf.bound();
      ctime_->push_back(timer_.elapsedTime());
        times_->push_back(0);
        values_->push_back(val);
        bounds_->push_back(bound);
        iterations_->push_back(double(iteration_));

        // print step
        if(verbose_)
         std::cout<<"value "<<val<<" bound "<<bound<<"\n";
        // increment iteration
        ++iteration_;
      // restart timer
      timer_.reset();
      timer_.tic();
   }

  size_t operator()(INFERENCE & inf){

    if(iteration_%visithNth_==0){
      // stop timer
      timer_.toc();

      // store values bound time and iteration number
      const ValueType val   =inf.value();
      const ValueType bound   =inf.bound();
      const double  t     = timer_.elapsedTime();
         times_->push_back(t);
         values_->push_back(val);
         bounds_->push_back(bound);
         iterations_->push_back(double(iteration_));
         // increment total time
         totalTime_+=t;
         if(verbose_){
         std::cout<<"step: "<<iteration_<<" value "<<val<<" bound "<<bound<<" [ "<<totalTime_ << "]" <<"\n";
         }

         // check if gap limit reached
      if(std::fabs(bound - val) <= gapLimit_){
           if(verbose_)
              std::cout<<"gap limit reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfBoundReached;
         }
      // check if time limit reached
         if(totalTime_ > timeLimit_) {
           if(verbose_)
              std::cout<<"timeout reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfTimeout;
         }
         // restart timer
         timer_.reset();
         timer_.tic();
      }
      ++iteration_;
      return VisitorReturnFlag::ContinueInf;
  }

  void end(INFERENCE & inf){
    // stop timer
    timer_.toc();
    // store values bound time and iteration number
    const ValueType val=inf.value();
    const ValueType bound=inf.bound();
    times_->push_back(timer_.elapsedTime());
        values_->push_back(val);
        bounds_->push_back(bound);
        iterations_->push_back(double(iteration_));
        if(verbose_){
          std::cout<<"value "<<val<<" bound "<<bound<<"\n";
        }
  }

  // timing visitor specific interface

  const std::map< std::string, std::vector<double  > > & protocolMap()const{
    return protocolMap_;
  }

  const std::vector<double> & getConstructionTime()const{
    return *ctime_;
  }
  const std::vector<double> & getTimes      ()const{
    return *times_;
  }
  const std::vector<double> & getValues     ()const{
    return *values_;
  }
  const std::vector<double> & getBounds     ()const{
    return *bounds_;
  }
  const std::vector<double> & getIterations   ()const{
    return *iterations_;
  }

private:

  std::map< std::string, std::vector<double  > >  protocolMap_;

  std::vector<double  > * ctime_;
  std::vector<double  > * times_;
  std::vector<double  > * values_;
  std::vector<double  > * bounds_;
  std::vector<double  > * iterations_;
  opengm::Timer timer_;
  opengm::Timer totalTimer_;
  size_t iteration_;
  size_t visithNth_;
  bool verbose_;
  bool   multiline_;

  double timeLimit_;
  double gapLimit_;
  double totalTime_;
};

template<class INFERENCE>
class ExplicitTimingVisitor{
public:
   typedef typename  INFERENCE::ValueType ValueType;

   ExplicitTimingVisitor(
      const size_t visithNth=1,
      const size_t reserve=0,
      const bool   verbose=true,
      const bool   multiline=true,
      const double timeLimit=std::numeric_limits<double>::infinity(),
      const double gapLimit=0.0
   )
   :
      protocolMap_(),
      times_(),
      values_(),
      bounds_(),
      iterations_(),
      timer_(),
      iteration_(0),
      visithNth_(visithNth),
      verbose_(verbose),
      multiline_(multiline),
      timeLimit_(timeLimit),
      gapLimit_(gapLimit),
      totalTime_(0.0)
   {
      // allocate all protocolated items
      ctime_      = & protocolMap_["ctime"]    ;
      times_      = & protocolMap_["times"]    ;
      values_     = & protocolMap_["values"]   ;
      bounds_     = & protocolMap_["bounds"]   ;
      iterations_ = & protocolMap_["iteration"];

      // reservations
      if(reserve>0){
         times_->reserve(reserve);
         values_->reserve(reserve);
         bounds_->reserve(reserve);
         iterations_->reserve(reserve);
      }

      // start timer to measure time from
      // constructor call to "begin" call
      timer_.tic();
   }

   void begin(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      // stop timer which measured time from
      // constructor call to this "begin" call
      timer_.toc();
      // store values bound time and iteration number
      ctime_->push_back(timer_.elapsedTime());
      times_->push_back(0);
      values_->push_back(value);
      bounds_->push_back(bound);
      iterations_->push_back(double(iteration_));

      // print step
      if(verbose_)
         std::cout<<"value "<<value<<" bound "<<bound<<"\n";
      // increment iteration
      ++iteration_;
      // restart timer
      timer_.reset();
      timer_.tic();
   }

   size_t operator()(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){

      if(iteration_%visithNth_==0){
         // stop timer
         timer_.toc();

         // store values bound time and iteration number
         const double   t     = timer_.elapsedTime();
         times_->push_back(t);
         values_->push_back(value);
         bounds_->push_back(bound);
         iterations_->push_back(double(iteration_));
         // increment total time
         totalTime_+=t;
         if(verbose_){
         std::cout<<"step: "<<iteration_<<" value "<<value<<" bound "<<bound<<" [ "<<totalTime_ << "]" <<"\n";
         }

         // check if gap limit reached
         if(std::fabs(bound - value) <= gapLimit_){
           if(verbose_)
              std::cout<<"gap limit reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfBoundReached;
         }
         // check if time limit reached
         if(totalTime_ > timeLimit_) {
           if(verbose_)
              std::cout<<"timeout reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfTimeout;
         }
         // restart timer
         timer_.reset();
         timer_.tic();
      }
      ++iteration_;
      return VisitorReturnFlag::ContinueInf;
   }

   void end(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      // stop timer
      timer_.toc();
      // store values bound time and iteration number
      times_->push_back(timer_.elapsedTime());
        values_->push_back(value);
        bounds_->push_back(bound);
        iterations_->push_back(double(iteration_));
        if(verbose_){
         std::cout<<"value "<<value<<" bound "<<bound<<"\n";
        }
   }

   // timing visitor specific interface

   const std::map< std::string, std::vector<double  > > & protocolMap()const{
      return protocolMap_;
   }

   const std::vector<double> & getConstructionTime()const{
      return *ctime_;
   }
   const std::vector<double> & getTimes         ()const{
      return *times_;
   }
   const std::vector<double> & getValues        ()const{
      return *values_;
   }
   const std::vector<double> & getBounds        ()const{
      return *bounds_;
   }
   const std::vector<double> & getIterations    ()const{
      return *iterations_;
   }

private:

   std::map< std::string, std::vector<double  > >  protocolMap_;

   std::vector<double  > * ctime_;
   std::vector<double  > * times_;
   std::vector<double  > * values_;
   std::vector<double  > * bounds_;
   std::vector<double  > * iterations_;
   opengm::Timer timer_;
   opengm::Timer totalTimer_;
   size_t iteration_;
   size_t visithNth_;
   bool verbose_;
   bool   multiline_;

   double timeLimit_;
   double gapLimit_;
   double totalTime_;
};

}
}

#endif //OPENGM_NEW_VISITOR_HXX
<commit_msg>add missing include of map<commit_after>#ifndef OPENGM_NEW_VISITOR_HXX
#define OPENGM_NEW_VISITOR_HXX

#include <iostream>
#include <map>
#include <opengm/opengm.hxx>
#include <opengm/utilities/timer.hxx>

namespace opengm{
namespace visitors{

struct VisitorReturnFlag{
  const static size_t ContinueInf          = 0;
   const static size_t StopInfBoundReached  = 1;
   const static size_t StopInfTimeout       = 2;
};

template<class INFERENCE>
class EmptyVisitor{
public:
  EmptyVisitor(){
  }
  void begin(INFERENCE & inf){}
  size_t operator()(INFERENCE & inf){
    return VisitorReturnFlag::ContinueInf;
  }
  void end(INFERENCE & inf){
  }
};

template<class INFERENCE>
class ExplicitEmptyVisitor{
public:
   ExplicitEmptyVisitor(){
   }
   void begin(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){}
   size_t operator()(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      return VisitorReturnFlag::ContinueInf;
   }
   void end(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
   }
};

template<class INFERENCE>
class VerboseVisitor{
public:
  VerboseVisitor(const size_t visithNth=1,const bool multiline=false)
  :   iteration_(0),
    visithNth_(visithNth),
    multiline_(multiline){
  }
  void begin(INFERENCE & inf){
      std::cout<<"begin: value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
      ++iteration_;
   }
  size_t operator()(INFERENCE & inf){
    if((iteration_)%visithNth_==0){
      std::cout<<"step: "<<iteration_<<" value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
    }
    ++iteration_;
    return VisitorReturnFlag::ContinueInf;
  }
  void end(INFERENCE & inf){
    std::cout<<"value "<<inf.value()<<" bound "<<inf.bound()<<"\n";
  }
private:
  size_t iteration_;
  size_t visithNth_;
  bool   multiline_;
};

template<class INFERENCE>
class ExplicitVerboseVisitor{
public:
   ExplicitVerboseVisitor(const size_t visithNth=1,const bool multiline=false)
   :  iteration_(0),
      visithNth_(visithNth),
      multiline_(multiline){
   }
   void begin(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      std::cout<<"begin: value "<< value <<" bound "<< bound <<"\n";
      ++iteration_;
   }
   size_t operator()(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      if((iteration_)%visithNth_==0){
         std::cout<<"step: "<<iteration_<<" value "<< value <<" bound "<< bound <<"\n";
      }
      ++iteration_;
      return VisitorReturnFlag::ContinueInf;
   }
   void end(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      std::cout<<"value "<< value <<" bound "<< bound <<"\n";
   }
private:
   size_t iteration_;
   size_t visithNth_;
   bool   multiline_;
};

template<class INFERENCE>
class TimingVisitor{
public:
  typedef typename  INFERENCE::ValueType ValueType;

  TimingVisitor(
    const size_t visithNth=1,
    const size_t reserve=0,
    const bool   verbose=true,
    const bool   multiline=true,
    const double timeLimit=std::numeric_limits<double>::infinity(),
    const double gapLimit=0.0
  )
  :
    protocolMap_(),
    times_(),
    values_(),
    bounds_(),
    iterations_(),
    timer_(),
    iteration_(0),
    visithNth_(visithNth),
    verbose_(verbose),
    multiline_(multiline),
    timeLimit_(timeLimit),
    gapLimit_(gapLimit),
    totalTime_(0.0)
  {
    // allocate all protocolated items
    ctime_    = & protocolMap_["ctime"]    ;
    times_      = & protocolMap_["times"]    ;
    values_     = & protocolMap_["values"]   ;
    bounds_     = & protocolMap_["bounds"]   ;
    iterations_ = & protocolMap_["iteration"];

    // reservations
    if(reserve>0){
      times_->reserve(reserve);
      values_->reserve(reserve);
      bounds_->reserve(reserve);
      iterations_->reserve(reserve);
    }

    // start timer to measure time from
    // constructor call to "begin" call
    timer_.tic();
  }

  void begin(INFERENCE & inf){
      // stop timer which measured time from
      // constructor call to this "begin" call
      timer_.toc();
      // store values bound time and iteration number
      const ValueType val=inf.value();
      const ValueType bound=inf.bound();
      ctime_->push_back(timer_.elapsedTime());
        times_->push_back(0);
        values_->push_back(val);
        bounds_->push_back(bound);
        iterations_->push_back(double(iteration_));

        // print step
        if(verbose_)
         std::cout<<"value "<<val<<" bound "<<bound<<"\n";
        // increment iteration
        ++iteration_;
      // restart timer
      timer_.reset();
      timer_.tic();
   }

  size_t operator()(INFERENCE & inf){

    if(iteration_%visithNth_==0){
      // stop timer
      timer_.toc();

      // store values bound time and iteration number
      const ValueType val   =inf.value();
      const ValueType bound   =inf.bound();
      const double  t     = timer_.elapsedTime();
         times_->push_back(t);
         values_->push_back(val);
         bounds_->push_back(bound);
         iterations_->push_back(double(iteration_));
         // increment total time
         totalTime_+=t;
         if(verbose_){
         std::cout<<"step: "<<iteration_<<" value "<<val<<" bound "<<bound<<" [ "<<totalTime_ << "]" <<"\n";
         }

         // check if gap limit reached
      if(std::fabs(bound - val) <= gapLimit_){
           if(verbose_)
              std::cout<<"gap limit reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfBoundReached;
         }
      // check if time limit reached
         if(totalTime_ > timeLimit_) {
           if(verbose_)
              std::cout<<"timeout reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfTimeout;
         }
         // restart timer
         timer_.reset();
         timer_.tic();
      }
      ++iteration_;
      return VisitorReturnFlag::ContinueInf;
  }

  void end(INFERENCE & inf){
    // stop timer
    timer_.toc();
    // store values bound time and iteration number
    const ValueType val=inf.value();
    const ValueType bound=inf.bound();
    times_->push_back(timer_.elapsedTime());
        values_->push_back(val);
        bounds_->push_back(bound);
        iterations_->push_back(double(iteration_));
        if(verbose_){
          std::cout<<"value "<<val<<" bound "<<bound<<"\n";
        }
  }

  // timing visitor specific interface

  const std::map< std::string, std::vector<double  > > & protocolMap()const{
    return protocolMap_;
  }

  const std::vector<double> & getConstructionTime()const{
    return *ctime_;
  }
  const std::vector<double> & getTimes      ()const{
    return *times_;
  }
  const std::vector<double> & getValues     ()const{
    return *values_;
  }
  const std::vector<double> & getBounds     ()const{
    return *bounds_;
  }
  const std::vector<double> & getIterations   ()const{
    return *iterations_;
  }

private:

  std::map< std::string, std::vector<double  > >  protocolMap_;

  std::vector<double  > * ctime_;
  std::vector<double  > * times_;
  std::vector<double  > * values_;
  std::vector<double  > * bounds_;
  std::vector<double  > * iterations_;
  opengm::Timer timer_;
  opengm::Timer totalTimer_;
  size_t iteration_;
  size_t visithNth_;
  bool verbose_;
  bool   multiline_;

  double timeLimit_;
  double gapLimit_;
  double totalTime_;
};

template<class INFERENCE>
class ExplicitTimingVisitor{
public:
   typedef typename  INFERENCE::ValueType ValueType;

   ExplicitTimingVisitor(
      const size_t visithNth=1,
      const size_t reserve=0,
      const bool   verbose=true,
      const bool   multiline=true,
      const double timeLimit=std::numeric_limits<double>::infinity(),
      const double gapLimit=0.0
   )
   :
      protocolMap_(),
      times_(),
      values_(),
      bounds_(),
      iterations_(),
      timer_(),
      iteration_(0),
      visithNth_(visithNth),
      verbose_(verbose),
      multiline_(multiline),
      timeLimit_(timeLimit),
      gapLimit_(gapLimit),
      totalTime_(0.0)
   {
      // allocate all protocolated items
      ctime_      = & protocolMap_["ctime"]    ;
      times_      = & protocolMap_["times"]    ;
      values_     = & protocolMap_["values"]   ;
      bounds_     = & protocolMap_["bounds"]   ;
      iterations_ = & protocolMap_["iteration"];

      // reservations
      if(reserve>0){
         times_->reserve(reserve);
         values_->reserve(reserve);
         bounds_->reserve(reserve);
         iterations_->reserve(reserve);
      }

      // start timer to measure time from
      // constructor call to "begin" call
      timer_.tic();
   }

   void begin(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      // stop timer which measured time from
      // constructor call to this "begin" call
      timer_.toc();
      // store values bound time and iteration number
      ctime_->push_back(timer_.elapsedTime());
      times_->push_back(0);
      values_->push_back(value);
      bounds_->push_back(bound);
      iterations_->push_back(double(iteration_));

      // print step
      if(verbose_)
         std::cout<<"value "<<value<<" bound "<<bound<<"\n";
      // increment iteration
      ++iteration_;
      // restart timer
      timer_.reset();
      timer_.tic();
   }

   size_t operator()(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){

      if(iteration_%visithNth_==0){
         // stop timer
         timer_.toc();

         // store values bound time and iteration number
         const double   t     = timer_.elapsedTime();
         times_->push_back(t);
         values_->push_back(value);
         bounds_->push_back(bound);
         iterations_->push_back(double(iteration_));
         // increment total time
         totalTime_+=t;
         if(verbose_){
         std::cout<<"step: "<<iteration_<<" value "<<value<<" bound "<<bound<<" [ "<<totalTime_ << "]" <<"\n";
         }

         // check if gap limit reached
         if(std::fabs(bound - value) <= gapLimit_){
           if(verbose_)
              std::cout<<"gap limit reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfBoundReached;
         }
         // check if time limit reached
         if(totalTime_ > timeLimit_) {
           if(verbose_)
              std::cout<<"timeout reached\n";
           // restart timer
           timer_.reset();
           timer_.tic();
           return VisitorReturnFlag::StopInfTimeout;
         }
         // restart timer
         timer_.reset();
         timer_.tic();
      }
      ++iteration_;
      return VisitorReturnFlag::ContinueInf;
   }

   void end(INFERENCE & inf, const typename INFERENCE::ValueType value, const typename INFERENCE::ValueType bound){
      // stop timer
      timer_.toc();
      // store values bound time and iteration number
      times_->push_back(timer_.elapsedTime());
        values_->push_back(value);
        bounds_->push_back(bound);
        iterations_->push_back(double(iteration_));
        if(verbose_){
         std::cout<<"value "<<value<<" bound "<<bound<<"\n";
        }
   }

   // timing visitor specific interface

   const std::map< std::string, std::vector<double  > > & protocolMap()const{
      return protocolMap_;
   }

   const std::vector<double> & getConstructionTime()const{
      return *ctime_;
   }
   const std::vector<double> & getTimes         ()const{
      return *times_;
   }
   const std::vector<double> & getValues        ()const{
      return *values_;
   }
   const std::vector<double> & getBounds        ()const{
      return *bounds_;
   }
   const std::vector<double> & getIterations    ()const{
      return *iterations_;
   }

private:

   std::map< std::string, std::vector<double  > >  protocolMap_;

   std::vector<double  > * ctime_;
   std::vector<double  > * times_;
   std::vector<double  > * values_;
   std::vector<double  > * bounds_;
   std::vector<double  > * iterations_;
   opengm::Timer timer_;
   opengm::Timer totalTimer_;
   size_t iteration_;
   size_t visithNth_;
   bool verbose_;
   bool   multiline_;

   double timeLimit_;
   double gapLimit_;
   double totalTime_;
};

}
}

#endif //OPENGM_NEW_VISITOR_HXX
<|endoftext|>


<commit_before>#include <sal/queue.hpp>
#include <sal/common.test.hpp>
#include <thread>

namespace {

template <typename SyncPolicy>
struct test
  : public sal_test::with_type<SyncPolicy>
{
  using queue_t = sal::queue_t<int, SyncPolicy>;
  queue_t queue{};
};

using types = testing::Types<
  sal::no_sync_t,
  sal::spsc_sync_t
>;

TYPED_TEST_CASE_P(test);

TYPED_TEST_P(test, ctor)
{
  int i;
  ASSERT_EQ(false, this->queue.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_empty)
{
  int i;
  ASSERT_EQ(false, this->queue.try_pop(&i));

  auto q = std::move(this->queue);
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_empty_1)
{
  this->queue.push(1);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  auto q = std::move(this->queue);
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_single)
{
  this->queue.push(1);

  auto q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_single_1)
{
  this->queue.push(1);
  this->queue.push(2);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  auto q = std::move(this->queue);
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_multiple)
{
  this->queue.push(1);
  this->queue.push(2);

  auto q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_multiple_1)
{
  this->queue.push(1);
  this->queue.push(2);
  this->queue.push(3);

  int i;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  auto q = std::move(this->queue);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_empty)
{
  typename TestFixture::queue_t q;
  q = std::move(this->queue);

  int i;
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_empty_1)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  q = std::move(this->queue);
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_single)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);

  q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_single_1)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);
  this->queue.push(2);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  q = std::move(this->queue);
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_multiple)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);
  this->queue.push(2);

  q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_multiple_1)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);
  this->queue.push(2);
  this->queue.push(3);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  q = std::move(this->queue);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, single_push_pop)
{
  this->queue.push(1);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(false, this->queue.try_pop(&i));
}

TYPED_TEST_P(test, multiple_push_pop)
{
  this->queue.push(1);
  this->queue.push(2);
  this->queue.push(3);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(2, i);
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(false, this->queue.try_pop(&i));
}

TYPED_TEST_P(test, interleaved_push_pop)
{
  this->queue.push(1);
  this->queue.push(2);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  this->queue.push(3);

  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(2, i);

  this->queue.push(2);

  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, this->queue.try_pop(&i));
}

REGISTER_TYPED_TEST_CASE_P(test,
  ctor,

  move_ctor_empty,
  move_ctor_empty_1,
  move_ctor_single,
  move_ctor_single_1,
  move_ctor_multiple,
  move_ctor_multiple_1,

  move_assign_empty,
  move_assign_empty_1,
  move_assign_single,
  move_assign_single_1,
  move_assign_multiple,
  move_assign_multiple_1,

  single_push_pop,
  multiple_push_pop,
  interleaved_push_pop
);

INSTANTIATE_TYPED_TEST_CASE_P(queue, test, types);

TEST(queue, single_consumer_single_producer)
{
  // FYI, this test is almost meaningless, just for fun
  sal::queue_t<int, sal::spsc_sync_t> queue{};

  // consumer
  auto consumer = std::thread([&queue]
  {
    int i = 0, prev = 0;
    while (i != -1)
    {
      if (queue.try_pop(&i) && i != -1)
      {
        EXPECT_EQ(prev + 1, i);
        prev = i;
      }
      std::this_thread::yield();
    }
  });

  // producer
  for (int i = 1;  i < 1000;  ++i)
  {
    queue.push(i);
  }
  queue.push(-1);

  consumer.join();
}

} // namespace
<commit_msg>queue: increase spsc test iteration to 10k [skip ci]<commit_after>#include <sal/queue.hpp>
#include <sal/common.test.hpp>
#include <thread>

namespace {

template <typename SyncPolicy>
struct test
  : public sal_test::with_type<SyncPolicy>
{
  using queue_t = sal::queue_t<int, SyncPolicy>;
  queue_t queue{};
};

using types = testing::Types<
  sal::no_sync_t,
  sal::spsc_sync_t
>;

TYPED_TEST_CASE_P(test);

TYPED_TEST_P(test, ctor)
{
  int i;
  ASSERT_EQ(false, this->queue.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_empty)
{
  int i;
  ASSERT_EQ(false, this->queue.try_pop(&i));

  auto q = std::move(this->queue);
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_empty_1)
{
  this->queue.push(1);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  auto q = std::move(this->queue);
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_single)
{
  this->queue.push(1);

  auto q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_single_1)
{
  this->queue.push(1);
  this->queue.push(2);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  auto q = std::move(this->queue);
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_multiple)
{
  this->queue.push(1);
  this->queue.push(2);

  auto q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_ctor_multiple_1)
{
  this->queue.push(1);
  this->queue.push(2);
  this->queue.push(3);

  int i;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  auto q = std::move(this->queue);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_empty)
{
  typename TestFixture::queue_t q;
  q = std::move(this->queue);

  int i;
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_empty_1)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  q = std::move(this->queue);
  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_single)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);

  q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_single_1)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);
  this->queue.push(2);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  q = std::move(this->queue);
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_multiple)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);
  this->queue.push(2);

  q = std::move(this->queue);

  int i = 0;
  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, move_assign_multiple_1)
{
  typename TestFixture::queue_t q;

  this->queue.push(1);
  this->queue.push(2);
  this->queue.push(3);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  q = std::move(this->queue);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(true, q.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(false, q.try_pop(&i));
}

TYPED_TEST_P(test, single_push_pop)
{
  this->queue.push(1);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  ASSERT_EQ(false, this->queue.try_pop(&i));
}

TYPED_TEST_P(test, multiple_push_pop)
{
  this->queue.push(1);
  this->queue.push(2);
  this->queue.push(3);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(2, i);
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(false, this->queue.try_pop(&i));
}

TYPED_TEST_P(test, interleaved_push_pop)
{
  this->queue.push(1);
  this->queue.push(2);

  int i = 0;
  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(1, i);

  this->queue.push(3);

  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(2, i);

  this->queue.push(2);

  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(3, i);

  ASSERT_EQ(true, this->queue.try_pop(&i));
  EXPECT_EQ(2, i);

  ASSERT_EQ(false, this->queue.try_pop(&i));
}

REGISTER_TYPED_TEST_CASE_P(test,
  ctor,

  move_ctor_empty,
  move_ctor_empty_1,
  move_ctor_single,
  move_ctor_single_1,
  move_ctor_multiple,
  move_ctor_multiple_1,

  move_assign_empty,
  move_assign_empty_1,
  move_assign_single,
  move_assign_single_1,
  move_assign_multiple,
  move_assign_multiple_1,

  single_push_pop,
  multiple_push_pop,
  interleaved_push_pop
);

INSTANTIATE_TYPED_TEST_CASE_P(queue, test, types);

TEST(queue, single_consumer_single_producer)
{
  // FYI, this test is almost meaningless, just for fun
  sal::queue_t<int, sal::spsc_sync_t> queue{};

  // consumer
  auto consumer = std::thread([&queue]
  {
    int i = 0, prev = 0;
    while (i != -1)
    {
      if (queue.try_pop(&i) && i != -1)
      {
        EXPECT_EQ(prev + 1, i);
        prev = i;
      }
      std::this_thread::yield();
    }
  });

  // producer
  for (int i = 1;  i < 10000;  ++i)
  {
    queue.push(i);
  }
  queue.push(-1);

  consumer.join();
}

} // namespace
<|endoftext|>


<commit_before>#include <fstream>
#include <sstream>
#include <vector>
#include <iostream>

#include "core/argparse.h"

#include "core/io.h"
#include "core/image.h"
#include "core/image_draw.h"
#include "core/pack.h"

using namespace euphoria::core;

int
main(int argc, char* argv[])
{
    std::string output_file = "collage.png";
    auto image_size = Sizei::FromWidthHeight(1014, 1024);
    int padding = 5;
    auto background_color = Color::Gray;

    // todo: input more than one file
    std::vector<std::string> files;

    auto parser = argparse::Parser {"collage tool"};

    parser.Add("-o, --output", &output_file);
    parser.AddVector("files", &files).Nargs("F");
    parser.OnComplete([&]
    {
        auto images = std::vector<ImageLoadResult>(files.size());
        auto image_sizes = std::vector<Sizei>(files.size());
        int i = 0;

        // load images
        for(const auto& f: files)
        {
            const auto index = i; i += 1;

            auto chunk = io::FileToChunk(f);
            if(chunk == nullptr)
            {
                std::cerr << "failed to read " << f << "\n";
                return argparse::ParseResult::Error;
            }
            images[index] = LoadImage(chunk, f, AlphaLoad::Keep);
            if(images[index].error.empty() == false)
            {
                std::cerr << "failed to read image " <<
                    images[index].error << "\n";
                return argparse::ParseResult::Error;
            }

            image_sizes[index] = Sizei::FromWidthHeight
            (
                images[index].image.GetWidth() + padding,
                images[index].image.GetHeight() + padding
            );
        }

        // pack images
        const auto packed = Pack(image_size, image_sizes);
        bool all_packed = true; // updated when drawing

        // draw new image
        auto composed_image = Image{};
        composed_image.SetupWithAlphaSupport(image_size.width, image_size.height);
        Clear(&composed_image, background_color);
        i = 0;
        for(const auto& rect: packed)
        {
            const auto index = i; i += 1;

            if(rect.has_value() == false)
            {
                std::cerr << "failed to pack " << files[i] << "\n";
                all_packed = false;
                continue;
            }

            // std::cout << rect->BottomLeft() << "\n";
            PasteImage(&composed_image, rect->BottomLeft(), images[index].image);
        }

        if(all_packed == false)
        {
            // return argparse::ParseResult::Error;
        }

        // save image to out
        auto saved_chunk = composed_image.Write(ImageWriteFormat::PNG);
        io::ChunkToFile(saved_chunk, output_file);
        return argparse::ParseResult::Ok;
    });

    return ParseFromMain(&parser, argc, argv);
}
<commit_msg>added todos<commit_after>#include <fstream>
#include <sstream>
#include <vector>
#include <iostream>

#include "core/argparse.h"

#include "core/io.h"
#include "core/image.h"
#include "core/image_draw.h"
#include "core/pack.h"

using namespace euphoria::core;

int
main(int argc, char* argv[])
{
    // todo(Gustav): expose as commandline arguments
    std::string output_file = "collage.png";
    auto image_size = Sizei::FromWidthHeight(1014, 1024);
    int padding = 5;
    auto background_color = Color::Gray;

    // todo: input more than one file
    std::vector<std::string> files;

    auto parser = argparse::Parser {"collage tool"};

    parser.Add("-o, --output", &output_file);
    parser.AddVector("files", &files).Nargs("F");
    parser.OnComplete([&]
    {
        auto images = std::vector<ImageLoadResult>(files.size());
        auto image_sizes = std::vector<Sizei>(files.size());
        int i = 0;

        // load images
        for(const auto& f: files)
        {
            const auto index = i; i += 1;

            auto chunk = io::FileToChunk(f);
            if(chunk == nullptr)
            {
                std::cerr << "failed to read " << f << "\n";
                return argparse::ParseResult::Error;
            }
            images[index] = LoadImage(chunk, f, AlphaLoad::Keep);
            if(images[index].error.empty() == false)
            {
                std::cerr << "failed to read image " <<
                    images[index].error << "\n";
                return argparse::ParseResult::Error;
            }

            image_sizes[index] = Sizei::FromWidthHeight
            (
                images[index].image.GetWidth() + padding,
                images[index].image.GetHeight() + padding
            );
        }

        // pack images
        const auto packed = Pack(image_size, image_sizes);
        bool all_packed = true; // updated when drawing

        // draw new image
        // todo(Gustav): add option to pack make image smaller than requested
        // to reduce wasted space and tighly pack the images
        auto composed_image = Image{};
        composed_image.SetupWithAlphaSupport(image_size.width, image_size.height);
        Clear(&composed_image, background_color);
        i = 0;
        for(const auto& rect: packed)
        {
            const auto index = i; i += 1;

            if(rect.has_value() == false)
            {
                std::cerr << "failed to pack " << files[i] << "\n";
                all_packed = false;
                continue;
            }

            // std::cout << rect->BottomLeft() << "\n";
            PasteImage(&composed_image, rect->BottomLeft(), images[index].image);
        }

        if(all_packed == false)
        {
            // return argparse::ParseResult::Error;
        }

        // save image to out
        auto saved_chunk = composed_image.Write(ImageWriteFormat::PNG);
        io::ChunkToFile(saved_chunk, output_file);
        return argparse::ParseResult::Ok;
    });

    return ParseFromMain(&parser, argc, argv);
}
<|endoftext|>


<commit_before>// https://oj.leetcode.com/problems/word-break/
namespace WordBreak {
    // recursive solution, will Time Limit Exceeded in OJ
    class Solution {
    public:
        bool doWordBreak(string &s, int start, unordered_set<string> &dict) {
            if (start == s.size()) return true;
            for (unordered_set<string>::iterator it = dict.begin(); it != dict.end(); it++) {
                const string& word = *it;
                if (start + word.size() > s.size()) continue;
                if (s.substr(start, word.size()) == word && doWordBreak(s, start + word.size(), dict)) {
                    return true;
                }
            }
            return false;
        }

        bool wordBreak(string s, unordered_set<string> &dict) {
            return doWordBreak(s, 0, dict);
        }
    };

    class Solution {
    public:
        pair<int, int> findMinLenAndMaxLen(unordered_set<string> &dict) {
            int minLen = INT_MAX;
            int maxLen = INT_MIN;
            for (unordered_set<string>::iterator it = dict.begin(); it != dict.end(); it++) {
                const string & cur = *it;
                minLen = min((int)cur.size(), minLen);
                maxLen = max((int)cur.size(), maxLen);
            }
            return make_pair(minLen, maxLen);
        }

        bool wordBreak(string s, unordered_set<string> &dict) {
            if (s.empty()) return false;
            if (dict.empty()) return false;

            pair<int, int> m = findMinLenAndMaxLen(dict);
            int minLen = m.first;
            int maxLen = m.second;
            vector<bool> dp = vector<bool>(s.size() + 1, false);
            dp[0] = true;
            for (int i = 1; i <= s.size(); i++) {
                if (!dp[i - 1]) continue;
                for (int len = minLen; len <= maxLen; len++) {
                    if (i + len - 1 > s.size()) break;
                    string cur = s.substr(i - 1, len);
                    if (dict.find(cur) != dict.end()) {
                        dp[i + len - 1] = true;
                    }
                }
            }

            return dp[s.size()];
        }
    };
}
<commit_msg>Add 1-D dp solution<commit_after>// https://oj.leetcode.com/problems/word-break/
namespace WordBreak {
    // recursive solution, will Time Limit Exceeded in OJ
    class Solution {
    public:
        bool doWordBreak(string &s, int start, unordered_set<string> &dict) {
            if (start == s.size()) return true;
            for (unordered_set<string>::iterator it = dict.begin(); it != dict.end(); it++) {
                const string& word = *it;
                if (start + word.size() > s.size()) continue;
                if (s.substr(start, word.size()) == word && doWordBreak(s, start + word.size(), dict)) {
                    return true;
                }
            }
            return false;
        }

        bool wordBreak(string s, unordered_set<string> &dict) {
            return doWordBreak(s, 0, dict);
        }
    };

    // 1-D DP, time complexity O(n^2), space complexity O(n)
    class Solution {
    public:
        bool wordBreak(string s, unordered_set<string> &dict) {
            vector<bool> dp(s.size() + 1, false);
            dp[0] = true;
            for (int i = 1; i <= s.size(); i++) {
                int len = 1;
                while (i - len >= 0) {
                    if (dp[i - len] && dict.find(s.substr(i - len, len)) != dict.end())  {
                        dp[i] = true;
                        break;
                    }
                    len++;
                }
            }

            return dp[s.size()];
        }
    };

    // 2-D dp
    class Solution {
    public:
        pair<int, int> findMinLenAndMaxLen(unordered_set<string> &dict) {
            int minLen = INT_MAX;
            int maxLen = INT_MIN;
            for (unordered_set<string>::iterator it = dict.begin(); it != dict.end(); it++) {
                const string & cur = *it;
                minLen = min((int)cur.size(), minLen);
                maxLen = max((int)cur.size(), maxLen);
            }
            return make_pair(minLen, maxLen);
        }

        bool wordBreak(string s, unordered_set<string> &dict) {
            if (s.empty()) return false;
            if (dict.empty()) return false;

            pair<int, int> m = findMinLenAndMaxLen(dict);
            int minLen = m.first;
            int maxLen = m.second;
            vector<bool> dp = vector<bool>(s.size() + 1, false);
            dp[0] = true;
            for (int i = 1; i <= s.size(); i++) {
                if (!dp[i - 1]) continue;
                for (int len = minLen; len <= maxLen; len++) {
                    if (i + len - 1 > s.size()) break;
                    string cur = s.substr(i - 1, len);
                    if (dict.find(cur) != dict.end()) {
                        dp[i + len - 1] = true;
                    }
                }
            }

            return dp[s.size()];
        }
    };
}
<|endoftext|>


<commit_before>#ifndef COFFEE_MILL_SUPER_IMPOSE
#define COFFEE_MILL_SUPER_IMPOSE
#include "math/BestFitStructure.hpp"
#include "data/DCDReader.hpp"
#include "data/DCDWriter.hpp"
#include "data/PDBReader.hpp"
#include "data/PDBWriter.hpp"
#include <list>

namespace mill
{

template<typename T>
std::vector<T>
remove_except_elements(const std::vector<T>& elements,
        const std::vector<std::vector<std::int_least64_t>>& exception)
{
    std::vector<T> retval;
    retval.reserve(elements.size());
    std::int_least64_t index = 0;
    for(auto iter = elements.cbegin(); iter != elements.cend(); ++iter)
    {
        ++index;
        bool remove = false;
        for(auto e = exception.cbegin(); e != exception.cend(); ++e)
        {
            if(e->front() <= index && index <= e->back())
            {
                remove = true;
                break;
            }
        }
        if(remove) continue;
        retval.push_back(*iter);
    }
    return retval;
}

template<typename vectorT>
int superimpose(const std::string& fname)
{
    if(fname.substr(fname.size() - 4, 4) == ".dcd")
    {// no input file. use all particles.
        const std::string outname =
            fname.substr(0, fname.size() - 4) + "_imposed.dcd";

        std::ofstream ofs(outname);
        if(not ofs.good())
            throw std::runtime_error("file open error: " + outname);

        DCDReader<vectorT> reader;
        DCDWriter<vectorT> writer;
        auto dcddata = reader.read(fname);
        writer.write_header(ofs, dcddata.header());

        BestFit<typename scalar_type_of<vectorT>::type> bestfit;
        bestfit.set_reference(dcddata.traj().front());
        for(auto snap = dcddata.cbegin(); snap != dcddata.cend(); ++snap)
        {
            writer.write_snapshot(ofs, bestfit.fit(*snap));
        }
        ofs.close();
        return 0;
    }
    else if(fname.substr(fname.size() - 5, 5) == ".toml")
    {// remove some particles to fit.
        std::ifstream tomlfile(fname);
        if(not tomlfile.good())
            throw std::invalid_argument("file open error: " + fname);

        const toml::Data input = toml::parse(tomlfile);
        const std::string dcdname = toml::get<toml::String>(input.at("dcdfile"));
        const std::string outname = toml::get<toml::String>(input.at("output"));
        const std::vector<std::vector<std::int_least64_t>> except_particle =
            toml::get<toml::Array<toml::Array<toml::Integer>>>(input.at("except"));

        std::ofstream outfile(outname);
        if(not outfile.good())
            throw std::runtime_error("file open error: " + outname);

        DCDReader<vectorT> reader;
        DCDWriter<vectorT> writer;
        std::ifstream dcdfile(dcdname);
        if(not dcdfile.good())
            throw std::invalid_argument("file open error: " + dcdname);

        auto dcddata = reader.read(dcdfile);
        writer.write_header(outfile, dcddata.header());

        auto initial = dcddata.traj().front();
        BestFit<typename scalar_type_of<vectorT>::type> bestfit;
        bestfit.set_reference(remove_except_elements(initial, except_particle));
        for(auto snap = dcddata.cbegin(); snap != dcddata.cend(); ++snap)
        {
            const auto core = remove_except_elements(*snap, except_particle);
            const auto R = bestfit.rotational_matrix(core);
            const auto dx = bestfit.zeroing_vector(core);
            auto rotated = *snap;
            for(auto iter = rotated.begin(); iter != rotated.end(); ++iter)
                *iter -= dx;

            for(auto iter = rotated.begin(); iter != rotated.end(); ++iter)
            {
                auto tmp = R * (*iter);
                *iter = tmp;
            }
            writer.write_snapshot(outfile, rotated);
        }
        outfile.close();
        return 0;
    }
    else
    {
        throw std::invalid_argument("unknown file in argument: " + fname);
    }
}

}// mill

#endif//COFFEE_MILL_SUPER_IMPOSE
<commit_msg>remove SuperImpose; use mode_dcd_impose<commit_after><|endoftext|>


<commit_before>#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#include <cstring>
#include "util.hpp"
#include "context.hpp"
#include "sass_functions.h"

extern "C" {
  using namespace std;
  using namespace Sass;

  // Struct to hold custom function callback
  struct Sass_Function {
    const char*      signature;
    Sass_Function_Fn function;
    void*            cookie;
  };

  Sass_Function_List ADDCALL sass_make_function_list(size_t length)
  {
    return (Sass_Function_List) calloc(length + 1, sizeof(Sass_Function_Entry));
  }

  Sass_Function_Entry ADDCALL sass_make_function(const char* signature, Sass_Function_Fn function, void* cookie)
  {
    Sass_Function_Entry cb = (Sass_Function_Entry) calloc(1, sizeof(Sass_Function));
    if (cb == 0) return 0;
    cb->signature = signature;
    cb->function = function;
    cb->cookie = cookie;
    return cb;
  }

  // Setters and getters for callbacks on function lists
  Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) { return list[pos]; }
  void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) { list[pos] = cb; }

  const char* ADDCALL sass_function_get_signature(Sass_Function_Entry cb) { return cb->signature; }
  Sass_Function_Fn ADDCALL sass_function_get_function(Sass_Function_Entry cb) { return cb->function; }
  void* ADDCALL sass_function_get_cookie(Sass_Function_Entry cb) { return cb->cookie; }

  // External import entry
  struct Sass_Import {
    char* path;
    char* base;
    char* source;
    char* srcmap;
    // error handling
    char* error;
    size_t line;
    size_t column;
  };

  // Struct to hold importer callback
  struct Sass_Importer {
    Sass_Importer_Fn importer;
    double           priority;
    void*            cookie;
  };

  Sass_Importer_Entry ADDCALL sass_make_importer(Sass_Importer_Fn importer, double priority, void* cookie)
  {
    Sass_Importer_Entry cb = (Sass_Importer_Entry) calloc(1, sizeof(Sass_Importer));
    if (cb == 0) return 0;
    cb->importer = importer;
    cb->priority = priority;
    cb->cookie = cookie;
    return cb;
  }

  Sass_Importer_Fn ADDCALL sass_importer_get_function(Sass_Importer_Entry cb) { return cb->importer; }
  double ADDCALL sass_importer_get_priority (Sass_Importer_Entry cb) { return cb->priority; }
  void* ADDCALL sass_importer_get_cookie(Sass_Importer_Entry cb) { return cb->cookie; }

  // Just in case we have some stray import structs
  void ADDCALL sass_delete_importer (Sass_Importer_Entry cb)
  {
    free(cb);
  }

  // Creator for sass custom importer function list
  Sass_Importer_List ADDCALL sass_make_importer_list(size_t length)
  {
    return (Sass_Importer_List) calloc(length + 1, sizeof(Sass_Importer_Entry));
  }

  // Creator for sass custom importer return argument list
  Sass_Import_List ADDCALL sass_make_import_list(size_t length)
  {
    return (Sass_Import**) calloc(length + 1, sizeof(Sass_Import*));
  }

  // Creator for a single import entry returned by the custom importer inside the list
  // We take ownership of the memory for source and srcmap (freed when context is destroyd)
  Sass_Import_Entry ADDCALL sass_make_import(const char* path, const char* base, char* source, char* srcmap)
  {
    Sass_Import* v = (Sass_Import*) calloc(1, sizeof(Sass_Import));
    if (v == 0) return 0;
    v->path = path ? sass_strdup(path) : 0;
    v->base = base ? sass_strdup(base) : 0;
    v->source = source;
    v->srcmap = srcmap;
    v->error = 0;
    v->line = -1;
    v->column = -1;
    return v;
  }

  // Older style, but somehow still valid - keep around or deprecate?
  Sass_Import_Entry ADDCALL sass_make_import_entry(const char* path, char* source, char* srcmap)
  {
    return sass_make_import(path, path, source, srcmap);
  }

  // Upgrade a normal import entry to throw an error (original path can be re-used by error reporting)
  Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import, const char* error, size_t line, size_t col)
  {
    if (import == 0) return 0;
    if (import->error) free(import->error);
    import->error = error ? strdup(error) : 0;
    import->line = line ? line : -1;
    import->column = col ? col : -1;
    return import;
  }

  // Setters and getters for entries on the import list
  void ADDCALL sass_import_set_list_entry(Sass_Import_List list, size_t idx, Sass_Import_Entry entry) { list[idx] = entry; }
  Sass_Import_Entry ADDCALL sass_import_get_list_entry(Sass_Import_List list, size_t idx) { return list[idx]; }

  // Deallocator for the allocated memory
  void ADDCALL sass_delete_import_list(Sass_Import_List list)
  {
    Sass_Import_List it = list;
    if (list == 0) return;
    while(*list) {
      sass_delete_import(*list);
      ++list;
    }
    free(it);
  }

  // Just in case we have some stray import structs
  void ADDCALL sass_delete_import(Sass_Import_Entry import)
  {
    free(import->path);
    free(import->base);
    free(import->source);
    free(import->srcmap);
    free(import->error);
    free(import);
  }

  // Getter for import entry
  const char* ADDCALL sass_import_get_path(Sass_Import_Entry entry) { return entry->path; }
  const char* ADDCALL sass_import_get_base(Sass_Import_Entry entry) { return entry->base; }
  const char* ADDCALL sass_import_get_source(Sass_Import_Entry entry) { return entry->source; }
  const char* ADDCALL sass_import_get_srcmap(Sass_Import_Entry entry) { return entry->srcmap; }

  // Getter for import error entry
  size_t ADDCALL sass_import_get_error_line(Sass_Import_Entry entry) { return entry->line; }
  size_t ADDCALL sass_import_get_error_column(Sass_Import_Entry entry) { return entry->column; }
  const char* ADDCALL sass_import_get_error_message(Sass_Import_Entry entry) { return entry->error; }

  // Explicit functions to take ownership of the memory
  // Resets our own property since we do not know if it is still alive
  char* ADDCALL sass_import_take_source(Sass_Import_Entry entry) { char* ptr = entry->source; entry->source = 0; return ptr; }
  char* ADDCALL sass_import_take_srcmap(Sass_Import_Entry entry) { char* ptr = entry->srcmap; entry->srcmap = 0; return ptr; }

}
<commit_msg>Add missing implementation of sass_importer_set_list_entry.<commit_after>#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#endif

#include <cstring>
#include "util.hpp"
#include "context.hpp"
#include "sass_functions.h"

extern "C" {
  using namespace std;
  using namespace Sass;

  // Struct to hold custom function callback
  struct Sass_Function {
    const char*      signature;
    Sass_Function_Fn function;
    void*            cookie;
  };

  Sass_Function_List ADDCALL sass_make_function_list(size_t length)
  {
    return (Sass_Function_List) calloc(length + 1, sizeof(Sass_Function_Entry));
  }

  Sass_Function_Entry ADDCALL sass_make_function(const char* signature, Sass_Function_Fn function, void* cookie)
  {
    Sass_Function_Entry cb = (Sass_Function_Entry) calloc(1, sizeof(Sass_Function));
    if (cb == 0) return 0;
    cb->signature = signature;
    cb->function = function;
    cb->cookie = cookie;
    return cb;
  }

  // Setters and getters for callbacks on function lists
  Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) { return list[pos]; }
  void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) { list[pos] = cb; }

  const char* ADDCALL sass_function_get_signature(Sass_Function_Entry cb) { return cb->signature; }
  Sass_Function_Fn ADDCALL sass_function_get_function(Sass_Function_Entry cb) { return cb->function; }
  void* ADDCALL sass_function_get_cookie(Sass_Function_Entry cb) { return cb->cookie; }

  // External import entry
  struct Sass_Import {
    char* path;
    char* base;
    char* source;
    char* srcmap;
    // error handling
    char* error;
    size_t line;
    size_t column;
  };

  // Struct to hold importer callback
  struct Sass_Importer {
    Sass_Importer_Fn importer;
    double           priority;
    void*            cookie;
  };

  Sass_Importer_Entry ADDCALL sass_make_importer(Sass_Importer_Fn importer, double priority, void* cookie)
  {
    Sass_Importer_Entry cb = (Sass_Importer_Entry) calloc(1, sizeof(Sass_Importer));
    if (cb == 0) return 0;
    cb->importer = importer;
    cb->priority = priority;
    cb->cookie = cookie;
    return cb;
  }

  Sass_Importer_Fn ADDCALL sass_importer_get_function(Sass_Importer_Entry cb) { return cb->importer; }
  double ADDCALL sass_importer_get_priority (Sass_Importer_Entry cb) { return cb->priority; }
  void* ADDCALL sass_importer_get_cookie(Sass_Importer_Entry cb) { return cb->cookie; }

  // Just in case we have some stray import structs
  void ADDCALL sass_delete_importer (Sass_Importer_Entry cb)
  {
    free(cb);
  }

  // Creator for sass custom importer function list
  Sass_Importer_List ADDCALL sass_make_importer_list(size_t length)
  {
    return (Sass_Importer_List) calloc(length + 1, sizeof(Sass_Importer_Entry));
  }

  void ADDCALL sass_importer_set_list_entry(Sass_Importer_List list, size_t idx, Sass_Importer_Entry cb) { list[idx] = cb; }

  // Creator for sass custom importer return argument list
  Sass_Import_List ADDCALL sass_make_import_list(size_t length)
  {
    return (Sass_Import**) calloc(length + 1, sizeof(Sass_Import*));
  }

  // Creator for a single import entry returned by the custom importer inside the list
  // We take ownership of the memory for source and srcmap (freed when context is destroyd)
  Sass_Import_Entry ADDCALL sass_make_import(const char* path, const char* base, char* source, char* srcmap)
  {
    Sass_Import* v = (Sass_Import*) calloc(1, sizeof(Sass_Import));
    if (v == 0) return 0;
    v->path = path ? sass_strdup(path) : 0;
    v->base = base ? sass_strdup(base) : 0;
    v->source = source;
    v->srcmap = srcmap;
    v->error = 0;
    v->line = -1;
    v->column = -1;
    return v;
  }

  // Older style, but somehow still valid - keep around or deprecate?
  Sass_Import_Entry ADDCALL sass_make_import_entry(const char* path, char* source, char* srcmap)
  {
    return sass_make_import(path, path, source, srcmap);
  }

  // Upgrade a normal import entry to throw an error (original path can be re-used by error reporting)
  Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import, const char* error, size_t line, size_t col)
  {
    if (import == 0) return 0;
    if (import->error) free(import->error);
    import->error = error ? strdup(error) : 0;
    import->line = line ? line : -1;
    import->column = col ? col : -1;
    return import;
  }

  // Setters and getters for entries on the import list
  void ADDCALL sass_import_set_list_entry(Sass_Import_List list, size_t idx, Sass_Import_Entry entry) { list[idx] = entry; }
  Sass_Import_Entry ADDCALL sass_import_get_list_entry(Sass_Import_List list, size_t idx) { return list[idx]; }

  // Deallocator for the allocated memory
  void ADDCALL sass_delete_import_list(Sass_Import_List list)
  {
    Sass_Import_List it = list;
    if (list == 0) return;
    while(*list) {
      sass_delete_import(*list);
      ++list;
    }
    free(it);
  }

  // Just in case we have some stray import structs
  void ADDCALL sass_delete_import(Sass_Import_Entry import)
  {
    free(import->path);
    free(import->base);
    free(import->source);
    free(import->srcmap);
    free(import->error);
    free(import);
  }

  // Getter for import entry
  const char* ADDCALL sass_import_get_path(Sass_Import_Entry entry) { return entry->path; }
  const char* ADDCALL sass_import_get_base(Sass_Import_Entry entry) { return entry->base; }
  const char* ADDCALL sass_import_get_source(Sass_Import_Entry entry) { return entry->source; }
  const char* ADDCALL sass_import_get_srcmap(Sass_Import_Entry entry) { return entry->srcmap; }

  // Getter for import error entry
  size_t ADDCALL sass_import_get_error_line(Sass_Import_Entry entry) { return entry->line; }
  size_t ADDCALL sass_import_get_error_column(Sass_Import_Entry entry) { return entry->column; }
  const char* ADDCALL sass_import_get_error_message(Sass_Import_Entry entry) { return entry->error; }

  // Explicit functions to take ownership of the memory
  // Resets our own property since we do not know if it is still alive
  char* ADDCALL sass_import_take_source(Sass_Import_Entry entry) { char* ptr = entry->source; entry->source = 0; return ptr; }
  char* ADDCALL sass_import_take_srcmap(Sass_Import_Entry entry) { char* ptr = entry->srcmap; entry->srcmap = 0; return ptr; }

}
<|endoftext|>


<commit_before>/*
  SRMachineControl.cpp - Library for controlling a SR machine with an Arduino Due.

  Copyright (c) 2014 Peter van den Hurk

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

//#include "arduino.h"
#include "SRM.h"

//////////////////////////////////////////
// 				PhysicalSwitch			//
//////////////////////////////////////////

PhysicalSwitch::PhysicalSwitch(int switchnumber, int pin)
{
	// PhysicalSwitch sets the pin mode to output, inits it to low and saves the pin number.

	pinMode(pin, OUTPUT);
	digitalWrite(pin, LOW);
	this->_state = false;
	this->_pin = pin;
	this->_switchNumber = switchnumber;
};

void PhysicalSwitch::Activate()
{
	// Activate a switch
	if(not this->_state)
	{
		digitalWrite(_pin, HIGH);
		this->_state = true;
	};
};

void PhysicalSwitch::Deactivate()
{
	// Deactivate a switch
	if(this->_state)
	{
		digitalWrite(_pin, LOW);
		this->_state = false;
	};
};

int PhysicalSwitch::getSwitchNumber()
{
	return this->_switchNumber;
}

//////////////////////////////////////////
// 				SwitchState				//
//////////////////////////////////////////

SwitchState::SwitchState(PhysicalSwitch** activeSwitches, int nSwitches)
{
	// Switchstates takes an array of Switches, which can be activated in groups.
	this->_activeSwitches = activeSwitches;
	this->_nSwitches = nSwitches;
	this->_next = this;
	this->_previous = this;
};

void SwitchState::InsertSwitchState(SwitchState* insertedState)
{
	// Function for the ring. This inserts a state after this state.
	insertedState->SetPrevious(this);
	insertedState->SetNext(this->_next);
	_next->SetPrevious(insertedState);
	this->SetNext(insertedState);
};

void SwitchState::SetNext(SwitchState* insertedState)
{
	// set the _next variable
	_next = insertedState;
};

void SwitchState::SetPrevious(SwitchState* insertedState)
{
	// set the _previous variable
	_previous = insertedState;
};

SwitchState* SwitchState::GetNext()
{
	// get the _next variable
	return _next;
};

SwitchState* SwitchState::GetPrevious()
{
	// get the _previous variable
	return _previous;
};

int SwitchState::GetNumberOfSwitches()
{
	// get the number of switches (in _nSwitches variable)
	return _nSwitches;
};

PhysicalSwitch** SwitchState::GetSwitches()
{
	// Get the switches associated with the variable
	return _activeSwitches;
};

void SwitchState::SetTransition(int transition)
{
	this->_transition = transition;
}

int SwitchState::GetTransition()
{
	return this->_transition;
}

//////////////////////////////////////////
//				Bridge					//
//////////////////////////////////////////

Bridge::Bridge(int numberOfSwitches, PhysicalSwitch** switches)
{
	// Initialize the Bridge. It takes all of the switches associated with the bridge.
	_nSwitches = numberOfSwitches;
	_switches = switches;
};

void Bridge::TurnOff()
{
	// Turn off the switches associated with this bridge.
	int i;

	for(i = 0 ; i < _nSwitches ; i++)
	{
		_switches[i]->Deactivate();
	};
};

void Bridge::ActivateState(SwitchState* activatedState)
{
	// Activate the switches associated with the given state
	// Next version might include matching with bridge associated switches
	int limit = activatedState->GetNumberOfSwitches();
	PhysicalSwitch** tempSwitches = activatedState->GetSwitches();
	this->TurnOff();

	int i;

	for(i = 0 ; i < limit ; i++)
	{
		tempSwitches[i]->Activate();
	};
};

//////////////////////////////////////////
// 				Controller				//
//////////////////////////////////////////

// The controller implements the logic

Controller::Controller(SwitchState* topState, Bridge* theBridge, Encoder* theEncoder)
{
	// Init with all of the variables
	this->_startState = topState;
	this->_currentState = topState;
	this->_bridge = theBridge;
	this->_encoder = theEncoder;
};

void Controller::ActivateNextState()
{
	// Activate the state that is next in line from the current state
	this->_currentState = this->_currentState->GetNext();
	this->_bridge->ActivateState(this->_currentState);
};

void Controller::ActivatePreviousState()
{
	// Activate the state that is the previous in the ring from the current state
	this->_currentState = this->_currentState->GetPrevious();
	this->_bridge->ActivateState(this->_currentState);
};

/*float Controller::CalculateOffset()
{
	// Calculation of the offset (What the hell is this supposed to be?)
	float offset = ((float) this->_pulsesPerRev / (float) analogRead(1));
	return offset;
};*/

void Controller::CalculateTransitions(int pulsesPerRev, int eRevPerMRev, int nStates, int offset)
{
	// Calculation of the new transition point, given by the pulses per revolution, number of states and the difference in electrical and mechanical speeds.
	this->_startState->SetTransition((offset + pulsesPerRev) % pulsesPerRev);

	SwitchState* theState = this->_startState->GetNext();
	bool stop = false;
	float increase = (float) pulsesPerRev/( (float) (nStates * eRevPerMRev));
	float transition;
	int newTransition;
	int counter = 0;
	if (offset < 0)
	{
		transition = (float) (pulsesPerRev + offset);
	}
	else
	{
		transition = (float) offset;
	}
	this->_startState->SetTransition( (int) transition );
	Serial.println(transition);
	Serial.println((int) (transition + 0.5));

	while( true )
	{
		transition = (transition + increase);
		newTransition = ((int) (transition + 0.5)) % pulsesPerRev;
		theState->SetTransition(newTransition);
		Serial.println(transition);
		Serial.println(newTransition);

		theState = theState->GetNext();
		if( theState == this->_startState )
		{
			return;
		}
	}

};

void Controller::Logic()
{
	// The controller logic.
	// First get the next state for the relevant information.
	SwitchState* NextState = this->_currentState->GetNext();

	// In the case that the transition goes through 0, we check if the encoder did indeed reset. If it did, we can compare and eventually change state.
	if( NextState->GetTransition() < _currentState->GetTransition() )
	{
		if( (NextState->GetTransition() <= (this->_encoder->read()) && this->_encoder->read() < 10000) ) /* LELIJK! Moet een beter oplossing voor zijn.*/
		{
			this->ActivateNextState();
		}
	}
	else if( (NextState->GetTransition() <= (this->_encoder->read()) ) ) // otherwise, we can just use position >= transition
	{
		this->ActivateNextState();
	}
	return;
};

SwitchState* Controller::GetCurrentState()
{
	return this->_currentState;
}

/*float* Controller::GetTransition()
{
	return this->_transitionPosition;
}
*/
<commit_msg>Changed the logic algorithm to a more sensible setup.<commit_after>/*
  SRMachineControl.cpp - Library for controlling a SR machine with an Arduino Due.

  Copyright (c) 2014 Peter van den Hurk

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

//#include "arduino.h"
#include "SRM.h"

//////////////////////////////////////////
// 				PhysicalSwitch			//
//////////////////////////////////////////

PhysicalSwitch::PhysicalSwitch(int switchnumber, int pin)
{
	// PhysicalSwitch sets the pin mode to output, inits it to low and saves the pin number.

	pinMode(pin, OUTPUT);
	digitalWrite(pin, LOW);
	this->_state = false;
	this->_pin = pin;
	this->_switchNumber = switchnumber;
};

void PhysicalSwitch::Activate()
{
	// Activate a switch
	if(not this->_state)
	{
		digitalWrite(_pin, HIGH);
		this->_state = true;
		//Serial.print("ON: ");
		//Serial.print(this->_switchNumber);
		//Serial.println(" ");
	};
};

void PhysicalSwitch::Deactivate()
{
	// Deactivate a switch
	if(this->_state)
	{
		digitalWrite(_pin, LOW);
		this->_state = false;
		//Serial.print("ON: ");
		//Serial.print(this->_switchNumber);
		//Serial.println(" ");
	};
};

int PhysicalSwitch::getSwitchNumber()
{
	return this->_switchNumber;
}

//////////////////////////////////////////
// 				SwitchState				//
//////////////////////////////////////////

SwitchState::SwitchState(PhysicalSwitch** activeSwitches, int nSwitches)
{
	// Switchstates takes an array of Switches, which can be activated in groups.
	this->_activeSwitches = activeSwitches;
	this->_nSwitches = nSwitches;
	this->_next = this;
	this->_previous = this;
};

void SwitchState::InsertSwitchState(SwitchState* insertedState)
{
	// Function for the ring. This inserts a state after this state.
	insertedState->SetPrevious(this);
	insertedState->SetNext(this->_next);
	_next->SetPrevious(insertedState);
	this->SetNext(insertedState);
};

void SwitchState::SetNext(SwitchState* insertedState)
{
	// set the _next variable
	_next = insertedState;
};

void SwitchState::SetPrevious(SwitchState* insertedState)
{
	// set the _previous variable
	_previous = insertedState;
};

SwitchState* SwitchState::GetNext()
{
	// get the _next variable
	return _next;
};

SwitchState* SwitchState::GetPrevious()
{
	// get the _previous variable
	return _previous;
};

int SwitchState::GetNumberOfSwitches()
{
	// get the number of switches (in _nSwitches variable)
	return _nSwitches;
};

PhysicalSwitch** SwitchState::GetSwitches()
{
	// Get the switches associated with the variable
	return _activeSwitches;
};

void SwitchState::SetTransition(int transition)
{
	this->_transition = transition;
}

int SwitchState::GetTransition()
{
	return this->_transition;
}

//////////////////////////////////////////
//				Bridge					//
//////////////////////////////////////////

Bridge::Bridge(int numberOfSwitches, PhysicalSwitch** switches)
{
	// Initialize the Bridge. It takes all of the switches associated with the bridge.
	_nSwitches = numberOfSwitches;
	_switches = switches;
};

void Bridge::TurnOff()
{
	// Turn off the switches associated with this bridge.
	int i;

	for(i = 0 ; i < _nSwitches ; i++)
	{
		_switches[i]->Deactivate();
	};
};

void Bridge::ActivateState(SwitchState* activatedState)
{
	// Activate the switches associated with the given state
	// Next version might include matching with bridge associated switches
	int limit = activatedState->GetNumberOfSwitches();
	PhysicalSwitch** tempSwitches = activatedState->GetSwitches();
	this->TurnOff();

	int i;

	for(i = 0 ; i < limit ; i++)
	{
		tempSwitches[i]->Activate();
	};
};

//////////////////////////////////////////
// 				Controller				//
//////////////////////////////////////////

// The controller implements the logic

Controller::Controller(SwitchState* topState, Bridge* theBridge, Encoder* theEncoder)
{
	// Init with all of the variables
	this->_startState = topState;
	this->_currentState = topState;
	this->_bridge = theBridge;
	this->_encoder = theEncoder;
};

void Controller::ActivateNextState()
{
	// Activate the state that is next in line from the current state
	this->_currentState = this->_currentState->GetNext();
	this->_bridge->ActivateState(this->_currentState);
};

void Controller::ActivatePreviousState()
{
	// Activate the state that is the previous in the ring from the current state
	this->_currentState = this->_currentState->GetPrevious();
	this->_bridge->ActivateState(this->_currentState);
};

/*float Controller::CalculateOffset()
{
	// Calculation of the offset (What the hell is this supposed to be?)
	float offset = ((float) this->_pulsesPerRev / (float) analogRead(1));
	return offset;
};*/

void Controller::CalculateTransitions(int pulsesPerRev, int eRevPerMRev, int nStates, int offset)
{
	// Calculation of the new transition point, given by the pulses per revolution, number of states and the difference in electrical and mechanical speeds.
	this->_startState->SetTransition((offset + pulsesPerRev) % pulsesPerRev);

	SwitchState* theState = this->_startState->GetNext();
	bool stop = false;
	float increase = (float) pulsesPerRev/( (float) (nStates * eRevPerMRev));
	float transition;
	int newTransition;
	int counter = 0;
	if (offset < 0)
	{
		transition = (float) (pulsesPerRev + offset);
	}
	else
	{
		transition = (float) offset;
	}
	this->_startState->SetTransition( (int) transition );
	Serial.println(transition);
	Serial.println((int) (transition + 0.5));

	while( true )
	{
		transition = (transition + increase);
		newTransition = ((int) (transition + 0.5)) % pulsesPerRev;
		theState->SetTransition(newTransition);
		Serial.println(transition);
		Serial.println(newTransition);

		theState = theState->GetNext();
		if( theState == this->_startState )
		{
			return;
		}
	}

};

void Controller::Logic()
{
	// The controller logic.
	// First get the next state for the relevant information.
	SwitchState* NextState = this->_currentState->GetNext();

	// In the case that the transition goes through 0, we check if the encoder did indeed reset. If it did, we can compare and eventually change state.
	if( NextState->GetTransition() < _currentState->GetTransition() )
	{
		if( (NextState->GetTransition() <= (this->_encoder->read()) && this->_encoder->read() < this->_currentState->GetTransition()) )
		{
			//Serial.print("State Change at ");
			//Serial.print(this->_encoder->read());
			//Serial.println(" with 0 transition");
			this->ActivateNextState();
			//Serial.println("");
		}
	}
	else if( (NextState->GetTransition() <= (this->_encoder->read()) ) ) // otherwise, we can just use position >= transition
	{
		//Serial.print("State Change at ");
		//Serial.println(this->_encoder->read());
		this->ActivateNextState();
		//Serial.println("");
	}
	return;
};

SwitchState* Controller::GetCurrentState()
{
	return this->_currentState;
}

/*float* Controller::GetTransition()
{
	return this->_transitionPosition;
}
*/
<|endoftext|>