<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_LINEARSOLVER_CGLINEARSOLVER_INL
#define SOFA_COMPONENT_LINEARSOLVER_CGLINEARSOLVER_INL

#include <SofaBaseLinearSolver/CGLinearSolver.h>
#include <sofa/core/visual/VisualParams.h>
#include <SofaBaseLinearSolver/FullMatrix.h>
#include <SofaBaseLinearSolver/SparseMatrix.h>
#include <SofaBaseLinearSolver/CompressedRowSparseMatrix.h>
#include <sofa/simulation/MechanicalVisitor.h>
#include <sofa/helper/system/thread/CTime.h>
#include <sofa/helper/AdvancedTimer.h>

#include <sofa/core/ObjectFactory.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace linearsolver
{

/// Linear system solver using the conjugate gradient iterative algorithm
template<class TMatrix, class TVector>
CGLinearSolver<TMatrix,TVector>::CGLinearSolver()
    : f_maxIter( initData(&f_maxIter,(unsigned)25,"iterations","maximum number of iterations of the Conjugate Gradient solution") )
    , f_tolerance( initData(&f_tolerance,(SReal)1e-5,"tolerance","desired precision of the Conjugate Gradient Solution (ratio of current residual norm over initial residual norm)") )
    , f_smallDenominatorThreshold( initData(&f_smallDenominatorThreshold,(SReal)1e-5,"threshold","minimum value of the denominator in the conjugate Gradient solution") )
    , f_warmStart( initData(&f_warmStart,false,"warmStart","Use previous solution as initial solution") )
    , f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
    , f_graph( initData(&f_graph,"graph","Graph of residuals at each iteration") )
{
    f_graph.setWidget("graph");
#ifdef DISPLAY_TIME
    timeStamp = 1.0 / (SReal)sofa::helper::system::thread::CTime::getRefTicksPerSec();
#endif

    f_maxIter.setRequired(true);
    f_tolerance.setRequired(true);
    f_smallDenominatorThreshold.setRequired(true);
}

template<class TMatrix, class TVector>
void CGLinearSolver<TMatrix,TVector>::resetSystem()
{
    f_graph.beginEdit()->clear();
    f_graph.endEdit();

    Inherit::resetSystem();
}

template<class TMatrix, class TVector>
void CGLinearSolver<TMatrix,TVector>::setSystemMBKMatrix(const sofa::core::MechanicalParams* mparams)
{
#ifdef DISPLAY_TIME
    sofa::helper::system::thread::CTime timer;
    time2 = (SReal) timer.getTime();
#endif

    Inherit::setSystemMBKMatrix(mparams);

#ifdef DISPLAY_TIME
    time2 = ((SReal) timer.getTime() - time2)  * timeStamp;
#endif
}

/// Solve Mx=b
template<class TMatrix, class TVector>
void CGLinearSolver<TMatrix,TVector>::solve(Matrix& M, Vector& x, Vector& b)
{
#ifdef SOFA_DUMP_VISITOR_INFO
    simulation::Visitor::printComment("ConjugateGradient");
#endif

#ifdef SOFA_DUMP_VISITOR_INFO
    simulation::Visitor::printNode("VectorAllocation");
#endif

    const core::ExecParams* params = core::ExecParams::defaultInstance();
    typename Inherit::TempVectorContainer vtmp(this, params, M, x, b);
    Vector& p = *vtmp.createTempVector();
    Vector& q = *vtmp.createTempVector();
    Vector& r = *vtmp.createTempVector();

    const bool verbose  = f_verbose.getValue();
    double rho, rho_1=0, alpha, beta;

    msg_info_when(verbose) << " CGLinearSolver, b = " << b ;

    /// Compute the initial residual r
    if( f_warmStart.getValue() )
    {
        r = M * x;
        r.eq( b, r, -1.0 );   // initial residual r = b - Ax;
    }
    else
    {
        x.clear();
        r = b; // initial residual
    }

    /// Compute the norm of the right-hand-side vector b
    double normb = b.norm();

    std::map < std::string, sofa::helper::vector<SReal> >& graph = *f_graph.beginEdit();
    sofa::helper::vector<SReal>& graph_error = graph[(this->isMultiGroup()) ? this->currentNode->getName()+std::string("-Error") : std::string("Error")];
    graph_error.clear();
    sofa::helper::vector<SReal>& graph_den = graph[(this->isMultiGroup()) ? this->currentNode->getName()+std::string("-Denominator") : std::string("Denominator")];
    graph_den.clear();
    graph_error.push_back(1);
    unsigned nb_iter;
    const char* endcond = "iterations";

#ifdef DISPLAY_TIME
    sofa::helper::system::thread::CTime timer;
    time1 = (SReal) timer.getTime();
#endif

#ifdef SOFA_DUMP_VISITOR_INFO
    simulation::Visitor::printCloseNode("VectorAllocation");
#endif

    for( nb_iter=1; nb_iter<=f_maxIter.getValue(); nb_iter++ )
    {
#ifdef SOFA_DUMP_VISITOR_INFO
        std::ostringstream comment;
        if (simulation::Visitor::isPrintActivated())
        {
            comment << "Iteration_" << nb_iter;
            simulation::Visitor::printNode(comment.str());
        }
#endif

        /// Compute p = r^2
        rho = r.dot(r);

        /// If NOT the first step
        if (nb_iter>1)
        {
            /// Compute the error from the norm of ρ and b
            double normr = sqrt(rho);
            double err = normr/normb;

            graph_error.push_back(err);

            /// Break condition = TOLERANCE criterion regarding the error err is reached
            if (err <= f_tolerance.getValue())
            {
                endcond = "tolerance";
#ifdef SOFA_DUMP_VISITOR_INFO
                if (simulation::Visitor::isPrintActivated())
                    simulation::Visitor::printCloseNode(comment.str());
#endif
                break;
            }
        }

        /// Compute the value of p, conjugate with x
        if( nb_iter==1 )    // FIRST step
            p = r;
        else                // ALL other steps
        {
            beta = rho / rho_1;

            /// Update p = p*beta + r;
            cgstep_beta(params, p,r,beta);
        }

        if( verbose )
        {
            msg_info() << "p : " << p;
        }

        /// Compute the matrix-vector product : M p
        q = M*p;

        if( verbose )
        {
            msg_info() << "q = M p : " << q;
        }

        /// Compute the denominator : p M p
        double den = p.dot(q);

        graph_den.push_back(den);

        /// Break condition = THRESHOLD criterion regarding the denominator is reached (but do at least one iteration)
        if( fabs(den)<f_smallDenominatorThreshold.getValue())
        {
            if(nb_iter == 1 && den == 0.0)
            {
                if(f_warmStart.getValue())
                {
                    msg_info() << "Equilibrium found at first step (x=A^{-1}b)";
                }
                else
                {
                    msg_warning() << "b or A is zero (in Ax=b system), i.e. no external force or no mass is defined.";
                }

                endcond = "threshold";
                if( verbose )
                {
                    msg_info() << "CGLinearSolver, den = " << den <<", smallDenominatorThreshold = " << f_smallDenominatorThreshold.getValue();
                }

    #ifdef SOFA_DUMP_VISITOR_INFO
                if (simulation::Visitor::isPrintActivated())
                    simulation::Visitor::printCloseNode(comment.str());
    #endif
                break;
            }
            else if(nb_iter == 1)
            {
                msg_warning() << "denominator threshold reached at first iteration of CG" << msgendl
                                 "Check the 'threshold' data field, you might decrease it";
            }
            else
            {
                endcond = "threshold";
                if( verbose )
                {
                    msg_info() << "CGLinearSolver, den = " << den <<", smallDenominatorThreshold = " << f_smallDenominatorThreshold.getValue();
                }

    #ifdef SOFA_DUMP_VISITOR_INFO
                if (simulation::Visitor::isPrintActivated())
                    simulation::Visitor::printCloseNode(comment.str());
    #endif
                break;
            }
        }

        /// Compute the coefficient α for the conjugate direction
        alpha = rho/den;

        /// End of the CG step : update x and r
        cgstep_alpha(params, x,r,p,q,alpha);

        if( verbose )
        {
            msg_info() << "den = " << den << ", alpha = " << alpha;
            msg_info() << "x : " << x;
            msg_info() << "r : " << r;
        }

        rho_1 = rho;
#ifdef SOFA_DUMP_VISITOR_INFO
        if (simulation::Visitor::isPrintActivated())
            simulation::Visitor::printCloseNode(comment.str());
#endif
    }

#ifdef DISPLAY_TIME
    time1 = (SReal)(((SReal) timer.getTime() - time1) * timeStamp / (nb_iter-1));
#endif

    f_graph.endEdit();

    sofa::helper::AdvancedTimer::valSet("CG iterations", nb_iter);

    // x is the solution of the system
#ifdef DISPLAY_TIME
    dmsg_info() << " solve, CG = " << time1 << " build = " << time2;
#endif

    dmsg_info() << "solve, nbiter = "<<nb_iter<<" stop because of "<<endcond;
    dmsg_info_when( verbose ) <<"solve, solution = "<< x ;

    vtmp.deleteTempVector(&p);
    vtmp.deleteTempVector(&q);
    vtmp.deleteTempVector(&r);
}

template<class TMatrix, class TVector>
inline void CGLinearSolver<TMatrix,TVector>::cgstep_beta(const core::ExecParams* /*params*/, Vector& p, Vector& r, SReal beta)
{
    // p = p*beta + r
    p *= beta;
    p += r;
}

template<class TMatrix, class TVector>
inline void CGLinearSolver<TMatrix,TVector>::cgstep_alpha(const core::ExecParams* /*params*/, Vector& x, Vector& r, Vector& p, Vector& q, SReal alpha)
{
    // x = x + alpha p
    x.peq(p,alpha);

    // r = r - alpha q
    r.peq(q,-alpha);
}

} // namespace linearsolver

} // namespace component

} // namespace sofa

#endif // SOFA_COMPONENT_LINEARSOLVER_CGLINEARSOLVER_INL
<commit_msg>CHANGE message from warning to info<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#ifndef SOFA_COMPONENT_LINEARSOLVER_CGLINEARSOLVER_INL
#define SOFA_COMPONENT_LINEARSOLVER_CGLINEARSOLVER_INL

#include <SofaBaseLinearSolver/CGLinearSolver.h>
#include <sofa/core/visual/VisualParams.h>
#include <SofaBaseLinearSolver/FullMatrix.h>
#include <SofaBaseLinearSolver/SparseMatrix.h>
#include <SofaBaseLinearSolver/CompressedRowSparseMatrix.h>
#include <sofa/simulation/MechanicalVisitor.h>
#include <sofa/helper/system/thread/CTime.h>
#include <sofa/helper/AdvancedTimer.h>

#include <sofa/core/ObjectFactory.h>
#include <iostream>

namespace sofa
{

namespace component
{

namespace linearsolver
{

/// Linear system solver using the conjugate gradient iterative algorithm
template<class TMatrix, class TVector>
CGLinearSolver<TMatrix,TVector>::CGLinearSolver()
    : f_maxIter( initData(&f_maxIter,(unsigned)25,"iterations","maximum number of iterations of the Conjugate Gradient solution") )
    , f_tolerance( initData(&f_tolerance,(SReal)1e-5,"tolerance","desired precision of the Conjugate Gradient Solution (ratio of current residual norm over initial residual norm)") )
    , f_smallDenominatorThreshold( initData(&f_smallDenominatorThreshold,(SReal)1e-5,"threshold","minimum value of the denominator in the conjugate Gradient solution") )
    , f_warmStart( initData(&f_warmStart,false,"warmStart","Use previous solution as initial solution") )
    , f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
    , f_graph( initData(&f_graph,"graph","Graph of residuals at each iteration") )
{
    f_graph.setWidget("graph");
#ifdef DISPLAY_TIME
    timeStamp = 1.0 / (SReal)sofa::helper::system::thread::CTime::getRefTicksPerSec();
#endif

    f_maxIter.setRequired(true);
    f_tolerance.setRequired(true);
    f_smallDenominatorThreshold.setRequired(true);
}

template<class TMatrix, class TVector>
void CGLinearSolver<TMatrix,TVector>::resetSystem()
{
    f_graph.beginEdit()->clear();
    f_graph.endEdit();

    Inherit::resetSystem();
}

template<class TMatrix, class TVector>
void CGLinearSolver<TMatrix,TVector>::setSystemMBKMatrix(const sofa::core::MechanicalParams* mparams)
{
#ifdef DISPLAY_TIME
    sofa::helper::system::thread::CTime timer;
    time2 = (SReal) timer.getTime();
#endif

    Inherit::setSystemMBKMatrix(mparams);

#ifdef DISPLAY_TIME
    time2 = ((SReal) timer.getTime() - time2)  * timeStamp;
#endif
}

/// Solve Mx=b
template<class TMatrix, class TVector>
void CGLinearSolver<TMatrix,TVector>::solve(Matrix& M, Vector& x, Vector& b)
{
#ifdef SOFA_DUMP_VISITOR_INFO
    simulation::Visitor::printComment("ConjugateGradient");
#endif

#ifdef SOFA_DUMP_VISITOR_INFO
    simulation::Visitor::printNode("VectorAllocation");
#endif

    const core::ExecParams* params = core::ExecParams::defaultInstance();
    typename Inherit::TempVectorContainer vtmp(this, params, M, x, b);
    Vector& p = *vtmp.createTempVector();
    Vector& q = *vtmp.createTempVector();
    Vector& r = *vtmp.createTempVector();

    const bool verbose  = f_verbose.getValue();
    double rho, rho_1=0, alpha, beta;

    msg_info_when(verbose) << " CGLinearSolver, b = " << b ;

    /// Compute the initial residual r
    if( f_warmStart.getValue() )
    {
        r = M * x;
        r.eq( b, r, -1.0 );   // initial residual r = b - Ax;
    }
    else
    {
        x.clear();
        r = b; // initial residual
    }

    /// Compute the norm of the right-hand-side vector b
    double normb = b.norm();

    std::map < std::string, sofa::helper::vector<SReal> >& graph = *f_graph.beginEdit();
    sofa::helper::vector<SReal>& graph_error = graph[(this->isMultiGroup()) ? this->currentNode->getName()+std::string("-Error") : std::string("Error")];
    graph_error.clear();
    sofa::helper::vector<SReal>& graph_den = graph[(this->isMultiGroup()) ? this->currentNode->getName()+std::string("-Denominator") : std::string("Denominator")];
    graph_den.clear();
    graph_error.push_back(1);
    unsigned nb_iter;
    const char* endcond = "iterations";

#ifdef DISPLAY_TIME
    sofa::helper::system::thread::CTime timer;
    time1 = (SReal) timer.getTime();
#endif

#ifdef SOFA_DUMP_VISITOR_INFO
    simulation::Visitor::printCloseNode("VectorAllocation");
#endif

    for( nb_iter=1; nb_iter<=f_maxIter.getValue(); nb_iter++ )
    {
#ifdef SOFA_DUMP_VISITOR_INFO
        std::ostringstream comment;
        if (simulation::Visitor::isPrintActivated())
        {
            comment << "Iteration_" << nb_iter;
            simulation::Visitor::printNode(comment.str());
        }
#endif

        /// Compute p = r^2
        rho = r.dot(r);

        /// If NOT the first step
        if (nb_iter>1)
        {
            /// Compute the error from the norm of ρ and b
            double normr = sqrt(rho);
            double err = normr/normb;

            graph_error.push_back(err);

            /// Break condition = TOLERANCE criterion regarding the error err is reached
            if (err <= f_tolerance.getValue())
            {
                endcond = "tolerance";
#ifdef SOFA_DUMP_VISITOR_INFO
                if (simulation::Visitor::isPrintActivated())
                    simulation::Visitor::printCloseNode(comment.str());
#endif
                break;
            }
        }

        /// Compute the value of p, conjugate with x
        if( nb_iter==1 )    // FIRST step
            p = r;
        else                // ALL other steps
        {
            beta = rho / rho_1;

            /// Update p = p*beta + r;
            cgstep_beta(params, p,r,beta);
        }

        if( verbose )
        {
            msg_info() << "p : " << p;
        }

        /// Compute the matrix-vector product : M p
        q = M*p;

        if( verbose )
        {
            msg_info() << "q = M p : " << q;
        }

        /// Compute the denominator : p M p
        double den = p.dot(q);

        graph_den.push_back(den);

        /// Break condition = THRESHOLD criterion regarding the denominator is reached (but do at least one iteration)
        if( fabs(den)<f_smallDenominatorThreshold.getValue())
        {
            if(nb_iter == 1 && den == 0.0)
            {
                if(f_warmStart.getValue())
                {
                    msg_info() << "Equilibrium found at first step";
                }
                else
                {
                    msg_info() << "b or A is zero (in Ax=b system), i.e. no external force or no mass is defined";
                }

                endcond = "threshold";
                if( verbose )
                {
                    msg_info() << "CGLinearSolver, den = " << den <<", smallDenominatorThreshold = " << f_smallDenominatorThreshold.getValue();
                }

    #ifdef SOFA_DUMP_VISITOR_INFO
                if (simulation::Visitor::isPrintActivated())
                    simulation::Visitor::printCloseNode(comment.str());
    #endif
                break;
            }
            else if(nb_iter == 1)
            {
                msg_warning() << "denominator threshold reached at first iteration of CG" << msgendl
                              << "Check the 'threshold' data field, you might decrease it";
            }
            else
            {
                endcond = "threshold";
                if( verbose )
                {
                    msg_info() << "CGLinearSolver, den = " << den <<", smallDenominatorThreshold = " << f_smallDenominatorThreshold.getValue();
                }

    #ifdef SOFA_DUMP_VISITOR_INFO
                if (simulation::Visitor::isPrintActivated())
                    simulation::Visitor::printCloseNode(comment.str());
    #endif
                break;
            }
        }

        /// Compute the coefficient α for the conjugate direction
        alpha = rho/den;

        /// End of the CG step : update x and r
        cgstep_alpha(params, x,r,p,q,alpha);

        if( verbose )
        {
            msg_info() << "den = " << den << ", alpha = " << alpha;
            msg_info() << "x : " << x;
            msg_info() << "r : " << r;
        }

        rho_1 = rho;
#ifdef SOFA_DUMP_VISITOR_INFO
        if (simulation::Visitor::isPrintActivated())
            simulation::Visitor::printCloseNode(comment.str());
#endif
    }

#ifdef DISPLAY_TIME
    time1 = (SReal)(((SReal) timer.getTime() - time1) * timeStamp / (nb_iter-1));
#endif

    f_graph.endEdit();

    sofa::helper::AdvancedTimer::valSet("CG iterations", nb_iter);

    // x is the solution of the system
#ifdef DISPLAY_TIME
    dmsg_info() << " solve, CG = " << time1 << " build = " << time2;
#endif

    dmsg_info() << "solve, nbiter = "<<nb_iter<<" stop because of "<<endcond;
    dmsg_info_when( verbose ) <<"solve, solution = "<< x ;

    vtmp.deleteTempVector(&p);
    vtmp.deleteTempVector(&q);
    vtmp.deleteTempVector(&r);
}

template<class TMatrix, class TVector>
inline void CGLinearSolver<TMatrix,TVector>::cgstep_beta(const core::ExecParams* /*params*/, Vector& p, Vector& r, SReal beta)
{
    // p = p*beta + r
    p *= beta;
    p += r;
}

template<class TMatrix, class TVector>
inline void CGLinearSolver<TMatrix,TVector>::cgstep_alpha(const core::ExecParams* /*params*/, Vector& x, Vector& r, Vector& p, Vector& q, SReal alpha)
{
    // x = x + alpha p
    x.peq(p,alpha);

    // r = r - alpha q
    r.peq(q,-alpha);
}

} // namespace linearsolver

} // namespace component

} // namespace sofa

#endif // SOFA_COMPONENT_LINEARSOLVER_CGLINEARSOLVER_INL
<|endoftext|>


<commit_before>#include "command/config.h"
#include <set>
#include <string>

#include "common/file_stream.h"

#define SET_OPTION(key, type) \
do { if(!vm_[key].defaulted() || !config_[key]) { \
  config_[key] = vm_[key].as<type>(); \
}} while(0)

#define SET_OPTION_NONDEFAULT(key, type) \
do { if(vm_.count(key) > 0) { \
  config_[key] = vm_[key].as<type>(); \
}} while(0)

bool Config::has(const std::string& key) const {
  return config_[key];
}

YAML::Node Config::get(const std::string& key) const {
  return config_[key];
}

const YAML::Node& Config::get() const {
  return config_;
}

void ProcessPaths(YAML::Node& node, const boost::filesystem::path& configPath, bool isPath) {
  using namespace boost::filesystem;
  std::set<std::string> paths = {"model", "trainsets", "vocabs"};

  if(isPath) {
    if(node.Type() == YAML::NodeType::Scalar) {
      std::string nodePath = node.as<std::string>();
      if (nodePath.size()) {
        node = canonical(path{nodePath}, configPath).string();
      }
    }
    if(node.Type() == YAML::NodeType::Sequence) {
      for(auto&& sub : node) {
        ProcessPaths(sub, configPath, true);
        break;
      }
    }
  }
  else {
    switch (node.Type()) {
      case YAML::NodeType::Sequence:
        for(auto&& sub : node)
          ProcessPaths(sub, configPath, false);
        break;
      case YAML::NodeType::Map:
        for(auto&& sub : node) {
          std::string key = sub.first.as<std::string>();
          ProcessPaths(sub.second, configPath, paths.count(key) > 0);
        }
        break;
    }
  }
}

void Config::validate() const {
  if (config_["trainsets"]) {
    std::vector<std::string> tmp = config_["trainsets"].as<std::vector<std::string>>();
    if (tmp.size() != 2) {
      std::cerr << "No trainsets!" << std::endl;
      exit(1);
    }
  } else {
    std::cerr << "No trainsets!" << std::endl;
    exit(1);
  }
  if (config_["vocabs"]) {
    if (config_["vocabs"].as<std::vector<std::string>>().size() != 2) {
      std::cerr << "No vocab files!" << std::endl;
      exit(1);
    }
  } else {
    std::cerr << "No vocab files!" << std::endl;
    exit(1);
  }
}

void OutputRec(const YAML::Node node, YAML::Emitter& out) {
  // std::set<std::string> flow = { "devices" };
  std::set<std::string> sorter;
  switch (node.Type()) {
    case YAML::NodeType::Null:
      out << node; break;
    case YAML::NodeType::Scalar:
      out << node; break;
    case YAML::NodeType::Sequence:
      out << YAML::BeginSeq;
      for(auto&& n : node)
        OutputRec(n, out);
      out << YAML::EndSeq;
      break;
    case YAML::NodeType::Map:
      for(auto& n : node)
        sorter.insert(n.first.as<std::string>());
      out << YAML::BeginMap;
      for(auto& key : sorter) {
        out << YAML::Key;
        out << key;
        out << YAML::Value;
        // if(flow.count(key))
          // out << YAML::Flow;
        OutputRec(node[key], out);
      }
      out << YAML::EndMap;
      break;
    case YAML::NodeType::Undefined:
      out << node; break;
  }
}

void Config::addOptions(int argc, char** argv) {
  std::string configPath;

  namespace po = boost::program_options;
  po::options_description general("General options");

  general.add_options()
    ("config,c", po::value(&configPath),
     "Configuration file")
    ("model,m", po::value<std::string>()->default_value("./model"),
      "Path prefix for model to be saved")
    ("device,d", po::value<int>()->default_value(0),
      "Use device no.  arg")
    ("init,i", po::value<std::string>()->default_value(""),
      "Load weights from  arg  before training")
    ("overwrite", po::value<bool>()->default_value(false),
      "Overwrite model with following checkpoints")
    ("trainsets,t", po::value<std::vector<std::string>>()->multitoken(),
      "Paths to training corpora: source target")
    ("vocabs,v", po::value<std::vector<std::string>>()->multitoken(),
      "Paths to vocabulary files, have to correspond to --trainsets")
    ("after-epochs,e", po::value<size_t>()->default_value(0),
      "Finish after this many epochs, 0 is infinity")
    ("after-batches", po::value<size_t>()->default_value(0),
      "Finish after this many batch updates, 0 is infinity")
    ("disp-freq", po::value<size_t>()->default_value(100),
      "Display information every  arg  updates")
    ("save-freq", po::value<size_t>()->default_value(30000),
      "Save model file every  arg  updates")
    ("workspace,w", po::value<size_t>()->default_value(2048),
      "Preallocate  arg  MB of work space")
  ;

  po::options_description hyper("Hyper-parameters");
  hyper.add_options()
    ("max-length", po::value<size_t>()->default_value(50),
      "Maximum length of a sentence in a training sentence pair")
    ("mini-batch,b", po::value<int>()->default_value(40),
      "Size of mini-batch used during update")
    ("maxi-batch", po::value<int>()->default_value(20),
      "Number of batches to preload for length-based sorting")
    ("lrate,l", po::value<double>()->default_value(0.0001),
      "Learning rate for Adam algorithm")
    ("clip-norm,c", po::value<double>()->default_value(1.f),
      "Clip gradient norm to  arg  (0 to disable)")
    ("dim-vocabs", po::value<std::vector<int>>()
      ->multitoken()
      ->default_value(std::vector<int>({50000, 50000}), "50000 50000"),
      "Maximum items in vocabulary ordered by rank")
    ("dim-emb", po::value<int>()->default_value(512), "Size of embedding vector")
    ("dim-rnn", po::value<int>()->default_value(1024), "Size of rnn hidden state")
  ;

  po::options_description configuration("Configuration meta options");
  configuration.add_options()
    ("relative-paths", po::value<bool>()->zero_tokens()->default_value(false),
     "All paths are relative to the config file location")
    ("dump-config", po::value<bool>()->zero_tokens()->default_value(false),
     "Dump current (modified) configuration to stdout and exit")
    ("help,h", po::value<bool>()->zero_tokens()->default_value(false),
      "Print this help message and exit")
  ;

  po::options_description cmdline_options("Allowed options");
  cmdline_options.add(general);
  cmdline_options.add(hyper);
  cmdline_options.add(configuration);

  boost::program_options::variables_map vm_;
  try {
    po::store(po::command_line_parser(argc,argv)
              .options(cmdline_options).run(), vm_);
    po::notify(vm_);
  }
  catch (std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl << std::endl;

    std::cerr << "Usage: " + std::string(argv[0]) +  " [options]" << std::endl;
    std::cerr << cmdline_options << std::endl;
    exit(1);
  }

  if (vm_["help"].as<bool>()) {
    std::cerr << "Usage: " + std::string(argv[0]) +  " [options]" << std::endl;
    std::cerr << cmdline_options << std::endl;
    exit(0);
  }

  if(configPath.size())
    config_ = YAML::Load(InputFileStream(configPath));

  // Simple overwrites
  SET_OPTION("model", std::string);
  SET_OPTION("device", int);
  SET_OPTION("init", std::string);
  SET_OPTION("overwrite", bool);
  // SET_OPTION_NONDEFAULT("trainsets", std::vector<std::string>);

  if (!vm_["trainsets"].empty()) {
    config_["trainsets"] = vm_["trainsets"].as<std::vector<std::string>>();
  }
  if (!vm_["vocabs"].empty()) {
    config_["vocabs"] = vm_["vocabs"].as<std::vector<std::string>>();
  }
  // SET_OPTION_NONDEFAULT("vocabs", std::vector<std::string>);
  SET_OPTION("max-epochs", size_t);
  SET_OPTION("max-batches", size_t);
  SET_OPTION("disp-freq", size_t);
  SET_OPTION("save-freq", size_t);
  SET_OPTION("workspace", size_t);
  SET_OPTION("relative-paths", bool);

  SET_OPTION("max-length", size_t);
  SET_OPTION("mini-batch", int);
  SET_OPTION("maxi-batch", int);
  SET_OPTION("lrate", double);
  SET_OPTION("clip-norm", double);
  SET_OPTION("dim-vocabs", std::vector<int>);
  SET_OPTION("dim-emb", int);
  SET_OPTION("dim-rnn", int);

  validate();

  if (get<bool>("relative-paths") && !vm_["dump-config"].as<bool>())
    ProcessPaths(config_, boost::filesystem::path{configPath}.parent_path(), false);

  if(vm_["dump-config"].as<bool>()) {
    YAML::Emitter emit;
    OutputRec(config_, emit);
    std::cout << emit.c_str() << std::endl;
    exit(0);
  }

}

void Config::logOptions() {
  std::stringstream ss;
  YAML::Emitter out;
  OutputRec(config_, out);
  std::cerr << "Options: \n" << out.c_str() << std::endl;
}
<commit_msg>change options name<commit_after>#include "command/config.h"
#include <set>
#include <string>

#include "common/file_stream.h"

#define SET_OPTION(key, type) \
do { if(!vm_[key].defaulted() || !config_[key]) { \
  config_[key] = vm_[key].as<type>(); \
}} while(0)

#define SET_OPTION_NONDEFAULT(key, type) \
do { if(vm_.count(key) > 0) { \
  config_[key] = vm_[key].as<type>(); \
}} while(0)

bool Config::has(const std::string& key) const {
  return config_[key];
}

YAML::Node Config::get(const std::string& key) const {
  return config_[key];
}

const YAML::Node& Config::get() const {
  return config_;
}

void ProcessPaths(YAML::Node& node, const boost::filesystem::path& configPath, bool isPath) {
  using namespace boost::filesystem;
  std::set<std::string> paths = {"model", "trainsets", "vocabs"};

  if(isPath) {
    if(node.Type() == YAML::NodeType::Scalar) {
      std::string nodePath = node.as<std::string>();
      if (nodePath.size()) {
        node = canonical(path{nodePath}, configPath).string();
      }
    }
    if(node.Type() == YAML::NodeType::Sequence) {
      for(auto&& sub : node) {
        ProcessPaths(sub, configPath, true);
        break;
      }
    }
  }
  else {
    switch (node.Type()) {
      case YAML::NodeType::Sequence:
        for(auto&& sub : node)
          ProcessPaths(sub, configPath, false);
        break;
      case YAML::NodeType::Map:
        for(auto&& sub : node) {
          std::string key = sub.first.as<std::string>();
          ProcessPaths(sub.second, configPath, paths.count(key) > 0);
        }
        break;
    }
  }
}

void Config::validate() const {
  if (config_["trainsets"]) {
    std::vector<std::string> tmp = config_["trainsets"].as<std::vector<std::string>>();
    if (tmp.size() != 2) {
      std::cerr << "No trainsets!" << std::endl;
      exit(1);
    }
  } else {
    std::cerr << "No trainsets!" << std::endl;
    exit(1);
  }
  if (config_["vocabs"]) {
    if (config_["vocabs"].as<std::vector<std::string>>().size() != 2) {
      std::cerr << "No vocab files!" << std::endl;
      exit(1);
    }
  } else {
    std::cerr << "No vocab files!" << std::endl;
    exit(1);
  }
}

void OutputRec(const YAML::Node node, YAML::Emitter& out) {
  // std::set<std::string> flow = { "devices" };
  std::set<std::string> sorter;
  switch (node.Type()) {
    case YAML::NodeType::Null:
      out << node; break;
    case YAML::NodeType::Scalar:
      out << node; break;
    case YAML::NodeType::Sequence:
      out << YAML::BeginSeq;
      for(auto&& n : node)
        OutputRec(n, out);
      out << YAML::EndSeq;
      break;
    case YAML::NodeType::Map:
      for(auto& n : node)
        sorter.insert(n.first.as<std::string>());
      out << YAML::BeginMap;
      for(auto& key : sorter) {
        out << YAML::Key;
        out << key;
        out << YAML::Value;
        // if(flow.count(key))
          // out << YAML::Flow;
        OutputRec(node[key], out);
      }
      out << YAML::EndMap;
      break;
    case YAML::NodeType::Undefined:
      out << node; break;
  }
}

void Config::addOptions(int argc, char** argv) {
  std::string configPath;

  namespace po = boost::program_options;
  po::options_description general("General options");

  general.add_options()
    ("config,c", po::value(&configPath),
     "Configuration file")
    ("model,m", po::value<std::string>()->default_value("./model"),
      "Path prefix for model to be saved")
    ("device,d", po::value<int>()->default_value(0),
      "Use device no.  arg")
    ("init,i", po::value<std::string>()->default_value(""),
      "Load weights from  arg  before training")
    ("overwrite", po::value<bool>()->default_value(false),
      "Overwrite model with following checkpoints")
    ("trainsets,t", po::value<std::vector<std::string>>()->multitoken(),
      "Paths to training corpora: source target")
    ("vocabs,v", po::value<std::vector<std::string>>()->multitoken(),
      "Paths to vocabulary files, have to correspond to --trainsets")
    ("after-epochs,e", po::value<size_t>()->default_value(0),
      "Finish after this many epochs, 0 is infinity")
    ("after-batches", po::value<size_t>()->default_value(0),
      "Finish after this many batch updates, 0 is infinity")
    ("disp-freq", po::value<size_t>()->default_value(100),
      "Display information every  arg  updates")
    ("save-freq", po::value<size_t>()->default_value(30000),
      "Save model file every  arg  updates")
    ("workspace,w", po::value<size_t>()->default_value(2048),
      "Preallocate  arg  MB of work space")
  ;

  po::options_description hyper("Hyper-parameters");
  hyper.add_options()
    ("max-length", po::value<size_t>()->default_value(50),
      "Maximum length of a sentence in a training sentence pair")
    ("mini-batch,b", po::value<int>()->default_value(40),
      "Size of mini-batch used during update")
    ("maxi-batch", po::value<int>()->default_value(20),
      "Number of batches to preload for length-based sorting")
    ("learn-rate,l,", po::value<double>()->default_value(0.0001),
      "Learning rate for Adam algorithm")
    ("clip-norm", po::value<double>()->default_value(1.f),
      "Clip gradient norm to  arg  (0 to disable)")
    ("dim-vocabs", po::value<std::vector<int>>()
      ->multitoken()
      ->default_value(std::vector<int>({50000, 50000}), "50000 50000"),
      "Maximum items in vocabulary ordered by rank")
    ("dim-emb", po::value<int>()->default_value(512), "Size of embedding vector")
    ("dim-rnn", po::value<int>()->default_value(1024), "Size of rnn hidden state")
  ;

  po::options_description configuration("Configuration meta options");
  configuration.add_options()
    ("relative-paths", po::value<bool>()->zero_tokens()->default_value(false),
     "All paths are relative to the config file location")
    ("dump-config", po::value<bool>()->zero_tokens()->default_value(false),
     "Dump current (modified) configuration to stdout and exit")
    ("help,h", po::value<bool>()->zero_tokens()->default_value(false),
      "Print this help message and exit")
  ;

  po::options_description cmdline_options("Allowed options");
  cmdline_options.add(general);
  cmdline_options.add(hyper);
  cmdline_options.add(configuration);

  boost::program_options::variables_map vm_;
  try {
    po::store(po::command_line_parser(argc,argv)
              .options(cmdline_options).run(), vm_);
    po::notify(vm_);
  }
  catch (std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl << std::endl;

    std::cerr << "Usage: " + std::string(argv[0]) +  " [options]" << std::endl;
    std::cerr << cmdline_options << std::endl;
    exit(1);
  }

  if (vm_["help"].as<bool>()) {
    std::cerr << "Usage: " + std::string(argv[0]) +  " [options]" << std::endl;
    std::cerr << cmdline_options << std::endl;
    exit(0);
  }

  if(configPath.size())
    config_ = YAML::Load(InputFileStream(configPath));

  // Simple overwrites
  SET_OPTION("model", std::string);
  SET_OPTION("device", int);
  SET_OPTION("init", std::string);
  SET_OPTION("overwrite", bool);
  // SET_OPTION_NONDEFAULT("trainsets", std::vector<std::string>);

  if (!vm_["trainsets"].empty()) {
    config_["trainsets"] = vm_["trainsets"].as<std::vector<std::string>>();
  }
  if (!vm_["vocabs"].empty()) {
    config_["vocabs"] = vm_["vocabs"].as<std::vector<std::string>>();
  }
  // SET_OPTION_NONDEFAULT("vocabs", std::vector<std::string>);
  SET_OPTION("max-epochs", size_t);
  SET_OPTION("max-batches", size_t);
  SET_OPTION("disp-freq", size_t);
  SET_OPTION("save-freq", size_t);
  SET_OPTION("workspace", size_t);
  SET_OPTION("relative-paths", bool);

  SET_OPTION("max-length", size_t);
  SET_OPTION("mini-batch", int);
  SET_OPTION("maxi-batch", int);
  SET_OPTION("lrate", double);
  SET_OPTION("clip-norm", double);
  SET_OPTION("dim-vocabs", std::vector<int>);
  SET_OPTION("dim-emb", int);
  SET_OPTION("dim-rnn", int);

  validate();

  if (get<bool>("relative-paths") && !vm_["dump-config"].as<bool>())
    ProcessPaths(config_, boost::filesystem::path{configPath}.parent_path(), false);

  if(vm_["dump-config"].as<bool>()) {
    YAML::Emitter emit;
    OutputRec(config_, emit);
    std::cout << emit.c_str() << std::endl;
    exit(0);
  }

}

void Config::logOptions() {
  std::stringstream ss;
  YAML::Emitter out;
  OutputRec(config_, out);
  std::cerr << "Options: \n" << out.c_str() << std::endl;
}
<|endoftext|>


<commit_before>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <fstream>
#include <iostream>
#include <stdexcept>
#include <streambuf>
#include <vector>

int main() {
  if (!glfwInit()) {
    throw std::runtime_error("glfw initialization failed");
  }

  glfwWindowHint(GLFW_SAMPLES, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

  auto window = glfwCreateWindow(1024, 768, "Tutorial 01", nullptr, nullptr);
  if (window == nullptr) {
    glfwTerminate();
    throw std::runtime_error(
        "failed to open glfw window. If you have an Intel GPU, they "
        "are not 3.3 compatible. Try the 2.1 version of the tutorials.");
  }
  glfwMakeContextCurrent(window);
  glewExperimental = true;
  if (glewInit() != GLEW_OK) {
    throw std::runtime_error("failed to initialize glew");
  }

  glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

  GLuint vaID;
  glGenVertexArrays(1, &vaID);
  glBindVertexArray(vaID);

  std::vector<GLfloat> vertices = {-1, -1, 0, 1, -1, 0, 0, 1, 0};

  GLuint buf;
  glGenBuffers(1, &buf);
  glBindBuffer(GL_ARRAY_BUFFER, buf);
  glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(),
               vertices.data(), GL_STATIC_DRAW);

  auto programID = ([=](std::string vs, std::string fs) {
    auto vsID = glCreateShader(GL_VERTEX_SHADER);
    auto fsID = glCreateShader(GL_FRAGMENT_SHADER);

    auto readFile = [=](std::string s) {
      auto f = std::ifstream(s);
      return std::string(std::istreambuf_iterator<char>(f),
                         std::istreambuf_iterator<char>());
    };

    auto programID = glCreateProgram();
    for (auto s : ([=](std::vector<std::pair<GLuint, std::string>> v) {
           std::vector<std::pair<GLuint, std::string>> ov;
           for (auto a : v) {
             ov.push_back({a.first, readFile(a.second)});
           }
           return ov;
         })({{vsID, vs}, {fsID, fs}})) {
      auto sc = s.second.c_str();
      glShaderSource(s.first, 1, &sc, nullptr);
      glCompileShader(s.first);
      GLint res;
      glGetShaderiv(s.first, GL_COMPILE_STATUS, &res);
      int ll;
      glGetShaderiv(s.first, GL_INFO_LOG_LENGTH, &ll);
      if (ll > 0) {
        auto v = std::vector<char>(ll + 1);
        glGetShaderInfoLog(s.first, ll, nullptr, v.data());
        throw std::runtime_error("error compiling shader: " +
                                 std::string(v.begin(), v.end()));
      }
      glAttachShader(programID, s.first);
    }
    glLinkProgram(programID);

    GLint res;
    glGetProgramiv(programID, GL_COMPILE_STATUS, &res);
    int ll;
    glGetShaderiv(programID, GL_INFO_LOG_LENGTH, &ll);
    if (ll > 0) {
      auto v = std::vector<char>(ll + 1);
      glGetProgramInfoLog(programID, ll, nullptr, v.data());
      throw std::runtime_error("error linking program: " +
                               std::string(v.begin(), v.end()));
    }

    for (auto s : std::vector<GLuint>({vsID, fsID})) {
      glDetachShader(programID, s);
      glDeleteShader(s);
    }

    return programID;

  })("shaders/triangle.vert", "shaders/triangle.frag");

  do {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, buf);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, static_cast<void *>(0));
    glUseProgram(programID);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDisableVertexAttribArray(0);

    glfwSwapBuffers(window);
    glfwPollEvents();

  } // Check if the ESC key was pressed or the window was closed
  while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
         !glfwWindowShouldClose(window));
}
<commit_msg>simple graphics working<commit_after>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

#include <fstream>
#include <iostream>
#include <stdexcept>
#include <streambuf>
#include <vector>

int main() {
  if (!glfwInit()) {
    throw std::runtime_error("glfw initialization failed");
  }

  glfwWindowHint(GLFW_SAMPLES, 4);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

  auto window = glfwCreateWindow(1024, 768, "Tutorial 01", nullptr, nullptr);
  if (window == nullptr) {
    glfwTerminate();
    throw std::runtime_error(
        "failed to open glfw window. If you have an Intel GPU, they "
        "are not 3.3 compatible. Try the 2.1 version of the tutorials.");
  }
  glfwMakeContextCurrent(window);
  glewExperimental = true;
  if (glewInit() != GLEW_OK) {
    throw std::runtime_error("failed to initialize glew");
  }

  glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);

  GLuint vaID;
  glGenVertexArrays(1, &vaID);
  glBindVertexArray(vaID);

  std::vector<GLfloat> vertices = {-1, -1, 0, 1, -1, 0, 0, 1, 0};

  GLuint buf;
  glGenBuffers(1, &buf);
  glBindBuffer(GL_ARRAY_BUFFER, buf);
  glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertices.size(),
               vertices.data(), GL_STATIC_DRAW);

  auto programID = ([=](std::string vs, std::string fs) {
    auto vsID = glCreateShader(GL_VERTEX_SHADER);
    auto fsID = glCreateShader(GL_FRAGMENT_SHADER);

    auto readFile = [=](std::string s) {
      auto f = std::ifstream(s);
      return std::string(std::istreambuf_iterator<char>(f),
                         std::istreambuf_iterator<char>());
    };

    auto programID = glCreateProgram();
    for (auto s : ([=](std::vector<std::pair<GLuint, std::string>> v) {
           std::vector<std::pair<GLuint, std::string>> ov;
           for (auto a : v) {
             ov.push_back({a.first, readFile(a.second)});
           }
           return ov;
         })({{vsID, vs}, {fsID, fs}})) {
      auto sc = s.second.c_str();
      glShaderSource(s.first, 1, &sc, nullptr);
      glCompileShader(s.first);
      GLint res;
      glGetShaderiv(s.first, GL_COMPILE_STATUS, &res);
      int ll;
      glGetShaderiv(s.first, GL_INFO_LOG_LENGTH, &ll);
      if (!res) {
        auto v = std::vector<char>(ll + 1);
        glGetShaderInfoLog(s.first, ll, nullptr, v.data());
        throw std::runtime_error("error compiling shader: " +
                                 std::string(v.begin(), v.end()));
      }
      glAttachShader(programID, s.first);
    }
    glLinkProgram(programID);

    GLint res;
    glGetProgramiv(programID, GL_COMPILE_STATUS, &res);
    int ll;
    glGetShaderiv(programID, GL_INFO_LOG_LENGTH, &ll);
    if (!res) {
      auto v = std::vector<char>(ll + 1);
      glGetProgramInfoLog(programID, ll, nullptr, v.data());
      throw std::runtime_error("error linking program: " +
                               std::string(v.begin(), v.end()));
    }

    for (auto s : std::vector<GLuint>({vsID, fsID})) {
      glDetachShader(programID, s);
      glDeleteShader(s);
    }

    return programID;

  })("shaders/triangle.vert", "shaders/triangle.frag");

  do {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, buf);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, static_cast<void *>(0));
    glUseProgram(programID);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDisableVertexAttribArray(0);

    glfwSwapBuffers(window);
    glfwPollEvents();

  } // Check if the ESC key was pressed or the window was closed
  while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
         !glfwWindowShouldClose(window));
}
<|endoftext|>


<commit_before>#ifndef ITER_GROUP_BY_HPP_
#define ITER_GROUP_BY_HPP_

#include "iterbase.hpp"

#include <type_traits>
#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container&&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T>, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container&&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T>, KF);

            using key_func_ret = typename
                std::result_of<KeyFunc(iterator_deref<Container>)>::type;

            GroupBy(Container&& container, KeyFunc key_func)
                : container(std::forward<Container>(container)),
                key_func(key_func)
            { }

        public:
            GroupBy() = delete;
            GroupBy(const GroupBy&) = delete;
            GroupBy& operator=(const GroupBy&) = delete;
            GroupBy& operator=(GroupBy&&) = delete;

            GroupBy(GroupBy&&) = default;

            class Iterator;
            class Group;

        private:
            using KeyGroupPair =
                std::pair<key_func_ret, Group>;
        public:

            class Iterator
                : public std::iterator<std::input_iterator_tag, KeyGroupPair>
            {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_iter_peek;
                    iterator_type<Container> sub_end;
                    KeyFunc key_func;

                public:
                    Iterator (iterator_type<Container> si,
                              iterator_type<Container> end,
                              KeyFunc key_func)
                        : sub_iter{si},
                        sub_end{end},
                        key_func(key_func)
                    { }

                    KeyGroupPair operator*() {
                        return KeyGroupPair(
                                this->key_func(*this->sub_iter),
                                Group(
                                    *this,
                                    this->key_func(*this->sub_iter)));
                    }

                    Iterator& operator++() {
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator&) const {
                        return !this->exhausted();
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                        }
                    }

                    bool exhausted() const {
                        return !(this->sub_iter != this->sub_end);
                    }

                    iterator_deref<Container> current() {
                        return *this->sub_iter;
                    }

                    key_func_ret next_key() {
                        return this->key_func(*this->sub_iter);
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator& owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    bool completed = false;

                    Group(Iterator& owner, key_func_ret key) :
                        owner(owner),
                        key(key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // move-constructible, non-copy-constructible,
                    // non-assignable
                    Group() = delete;
                    Group(const Group&) = delete;
                    Group& operator=(const Group&) = delete;
                    Group& operator=(Group&&) = delete;

                    Group(Group&& other)
                            : owner{other.owner},
                            key{other.key},
                            completed{other.completed} {
                        other.completed = true;
                    }

                    class GroupIterator
                        : public std::iterator<std::input_iterator_tag,
                                iterator_traits_deref<Container>>
                    {
                        private:
                            key_func_ret key;
                            Group *group_p;

                            bool not_at_end() {
                                return !this->group_p->owner.exhausted()&&
                                    this->group_p->owner.next_key() == this->key;
                            }

                        public:
                            GroupIterator(Group *in_group_p,
                                          key_func_ret key)
                                : key{key},
                                group_p{in_group_p}
                            { }

                            bool operator!=(const GroupIterator& other) const {
                                return !(*this == other);
                            }

                            bool operator==(const GroupIterator& other) const {
                                return this->group_p == other.group_p;
                            }

                            GroupIterator& operator++() {
                                this->group_p->owner.increment_iterator();
                                if (!this->not_at_end()) {
                                    this->group_p->completed = true;
                                    this->group_p = nullptr;
                                }
                                return *this;
                            }

                            GroupIterator operator++(int) {
                                auto ret = *this;
                                ++*this;
                                return ret;
                            }

                            iterator_deref<Container> operator*() {
                                return this->group_p->owner.current();
                            }
                    };

                    GroupIterator begin() {
                        return {this, key};
                    }

                    GroupIterator end() {
                        return {nullptr, key};
                    }

            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->key_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->key_func};
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container&& container, KeyFunc key_func) {
        return {std::forward<Container>(container), key_func};
    }

    template <typename Container>
    auto groupby(Container&& container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> il, KeyFunc key_func) {
        return {std::move(il), key_func};
    }

    template <typename T>
    auto groupby(std::initializer_list<T> il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif
<commit_msg>iterators are actually compared<commit_after>#ifndef ITER_GROUP_BY_HPP_
#define ITER_GROUP_BY_HPP_

#include "iterbase.hpp"

#include <type_traits>
#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container&&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T>, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container&&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T>, KF);

            using key_func_ret = typename
                std::result_of<KeyFunc(iterator_deref<Container>)>::type;

            GroupBy(Container&& container, KeyFunc key_func)
                : container(std::forward<Container>(container)),
                key_func(key_func)
            { }

        public:
            GroupBy() = delete;
            GroupBy(const GroupBy&) = delete;
            GroupBy& operator=(const GroupBy&) = delete;
            GroupBy& operator=(GroupBy&&) = delete;

            GroupBy(GroupBy&&) = default;

            class Iterator;
            class Group;

        private:
            using KeyGroupPair =
                std::pair<key_func_ret, Group>;
        public:

            class Iterator
                : public std::iterator<std::input_iterator_tag, KeyGroupPair>
            {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_iter_peek;
                    iterator_type<Container> sub_end;
                    KeyFunc key_func;

                public:
                    Iterator (iterator_type<Container> si,
                              iterator_type<Container> end,
                              KeyFunc key_func)
                        : sub_iter{si},
                        sub_end{end},
                        key_func(key_func)
                    { }

                    KeyGroupPair operator*() {
                        return {
                            this->key_func(*this->sub_iter),
                            Group{*this, this->key_func(*this->sub_iter)}
                        };
                    }

                    Iterator& operator++() {
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

                    bool operator==(const Iterator& other) const {
                        return !(*this != other);
                    }

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                        }
                    }

                    bool exhausted() const {
                        return !(this->sub_iter != this->sub_end);
                    }

                    iterator_deref<Container> current() {
                        return *this->sub_iter;
                    }

                    key_func_ret next_key() {
                        return this->key_func(*this->sub_iter);
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator& owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    bool completed = false;

                    Group(Iterator& owner, key_func_ret key) :
                        owner(owner),
                        key(key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // move-constructible, non-copy-constructible,
                    // non-assignable
                    Group() = delete;
                    Group(const Group&) = delete;
                    Group& operator=(const Group&) = delete;
                    Group& operator=(Group&&) = delete;

                    Group(Group&& other)
                            : owner{other.owner},
                            key{other.key},
                            completed{other.completed} {
                        other.completed = true;
                    }

                    class GroupIterator
                        : public std::iterator<std::input_iterator_tag,
                                iterator_traits_deref<Container>>
                    {
                        private:
                            key_func_ret key;
                            Group *group_p;

                            bool not_at_end() {
                                return !this->group_p->owner.exhausted()&&
                                    this->group_p->owner.next_key() == this->key;
                            }

                        public:
                            GroupIterator(Group *in_group_p,
                                          key_func_ret key)
                                : key{key},
                                group_p{in_group_p}
                            { }

                            bool operator!=(const GroupIterator& other) const {
                                return !(*this == other);
                            }

                            bool operator==(const GroupIterator& other) const {
                                return this->group_p == other.group_p;
                            }

                            GroupIterator& operator++() {
                                this->group_p->owner.increment_iterator();
                                if (!this->not_at_end()) {
                                    this->group_p->completed = true;
                                    this->group_p = nullptr;
                                }
                                return *this;
                            }

                            GroupIterator operator++(int) {
                                auto ret = *this;
                                ++*this;
                                return ret;
                            }

                            iterator_deref<Container> operator*() {
                                return this->group_p->owner.current();
                            }
                    };

                    GroupIterator begin() {
                        return {this, key};
                    }

                    GroupIterator end() {
                        return {nullptr, key};
                    }

            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->key_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->key_func};
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container&& container, KeyFunc key_func) {
        return {std::forward<Container>(container), key_func};
    }

    template <typename Container>
    auto groupby(Container&& container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> il, KeyFunc key_func) {
        return {std::move(il), key_func};
    }

    template <typename T>
    auto groupby(std::initializer_list<T> il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif
<|endoftext|>


<commit_before>/*!
\file
	\brief
		Om header file.
	\version
		0.1.2
	\date
		2012-2013
	\copyright
		Copyright (c) Sparist. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License, Version 1.0, which accompanies this distribution.
	\authors
		Jason Erb - Initial API, implementation, and documentation.
*/

#ifndef Om_Element_

	#define Om_Element_ \
	Om::Element

	#include "om/program.hpp"

namespace Om {

	// MARK: - Om::Element

	/*!
	\brief
		A Program that contains a single "elemental" item (or none, when IsEmpty() returns true).

	Elemental items can be atomic (Atom) or non-atomic (Operand).
	*/
	class Element:
	public Program {

	public: // MARK: public (non-static)

		virtual ~Element() = 0;

		/*!
		\return
			The "wrapped" Program (Null if none).
		*/
		virtual Program & operator *() = 0;

		/*!
		\overload
		*/
		virtual Program const & operator *() const = 0;

		Program * operator ->();

		Program const * operator ->() const;

		using Program::Equals;

		virtual bool Equals(Element const &) const = 0;

		using Program::GetElementRange;

		/*!
		\return
			An Element range containing only this Element.
		*/
		virtual std::auto_ptr<
			Source<Element>
		> GetElementRange() = 0;

		/*!
		\return
			True if the Element could be merged.
		*/
		virtual bool Merge(Operator &);

		/*!
		\overload
		*/
		virtual bool Merge(Operator const &);

		/*!
		\overload
		*/
		virtual bool Merge(Separator &);

		/*!
		\overload
		*/
		virtual bool Merge(Separator const &);

	private: // MARK: private (non-static)

		Element & operator =(Element const &);

	};

	// MARK: - Om::

	bool operator ==(
		Element const &,
		Element const &
	);

	bool operator !=(
		Element const &,
		Element const &
	);

	/*!
	\return
		An owner pointer to a new copy.
	\note
		Required by boost::ptr_container classes.
	*/
	Element * new_clone(Element const &);

}

	#include "om/element.cpp"

#endif
<commit_msg>Removed unnecessary comment.<commit_after>/*!
\file
	\brief
		Om header file.
	\version
		0.1.2
	\date
		2012-2013
	\copyright
		Copyright (c) Sparist. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License, Version 1.0, which accompanies this distribution.
	\authors
		Jason Erb - Initial API, implementation, and documentation.
*/

#ifndef Om_Element_

	#define Om_Element_ \
	Om::Element

	#include "om/program.hpp"

namespace Om {

	// MARK: - Om::Element

	/*!
	\brief
		A Program that contains a single "elemental" item (or none, when IsEmpty() returns true).
	*/
	class Element:
	public Program {

	public: // MARK: public (non-static)

		virtual ~Element() = 0;

		/*!
		\return
			The "wrapped" Program (Null if none).
		*/
		virtual Program & operator *() = 0;

		/*!
		\overload
		*/
		virtual Program const & operator *() const = 0;

		Program * operator ->();

		Program const * operator ->() const;

		using Program::Equals;

		virtual bool Equals(Element const &) const = 0;

		using Program::GetElementRange;

		/*!
		\return
			An Element range containing only this Element.
		*/
		virtual std::auto_ptr<
			Source<Element>
		> GetElementRange() = 0;

		/*!
		\return
			True if the Element could be merged.
		*/
		virtual bool Merge(Operator &);

		/*!
		\overload
		*/
		virtual bool Merge(Operator const &);

		/*!
		\overload
		*/
		virtual bool Merge(Separator &);

		/*!
		\overload
		*/
		virtual bool Merge(Separator const &);

	private: // MARK: private (non-static)

		Element & operator =(Element const &);

	};

	// MARK: - Om::

	bool operator ==(
		Element const &,
		Element const &
	);

	bool operator !=(
		Element const &,
		Element const &
	);

	/*!
	\return
		An owner pointer to a new copy.
	\note
		Required by boost::ptr_container classes.
	*/
	Element * new_clone(Element const &);

}

	#include "om/element.cpp"

#endif
<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <fnordmetric/sql/parser/token.h>
#include <fnordmetric/util/runtimeexception.h>
#include <fnordmetric/util/inspect.h>
#include <string.h>

namespace fnordmetric {
namespace query {

Token::Token(kTokenType token_type) :
    type_(token_type) {}

Token::Token(
    kTokenType token_type,
    const char* data,
    size_t len) :
    type_(token_type) {
  if (data != nullptr) {
    str_ = std::string(data, len);
  }
}

Token::Token(
    kTokenType token_type,
    const std::string& str) :
    type_(token_type),
    str_(str) {}

Token::Token(const Token& copy) :
    type_(copy.type_),
    str_(copy.str_) {}

void Token::debugPrint() const {
  if (str_.size() == 0) {
    printf("%s\n", getTypeName(type_));
  } else {
    printf("%s(%s)\n", getTypeName(type_), str_.c_str());
  }
}

const char* Token::getTypeName(kTokenType type) {
  switch (type) {
    case T_SELECT:
      return "T_SELECT";

    case T_FROM:
      return "T_FROM";

    case T_WHERE:
      return "T_WHERE";

    case T_GROUP:
      return "T_GROUP";

    case T_BY:
      return "T_BY";

    case T_HAVING:
      return "T_HAVING";

    case T_AS:
      return "T_AS";

    case T_ASC:
      return "T_ASC";

    case T_DESC:
      return "T_DESC";

    case T_COMMA:
      return "T_COMMA";

    case T_DOT:
      return "T_DOT";

    case T_SEMICOLON:
      return "T_SEMICOLON";

    case T_LPAREN:
      return "T_LPAREN";

    case T_RPAREN:
      return "T_RPAREN";

    case T_EQUAL:
      return "T_EQUAL";

    case T_PLUS:
      return "T_PLUS";

    case T_MINUS:
      return "T_MINUS";

    case T_ASTERISK:
      return "T_ASTERISK";

    case T_NOT:
      return "T_NOT";

    case T_NUMERIC:
      return "T_NUMERIC";

    case T_IDENTIFIER:
      return "T_IDENTIFIER";

    default:
      return "T_UNKNOWN_TOKEN";
  }
}

Token::kTokenType Token::getType() const {
  return type_;
}

bool Token::operator==(const std::string& string) const {
  if (str_.size() != string.size()) {
    return false;
  }

  return strncasecmp(str_.c_str(), string.c_str(), string.size()) == 0;
}

bool Token::operator==(kTokenType type) const {
  return type_ == type;
}

bool Token::operator==(const Token& other) const {
  if (type_ != other.type_) {
    return false;
  }

  return str_ == other.str_;
}

int64_t Token::getInteger() const {
  return std::stoi(str_); // FIXPAUL catch errors
}

const std::string Token::getString() const {
  return str_;
}

} // namespace query
} // namespace fnordmetric

template <>
std::string fnord::util::inspect<
    fnordmetric::query::Token::kTokenType>(
    const fnordmetric::query::Token::kTokenType& value) {
  return fnordmetric::query::Token::getTypeName(value);
}

template <>
std::string fnord::util::inspect<
    fnordmetric::query::Token>(
    const fnordmetric::query::Token& value) {
  return fnordmetric::query::Token::getTypeName(value.getType());
}
<commit_msg>token reverse mapping<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <fnordmetric/sql/parser/token.h>
#include <fnordmetric/util/runtimeexception.h>
#include <fnordmetric/util/inspect.h>
#include <string.h>

namespace fnordmetric {
namespace query {

Token::Token(kTokenType token_type) :
    type_(token_type) {}

Token::Token(
    kTokenType token_type,
    const char* data,
    size_t len) :
    type_(token_type) {
  if (data != nullptr) {
    str_ = std::string(data, len);
  }
}

Token::Token(
    kTokenType token_type,
    const std::string& str) :
    type_(token_type),
    str_(str) {}

Token::Token(const Token& copy) :
    type_(copy.type_),
    str_(copy.str_) {}

void Token::debugPrint() const {
  if (str_.size() == 0) {
    printf("%s\n", getTypeName(type_));
  } else {
    printf("%s(%s)\n", getTypeName(type_), str_.c_str());
  }
}

const char* Token::getTypeName(kTokenType type) {
  switch (type) {
    case T_SELECT: return "T_SELECT";
    case T_FROM: return "T_FROM";
    case T_WHERE: return "T_WHERE";
    case T_GROUP: return "T_GROUP";
    case T_ORDER: return "T_ORDER";
    case T_BY: return "T_BY";
    case T_HAVING: return "T_HAVING";
    case T_LIMIT: return "T_LIMIT";
    case T_OFFSET: return "T_OFFSET";
    case T_ASC: return "T_ASC";
    case T_DESC: return "T_DESC";
    case T_COMMA: return "T_COMMA";
    case T_DOT: return "T_DOT";
    case T_IDENTIFIER: return "T_IDENTIFIER";
    case T_STRING: return "T_STRING";
    case T_NUMERIC: return "T_NUMERIC";
    case T_SEMICOLON: return "T_SEMICOLON";
    case T_LPAREN: return "T_LPAREN";
    case T_RPAREN: return "T_RPAREN";
    case T_AND: return "T_AND";
    case T_OR: return "T_OR";
    case T_EQUAL: return "T_EQUAL";
    case T_NEQUAL: return "T_NEQUAL";
    case T_PLUS: return "T_PLUS";
    case T_MINUS: return "T_MINUS";
    case T_ASTERISK: return "T_ASTERISK";
    case T_SLASH: return "T_SLASH";
    case T_AS: return "T_AS";
    case T_NOT: return "T_NOT";
    case T_TRUE: return "T_TRUE";
    case T_FALSE: return "T_FALSE";
    case T_BANG: return "T_BANG";
    case T_CIRCUMFLEX: return "T_CIRCUMFLEX";
    case T_TILDE: return "T_TILDE";
    case T_PERCENT: return "T_PERCENT";
    case T_DIV: return "T_DIV";
    case T_MOD: return "T_MOD";
    case T_AMPERSAND: return "T_AMPERSAND";
    case T_PIPE: return "T_PIPE";
    case T_LSHIFT: return "T_LSHIFT";
    case T_RSHIFT: return "T_RSHIFT";
    case T_LT: return "T_LT";
    case T_LTE: return "T_LTE";
    case T_GT: return "T_GT";
    case T_GTE: return "T_GTE";
    case T_BEGIN: return "T_BEGIN";
    case T_CREATE: return "T_CREATE";
    case T_WITH: return "T_WITH";
    case T_IMPORT: return "T_IMPORT";
    case T_TABLE: return "T_TABLE";
    case T_ON: return "T_ON";
    case T_OFF: return "T_OFF";
    case T_EOF: return "T_EOF";
    case T_DRAW: return "T_DRAW";
    case T_LINECHART: return "T_LINECHART";
    case T_AREACHART: return "T_AREACHART";
    case T_BARCHART: return "T_BARCHART";
    case T_POINTCHART: return "T_POINTCHART";
    case T_HEATMAP: return "T_HEATMAP";
    case T_HISTOGRAM: return "T_HISTOGRAM";
    case T_AXIS: return "T_AXIS";
    case T_TOP: return "T_TOP";
    case T_RIGHT: return "T_RIGHT";
    case T_BOTTOM: return "T_BOTTOM";
    case T_LEFT: return "T_LEFT";
    case T_ORIENTATION: return "T_ORIENTATION";
    case T_HORIZONTAL: return "T_HORIZONTAL";
    case T_VERTICAL: return "T_VERTICAL";
    case T_STACKED: return "T_STACKED";
    case T_XDOMAIN: return "T_XDOMAIN";
    case T_YDOMAIN: return "T_YDOMAIN";
    case T_ZDOMAIN: return "T_ZDOMAIN";
    case T_XGRID: return "T_XGRID";
    case T_YGRID: return "T_YGRID";
    case T_LOGARITHMIC: return "T_LOGARITHMIC";
    case T_INVERT: return "T_INVERT";
    case T_TITLE: return "T_TITLE";
    case T_SUBTITLE: return "T_SUBTITLE";
    case T_GRID: return "T_GRID";
    case T_LABELS: return "T_LABELS";
    case T_TICKS: return "T_TICKS";
    case T_INSIDE: return "T_INSIDE";
    case T_OUTSIDE: return "T_OUTSIDE";
    case T_ROTATE: return "T_ROTATE";
    case T_LEGEND: return "T_LEGEND";
    case T_OVER: return "T_OVER";
    case T_TIMEWINDOW: return "T_TIMEWINDOW";
    default: return "T_UNKNOWN_TOKEN";
  }
}

Token::kTokenType Token::getType() const {
  return type_;
}

bool Token::operator==(const std::string& string) const {
  if (str_.size() != string.size()) {
    return false;
  }

  return strncasecmp(str_.c_str(), string.c_str(), string.size()) == 0;
}

bool Token::operator==(kTokenType type) const {
  return type_ == type;
}

bool Token::operator==(const Token& other) const {
  if (type_ != other.type_) {
    return false;
  }

  return str_ == other.str_;
}

int64_t Token::getInteger() const {
  return std::stoi(str_); // FIXPAUL catch errors
}

const std::string Token::getString() const {
  return str_;
}

} // namespace query
} // namespace fnordmetric

template <>
std::string fnord::util::inspect<
    fnordmetric::query::Token::kTokenType>(
    const fnordmetric::query::Token::kTokenType& value) {
  return fnordmetric::query::Token::getTypeName(value);
}

template <>
std::string fnord::util::inspect<
    fnordmetric::query::Token>(
    const fnordmetric::query::Token& value) {
  return fnordmetric::query::Token::getTypeName(value.getType());
}
<|endoftext|>


<commit_before>#include "GlobalParamsBlock.h"

template<>
InputParameters validParams<GlobalParamsBlock>()
{
  InputParameters params;
  std::vector<std::string> blocks(1);
  blocks[0] = "__all__";

  /* GlobalParams should not have children or other standard block attributes */
  params.addPrivateParam<std::vector<std::string> >("active", blocks);
  params.addPrivateParam<ParserBlock *>("parent");
  params.addPrivateParam<Parser *>("parser_handle");
  return params;
}

GlobalParamsBlock::GlobalParamsBlock(std::string name, MooseSystem & moose_system, InputParameters params)
  :ParserBlock(name, moose_system, params)
{}

void
GlobalParamsBlock::execute()
{
#ifdef DEBUG
  std::cerr << "Inside the GlobalParamsBlock Object\n";
#endif

  visitChildren();
}

<commit_msg>Adding "type" to GlobalParams to fix syntax generation script<commit_after>#include "GlobalParamsBlock.h"

template<>
InputParameters validParams<GlobalParamsBlock>()
{
  InputParameters params;
  std::vector<std::string> blocks(1);
  blocks[0] = "__all__";

  /* GlobalParams should not have children or other standard public block attributes */
  params.addPrivateParam<std::vector<std::string> >("active", blocks);
  params.addPrivateParam<ParserBlock *>("parent");
  params.addPrivateParam<Parser *>("parser_handle");
  params.addPrivateParam<std::string>("type", "GlobalParams");
  return params;
}

GlobalParamsBlock::GlobalParamsBlock(std::string name, MooseSystem & moose_system, InputParameters params)
  :ParserBlock(name, moose_system, params)
{}

void
GlobalParamsBlock::execute()
{
#ifdef DEBUG
  std::cerr << "Inside the GlobalParamsBlock Object\n";
#endif

  visitChildren();
}

<|endoftext|>


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

#include "parser.h"

#include <ThreadWeaver/ThreadWeaver>
#include <KFormat>
#include <KLocalizedString>

#include <QTextStream>

#include "../accumulatedtracedata.h"

#include <vector>

using namespace std;

namespace {
struct ParserData final : public AccumulatedTraceData
{
    ParserData()
    {
        chartData.push_back({0, 0, 0, 0});
    }

    void handleTimeStamp(size_t /*newStamp*/, size_t oldStamp)
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
        chartData.push_back({oldStamp, maxLeakedSinceLastTimeStamp, totalAllocations, totalAllocated});
        maxLeakedSinceLastTimeStamp = 0;
    }

    void handleAllocation()
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
    }

    void handleDebuggee(const char* command)
    {
        debuggee = command;
    }

    string debuggee;

    ChartData chartData;
    size_t maxLeakedSinceLastTimeStamp = 0;
};

QString generateSummary(const ParserData& data)
{
    QString ret;
    KFormat format;
    QTextStream stream(&ret);
    const double totalTimeS = 0.001 * data.totalTime;
    stream << "<qt>"
           << i18n("debuggee: %1", QString::fromStdString(data.debuggee)) << "
"
           // xgettext:no-c-format
           << i18n("total runtime: %1s", totalTimeS) << "
"
           << i18n("bytes allocated in total (ignoring deallocations): %1 (%2/s)",
                   format.formatByteSize(data.totalAllocated, 2), format.formatByteSize(data.totalAllocated / totalTimeS)) << "
"
           << i18n("calls to allocation functions: %1 (%2/s)",
                   data.totalAllocations, quint64(data.totalAllocations / totalTimeS)) << "
"
           << i18n("peak heap memory consumption: %1", format.formatByteSize(data.peak)) << "
"
           << i18n("total memory leaked: %1", format.formatByteSize(data.leaked)) << "
";
    stream << "</qt>";
    return ret;
}

struct StringCache
{
    StringCache(const AccumulatedTraceData& data)
    {
        m_strings.resize(data.strings.size());
        transform(data.strings.begin(), data.strings.end(),
                  m_strings.begin(), [] (const string& str) { return QString::fromStdString(str); });
    }

    QString func(const InstructionPointer& ip) const
    {
        if (ip.functionIndex) {
            // TODO: support removal of template arguments
            return stringify(ip.functionIndex);
        } else {
            return static_cast<QString>(QLatin1String("0x") + QString::number(ip.instructionPointer, 16));
        }
    }

    QString file(const InstructionPointer& ip) const
    {
        if (ip.fileIndex) {
            auto file = stringify(ip.fileIndex);
            return file + QLatin1Char(':') + QString::number(ip.line);
        } else {
            return {};
        }
    }

    QString module(const InstructionPointer& ip) const
    {
        return stringify(ip.moduleIndex);
    }

    QString stringify(const StringIndex index) const
    {
        if (!index || index.index > m_strings.size()) {
            return {};
        } else {
            return m_strings.at(index.index - 1);
        }
    }

    LocationData location(const InstructionPointer& ip) const
    {
        return {func(ip), file(ip), module(ip)};
    }

    vector<QString> m_strings;
};

void setParents(QVector<RowData>& children, const RowData* parent)
{
    for (auto& row: children) {
        row.parent = parent;
        setParents(row.children, &row);
    }
}

QVector<RowData> mergeAllocations(const AccumulatedTraceData& data)
{
    QVector<RowData> topRows;
    StringCache strings(data);
    // merge allocations, leave parent pointers invalid (their location may change)
    for (const auto& allocation : data.allocations) {
        auto traceIndex = allocation.traceIndex;
        auto rows = &topRows;
        while (traceIndex) {
            const auto& trace = data.findTrace(traceIndex);
            const auto& ip = data.findIp(trace.ipIndex);
            // TODO: only store the IpIndex and use that
            auto location = strings.location(ip);
            auto it = lower_bound(rows->begin(), rows->end(), location);
            if (it != rows->end() && it->location == location) {
                it->allocated += allocation.allocated;
                it->allocations += allocation.allocations;
                it->leaked += allocation.leaked;
                it->peak = max(it->peak, static_cast<quint64>(allocation.peak));
            } else {
                it = rows->insert(it, {allocation.allocations, allocation.allocated, allocation.leaked, allocation.peak,
                                        location, nullptr, {}});
            }
            traceIndex = trace.parentIndex;
            rows = &it->children;
        }
    }
    // now set the parents, the data is constant from here on
    setParents(topRows, nullptr);
    return topRows;
}
}

Parser::Parser(QObject* parent)
    : QObject(parent)
{}

Parser::~Parser() = default;

void Parser::parse(const QString& path)
{
    using namespace ThreadWeaver;
    stream() << make_job([=]() {
        ParserData data;
        data.read(path.toStdString());
        emit summaryAvailable(generateSummary(data));
        emit bottomUpDataAvailable(mergeAllocations(data));
        emit chartDataAvailable(data.chartData);
        emit finished();
    });
}
<commit_msg>Also fix building of the gui on 32bit<commit_after>/*
 * Copyright 2015 Milian Wolff <mail@milianw.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "parser.h"

#include <ThreadWeaver/ThreadWeaver>
#include <KFormat>
#include <KLocalizedString>

#include <QTextStream>

#include "../accumulatedtracedata.h"

#include <vector>

using namespace std;

namespace {
struct ParserData final : public AccumulatedTraceData
{
    ParserData()
    {
        chartData.push_back({0, 0, 0, 0});
    }

    void handleTimeStamp(uint64_t /*newStamp*/, uint64_t oldStamp)
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
        chartData.push_back({oldStamp, maxLeakedSinceLastTimeStamp, totalAllocations, totalAllocated});
        maxLeakedSinceLastTimeStamp = 0;
    }

    void handleAllocation()
    {
        maxLeakedSinceLastTimeStamp = max(maxLeakedSinceLastTimeStamp, leaked);
    }

    void handleDebuggee(const char* command)
    {
        debuggee = command;
    }

    string debuggee;

    ChartData chartData;
    uint64_t maxLeakedSinceLastTimeStamp = 0;
};

QString generateSummary(const ParserData& data)
{
    QString ret;
    KFormat format;
    QTextStream stream(&ret);
    const double totalTimeS = 0.001 * data.totalTime;
    stream << "<qt>"
           << i18n("debuggee: %1", QString::fromStdString(data.debuggee)) << "
"
           // xgettext:no-c-format
           << i18n("total runtime: %1s", totalTimeS) << "
"
           << i18n("bytes allocated in total (ignoring deallocations): %1 (%2/s)",
                   format.formatByteSize(data.totalAllocated, 2), format.formatByteSize(data.totalAllocated / totalTimeS)) << "
"
           << i18n("calls to allocation functions: %1 (%2/s)",
                   data.totalAllocations, quint64(data.totalAllocations / totalTimeS)) << "
"
           << i18n("peak heap memory consumption: %1", format.formatByteSize(data.peak)) << "
"
           << i18n("total memory leaked: %1", format.formatByteSize(data.leaked)) << "
";
    stream << "</qt>";
    return ret;
}

struct StringCache
{
    StringCache(const AccumulatedTraceData& data)
    {
        m_strings.resize(data.strings.size());
        transform(data.strings.begin(), data.strings.end(),
                  m_strings.begin(), [] (const string& str) { return QString::fromStdString(str); });
    }

    QString func(const InstructionPointer& ip) const
    {
        if (ip.functionIndex) {
            // TODO: support removal of template arguments
            return stringify(ip.functionIndex);
        } else {
            return static_cast<QString>(QLatin1String("0x") + QString::number(ip.instructionPointer, 16));
        }
    }

    QString file(const InstructionPointer& ip) const
    {
        if (ip.fileIndex) {
            auto file = stringify(ip.fileIndex);
            return file + QLatin1Char(':') + QString::number(ip.line);
        } else {
            return {};
        }
    }

    QString module(const InstructionPointer& ip) const
    {
        return stringify(ip.moduleIndex);
    }

    QString stringify(const StringIndex index) const
    {
        if (!index || index.index > m_strings.size()) {
            return {};
        } else {
            return m_strings.at(index.index - 1);
        }
    }

    LocationData location(const InstructionPointer& ip) const
    {
        return {func(ip), file(ip), module(ip)};
    }

    vector<QString> m_strings;
};

void setParents(QVector<RowData>& children, const RowData* parent)
{
    for (auto& row: children) {
        row.parent = parent;
        setParents(row.children, &row);
    }
}

QVector<RowData> mergeAllocations(const AccumulatedTraceData& data)
{
    QVector<RowData> topRows;
    StringCache strings(data);
    // merge allocations, leave parent pointers invalid (their location may change)
    for (const auto& allocation : data.allocations) {
        auto traceIndex = allocation.traceIndex;
        auto rows = &topRows;
        while (traceIndex) {
            const auto& trace = data.findTrace(traceIndex);
            const auto& ip = data.findIp(trace.ipIndex);
            // TODO: only store the IpIndex and use that
            auto location = strings.location(ip);
            auto it = lower_bound(rows->begin(), rows->end(), location);
            if (it != rows->end() && it->location == location) {
                it->allocated += allocation.allocated;
                it->allocations += allocation.allocations;
                it->leaked += allocation.leaked;
                it->peak = max(it->peak, static_cast<quint64>(allocation.peak));
            } else {
                it = rows->insert(it, {allocation.allocations, allocation.allocated, allocation.leaked, allocation.peak,
                                        location, nullptr, {}});
            }
            traceIndex = trace.parentIndex;
            rows = &it->children;
        }
    }
    // now set the parents, the data is constant from here on
    setParents(topRows, nullptr);
    return topRows;
}
}

Parser::Parser(QObject* parent)
    : QObject(parent)
{}

Parser::~Parser() = default;

void Parser::parse(const QString& path)
{
    using namespace ThreadWeaver;
    stream() << make_job([=]() {
        ParserData data;
        data.read(path.toStdString());
        emit summaryAvailable(generateSummary(data));
        emit bottomUpDataAvailable(mergeAllocations(data));
        emit chartDataAvailable(data.chartData);
        emit finished();
    });
}
<|endoftext|>