<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "op_logical.hxx"

#include "formulagroup.hxx"
#include "document.hxx"
#include "formulacell.hxx"
#include "tokenarray.hxx"
#include "compiler.hxx"
#include "interpre.hxx"
#include <formula/vectortoken.hxx>
#include <sstream>

using namespace formula;

namespace sc { namespace opencl {
void OpAnd::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    double t = 1,tmp=0;\n";
    for(unsigned int j = 0; j< vSubArguments.size(); j++)
    {
        ss << "    double tmp"<<j<<" = 1;\n";
        FormulaToken *tmpCur0 = vSubArguments[j]->GetFormulaToken();
        if(tmpCur0->GetType() == formula::svSingleVectorRef)
        {
#ifdef ISNAN
        const formula::SingleVectorRefToken*pCurDVR= static_cast<const
            formula::SingleVectorRefToken *>(tmpCur0);
        ss<< "    int buffer_len"<<j<<" = "<<pCurDVR->GetArrayLength();
        ss<< ";\n";
        ss <<"    if(gid0 >= buffer_len"<<j<<" || isNan(";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef();
        ss <<"))\n";
        ss <<"        tmp = 1;\n    else\n";
#endif
        ss <<"        tmp = ";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp"<<j<<" = tmp"<<j<<" && tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDouble)
        {
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" && tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDoubleVectorRef)
        {
            const formula::DoubleVectorRefToken*pCurDVR= static_cast<const
            formula::DoubleVectorRefToken *>(tmpCur0);
            size_t nCurWindowSize = pCurDVR->GetArrayLength() <
            pCurDVR->GetRefRowSize() ? pCurDVR->GetArrayLength():
            pCurDVR->GetRefRowSize() ;
            ss << "    for(int i = ";
            if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed()) {
            ss << "gid0; i < " << nCurWindowSize << "; i++) {\n";
            }
            else if(pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed()){
            ss << "0; i < gid0 + " << nCurWindowSize << "; i++) {\n";
            }
            else{
            ss << "0; i < " << nCurWindowSize << "; i++) {\n";
            }
#ifdef ISNAN
            if(!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i+gid0>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 1;\n    else\n";
                }
            else
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 1;\n    else\n";
                }
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" && tmp;\n";
            ss <<"    }\n";
        }
        ss <<"    t = t && tmp"<<j<<";\n";
    }
    ss << "    return t;\n";
    ss << "}\n";
}

void OpOr::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    double t = 0,tmp=0;\n";
    for(unsigned int j = 0; j< vSubArguments.size(); j++)
    {
        ss << "    double tmp"<<j<<" = 0;\n";
        FormulaToken *tmpCur0 = vSubArguments[j]->GetFormulaToken();
        if(tmpCur0->GetType() == formula::svSingleVectorRef)
        {
#ifdef ISNAN
        const formula::SingleVectorRefToken*pCurDVR= static_cast<const
            formula::SingleVectorRefToken *>(tmpCur0);
        ss<< "    int buffer_len"<<j<<" = "<<pCurDVR->GetArrayLength();
        ss<< ";\n";
        ss <<"    if(gid0 >= buffer_len"<<j<<" || isNan(";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef();
        ss <<"))\n";
        ss <<"        tmp = 0;\n    else\n";
#endif
        ss <<"        tmp = ";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp"<<j<<" = tmp"<<j<<" || tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDouble)
        {
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" || tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDoubleVectorRef)
        {
            const formula::DoubleVectorRefToken*pCurDVR= static_cast<const
            formula::DoubleVectorRefToken *>(tmpCur0);
            size_t nCurWindowSize = pCurDVR->GetArrayLength() <
            pCurDVR->GetRefRowSize() ? pCurDVR->GetArrayLength():
            pCurDVR->GetRefRowSize() ;
            ss << "    for(int i = ";
            if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed()) {
            ss << "gid0; i < " << nCurWindowSize << "; i++) {\n";
            }
            else if(pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed()){
            ss << "0; i < gid0 + " << nCurWindowSize << "; i++) {\n";
            }
            else{
            ss << "0; i < " << nCurWindowSize << "; i++) {\n";
            }
#ifdef ISNAN
            if(!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i+gid0>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
            else
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" || tmp;\n";
            ss <<"    }\n";
        }
        ss <<"    t = t || tmp"<<j<<";\n";
    }
    ss << "    return t;\n";
    ss << "}\n";
}
void OpNot::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    double tmp=0;\n";
    FormulaToken *tmpCur0 = vSubArguments[0]->GetFormulaToken();
    if(tmpCur0->GetType() == formula::svSingleVectorRef)
    {
#ifdef ISNAN
        const formula::SingleVectorRefToken*pCurDVR= static_cast<const
            formula::SingleVectorRefToken *>(tmpCur0);
        ss <<"    if(gid0 >= "<<pCurDVR->GetArrayLength()<<" || isNan(";
        ss <<vSubArguments[0]->GenSlidingWindowDeclRef();
        ss <<"))\n";
        ss <<"        tmp = 0;\n    else\n";
#endif
        ss <<"        tmp = ";
        ss <<vSubArguments[0]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp = (tmp == 0.0);\n";
    }
    else if(tmpCur0->GetType() == formula::svDouble)
    {
        ss <<"        tmp = ";
        ss <<vSubArguments[0]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp = (tmp == 0.0);\n";
    }
    ss << "    return tmp;\n";
    ss << "}\n";
}

void OpXor::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    int t = 0,tmp0 = 0;\n";
    ss << "    double tmp = 0;\n";
    for(unsigned int j = 0; j< vSubArguments.size(); j++)
    {
        FormulaToken *tmpCur0 = vSubArguments[j]->GetFormulaToken();
        if(tmpCur0->GetType() == formula::svSingleVectorRef)
        {
#ifdef ISNAN
            const formula::SingleVectorRefToken*pCurDVR= static_cast<const
                formula::SingleVectorRefToken *>(tmpCur0);
            ss <<"    if(gid0 >= "<<pCurDVR->GetArrayLength()<<" || isNan(";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<"))\n";
            ss <<"        tmp = 0;\n    else\n";
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp0 = (tmp != 0);\n";
            ss <<"    t = t ^tmp0;\n";
        }
        else if(tmpCur0->GetType() == formula::svDouble)
        {
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp0 = (tmp != 0);\n";
            ss <<"    t = t ^tmp0;\n";
        }
        else if(tmpCur0->GetType() == formula::svDoubleVectorRef)
        {
            const formula::DoubleVectorRefToken*pCurDVR= static_cast<const
            formula::DoubleVectorRefToken *>(tmpCur0);
            size_t nCurWindowSize = pCurDVR->GetArrayLength() <
            pCurDVR->GetRefRowSize() ? pCurDVR->GetArrayLength():
            pCurDVR->GetRefRowSize() ;
            ss << "    for(int i = ";
            if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed()) {
            ss << "gid0; i < " << nCurWindowSize << "; i++) {\n";
            }
            else if(pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed()){
            ss << "0; i < gid0 + " << nCurWindowSize << "; i++) {\n";
            }
            else{
            ss << "0; i < " << nCurWindowSize << "; i++) {\n";
            }
#ifdef ISNAN
            if(!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i+gid0>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
            else
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp0 = (tmp != 0);\n";
            ss <<"    t = t ^tmp0;\n";
            ss <<"    }\n";
        }
    }
    ss << "    return t;\n";
    ss << "}\n";
}

}}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>GPU Calc: Support nested formula of string compared in AND formula.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "op_logical.hxx"

#include "formulagroup.hxx"
#include "document.hxx"
#include "formulacell.hxx"
#include "tokenarray.hxx"
#include "compiler.hxx"
#include "interpre.hxx"
#include <formula/vectortoken.hxx>
#include <sstream>

using namespace formula;

namespace sc { namespace opencl {
void OpAnd::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    double t = 1,tmp=0;\n";
    for(unsigned int j = 0; j< vSubArguments.size(); j++)
    {
        ss << "    double tmp"<<j<<" = 1;\n";
        FormulaToken *tmpCur0 = vSubArguments[j]->GetFormulaToken();
        if(tmpCur0->GetType() == formula::svSingleVectorRef)
        {
        const formula::SingleVectorRefToken*pCurDVR= static_cast<const
            formula::SingleVectorRefToken *>(tmpCur0);
        ss<< "    int buffer_len"<<j<<" = "<<pCurDVR->GetArrayLength();
        ss<< ";\n";
        ss <<"    if(gid0 >= buffer_len"<<j<<" || isNan(";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef();
        ss <<"))\n";
        ss <<"        tmp = 1;\n    else\n";
        ss <<"        tmp = ";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp"<<j<<" = tmp"<<j<<" && tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDouble)
        {
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" && tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDoubleVectorRef)
        {
            const formula::DoubleVectorRefToken*pCurDVR= static_cast<const
            formula::DoubleVectorRefToken *>(tmpCur0);
            size_t nCurWindowSize = pCurDVR->GetArrayLength() <
            pCurDVR->GetRefRowSize() ? pCurDVR->GetArrayLength():
            pCurDVR->GetRefRowSize() ;
            ss << "    for(int i = ";
            if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed()) {
            ss << "gid0; i < " << nCurWindowSize << "; i++) {\n";
            }
            else if(pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed()){
            ss << "0; i < gid0 + " << nCurWindowSize << "; i++) {\n";
            }
            else{
            ss << "0; i < " << nCurWindowSize << "; i++) {\n";
            }
#ifdef ISNAN
            if(!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i+gid0>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 1;\n    else\n";
                }
            else
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 1;\n    else\n";
                }
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" && tmp;\n";
            ss <<"    }\n";
        }
        else
        {
            ss <<"        tmp"<<j<<" = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
        }
        ss <<"    t = t && tmp"<<j<<";\n";
    }
    ss << "    return t;\n";
    ss << "}\n";
}

void OpOr::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    double t = 0,tmp=0;\n";
    for(unsigned int j = 0; j< vSubArguments.size(); j++)
    {
        ss << "    double tmp"<<j<<" = 0;\n";
        FormulaToken *tmpCur0 = vSubArguments[j]->GetFormulaToken();
        if(tmpCur0->GetType() == formula::svSingleVectorRef)
        {
#ifdef ISNAN
        const formula::SingleVectorRefToken*pCurDVR= static_cast<const
            formula::SingleVectorRefToken *>(tmpCur0);
        ss<< "    int buffer_len"<<j<<" = "<<pCurDVR->GetArrayLength();
        ss<< ";\n";
        ss <<"    if(gid0 >= buffer_len"<<j<<" || isNan(";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef();
        ss <<"))\n";
        ss <<"        tmp = 0;\n    else\n";
#endif
        ss <<"        tmp = ";
        ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp"<<j<<" = tmp"<<j<<" || tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDouble)
        {
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" || tmp;\n";
        }
        else if(tmpCur0->GetType() == formula::svDoubleVectorRef)
        {
            const formula::DoubleVectorRefToken*pCurDVR= static_cast<const
            formula::DoubleVectorRefToken *>(tmpCur0);
            size_t nCurWindowSize = pCurDVR->GetArrayLength() <
            pCurDVR->GetRefRowSize() ? pCurDVR->GetArrayLength():
            pCurDVR->GetRefRowSize() ;
            ss << "    for(int i = ";
            if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed()) {
            ss << "gid0; i < " << nCurWindowSize << "; i++) {\n";
            }
            else if(pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed()){
            ss << "0; i < gid0 + " << nCurWindowSize << "; i++) {\n";
            }
            else{
            ss << "0; i < " << nCurWindowSize << "; i++) {\n";
            }
#ifdef ISNAN
            if(!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i+gid0>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
            else
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp"<<j<<" = tmp"<<j<<" || tmp;\n";
            ss <<"    }\n";
        }
        ss <<"    t = t || tmp"<<j<<";\n";
    }
    ss << "    return t;\n";
    ss << "}\n";
}
void OpNot::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    double tmp=0;\n";
    FormulaToken *tmpCur0 = vSubArguments[0]->GetFormulaToken();
    if(tmpCur0->GetType() == formula::svSingleVectorRef)
    {
#ifdef ISNAN
        const formula::SingleVectorRefToken*pCurDVR= static_cast<const
            formula::SingleVectorRefToken *>(tmpCur0);
        ss <<"    if(gid0 >= "<<pCurDVR->GetArrayLength()<<" || isNan(";
        ss <<vSubArguments[0]->GenSlidingWindowDeclRef();
        ss <<"))\n";
        ss <<"        tmp = 0;\n    else\n";
#endif
        ss <<"        tmp = ";
        ss <<vSubArguments[0]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp = (tmp == 0.0);\n";
    }
    else if(tmpCur0->GetType() == formula::svDouble)
    {
        ss <<"        tmp = ";
        ss <<vSubArguments[0]->GenSlidingWindowDeclRef()<<";\n";
        ss <<"    tmp = (tmp == 0.0);\n";
    }
    ss << "    return tmp;\n";
    ss << "}\n";
}

void OpXor::GenSlidingWindowFunction(std::stringstream &ss,
    const std::string &sSymName, SubArguments &vSubArguments)
{
    ss << "\ndouble " << sSymName;
    ss << "_"<< BinFuncName() <<"(";
    for (unsigned i = 0; i < vSubArguments.size(); i++)
    {
        if (i)
            ss << ",";
        vSubArguments[i]->GenSlidingWindowDecl(ss);
    }
    ss << ") {\n";
    ss << "    int gid0 = get_global_id(0);\n";
    ss << "    int t = 0,tmp0 = 0;\n";
    ss << "    double tmp = 0;\n";
    for(unsigned int j = 0; j< vSubArguments.size(); j++)
    {
        FormulaToken *tmpCur0 = vSubArguments[j]->GetFormulaToken();
        if(tmpCur0->GetType() == formula::svSingleVectorRef)
        {
#ifdef ISNAN
            const formula::SingleVectorRefToken*pCurDVR= static_cast<const
                formula::SingleVectorRefToken *>(tmpCur0);
            ss <<"    if(gid0 >= "<<pCurDVR->GetArrayLength()<<" || isNan(";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<"))\n";
            ss <<"        tmp = 0;\n    else\n";
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp0 = (tmp != 0);\n";
            ss <<"    t = t ^tmp0;\n";
        }
        else if(tmpCur0->GetType() == formula::svDouble)
        {
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp0 = (tmp != 0);\n";
            ss <<"    t = t ^tmp0;\n";
        }
        else if(tmpCur0->GetType() == formula::svDoubleVectorRef)
        {
            const formula::DoubleVectorRefToken*pCurDVR= static_cast<const
            formula::DoubleVectorRefToken *>(tmpCur0);
            size_t nCurWindowSize = pCurDVR->GetArrayLength() <
            pCurDVR->GetRefRowSize() ? pCurDVR->GetArrayLength():
            pCurDVR->GetRefRowSize() ;
            ss << "    for(int i = ";
            if (!pCurDVR->IsStartFixed() && pCurDVR->IsEndFixed()) {
            ss << "gid0; i < " << nCurWindowSize << "; i++) {\n";
            }
            else if(pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed()){
            ss << "0; i < gid0 + " << nCurWindowSize << "; i++) {\n";
            }
            else{
            ss << "0; i < " << nCurWindowSize << "; i++) {\n";
            }
#ifdef ISNAN
            if(!pCurDVR->IsStartFixed() && !pCurDVR->IsEndFixed())
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i+gid0>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
            else
                {
            ss <<"    if(isNan("<<vSubArguments[j]->GenSlidingWindowDeclRef();
            ss <<")||i>="<<pCurDVR->GetArrayLength();
            ss <<")\n";
            ss <<"        tmp = 0;\n    else\n";
                }
#endif
            ss <<"        tmp = ";
            ss <<vSubArguments[j]->GenSlidingWindowDeclRef()<<";\n";
            ss <<"    tmp0 = (tmp != 0);\n";
            ss <<"    t = t ^tmp0;\n";
            ss <<"    }\n";
        }
    }
    ss << "    return t;\n";
    ss << "}\n";
}

}}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <boost/program_options.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "cyclus.h"
#include "hdf5_back.h"
#include "pyne.h"
#include "query_backend.h"
#include "sim_init.h"
#include "sqlite_back.h"
#include "xml_file_loader.h"
#include "xml_flat_loader.h"

namespace po = boost::program_options;
namespace fs = boost::filesystem;

using namespace cyclus;

struct ArgInfo {
  po::variables_map vm;  // holds parsed/specified cli opts and values
  po::options_description desc;  // holds cli opts description;
  bool flat_schema;
  std::string schema_path;
  std::string output_path;
};

// Describes and parses cli arguments. Returns the error code that main should
// return early OR -1 if main should not return early.
int ParseCliArgs(ArgInfo* ai, int argc, char* argv[]);

// Processes and handles args that don't run a simulation. Returns the error
// code that main should return early OR -1 if main should not return early.
int EarlyExitArgs(const ArgInfo& ai);

// Using cli flags, retrieves and sets global params for the simulation.
void GetSimInfo(ArgInfo* ai);

static std::string usage = "Usage:   cyclus [opts] [input-file]";

//-----------------------------------------------------------------------
// Main entry point for the test application...
//-----------------------------------------------------------------------
int main(int argc, char* argv[]) {
  // close all dlopen'd modules AFTER everything else destructs
  DynamicModule::Closer cl;

  // tell ENV the path between the cwd and the cyclus executable
  std::string path = Env::PathBase(argv[0]);

  // tell pyne about the path to nuc data
  Env::SetNucDataPath();

  // handle cli option flags
  ArgInfo ai;
  int ret = ParseCliArgs(&ai, argc, argv);
  if (ret > -1) {
    return ret;
  }
  GetSimInfo(&ai);
  ret = EarlyExitArgs(ai);
  if (ret > -1) {
    return ret;
  }

  // process positional args
  if (!ai.vm.count("input-file")) {
    std::cout << "No input file specified.\n"
              << usage << "\n\n"
              << ai.desc << "\n";
    return 1;
  }
  std::string infile = ai.vm["input-file"].as<std::string>();

  // announce yourself
  std::cout << "              :                                                               " << std::endl;
  std::cout << "          .CL:CC CC             _Q     _Q  _Q_Q    _Q    _Q              _Q   " << std::endl;
  std::cout << "        CC;CCCCCCCC:C;         /_\\)   /_\\)/_/\\\\)  /_\\)  /_\\)            /_\\)  " << std::endl;
  std::cout << "        CCCCCCCCCCCCCl       __O|/O___O|/O_OO|/O__O|/O__O|/O____________O|/O__" << std::endl;
  std::cout << "     CCCCCCf     iCCCLCC     /////////////////////////////////////////////////" << std::endl;
  std::cout << "     iCCCt  ;;;;;.  CCCC                                                      " << std::endl;
  std::cout << "    CCCC  ;;;;;;;;;. CClL.                          c                         " << std::endl;
  std::cout << "   CCCC ,;;       ;;: CCCC  ;                   : CCCCi                       " << std::endl;
  std::cout << "    CCC ;;         ;;  CC   ;;:                CCC`   `C;                     " << std::endl;
  std::cout << "  lCCC ;;              CCCC  ;;;:             :CC .;;. C;   ;    :   ;  :;;   " << std::endl;
  std::cout << "  CCCC ;.              CCCC    ;;;,           CC ;    ; Ci  ;    :   ;  :  ;  " << std::endl;
  std::cout << "   iCC :;               CC       ;;;,        ;C ;       CC  ;    :   ; .      " << std::endl;
  std::cout << "  CCCi ;;               CCC        ;;;.      .C ;       tf  ;    :   ;  ;.    " << std::endl;
  std::cout << "  CCC  ;;               CCC          ;;;;;;; fC :       lC  ;    :   ;    ;:  " << std::endl;
  std::cout << "   iCf ;;               CC         :;;:      tC ;       CC  ;    :   ;     ;  " << std::endl;
  std::cout << "  fCCC :;              LCCf      ;;;:         LC :.  ,: C   ;    ;   ; ;   ;  " << std::endl;
  std::cout << "  CCCC  ;;             CCCC    ;;;:           CCi `;;` CC.  ;;;; :;.;.  ; ,;  " << std::endl;
  std::cout << "    CCl ;;             CC    ;;;;              CCC    CCL                     " << std::endl;
  std::cout << "   tCCC  ;;        ;; CCCL  ;;;                  tCCCCC.                      " << std::endl;
  std::cout << "    CCCC  ;;     :;; CCCCf  ;                     ,L                          " << std::endl;
  std::cout << "     lCCC   ;;;;;;  CCCL                                                      " << std::endl;
  std::cout << "     CCCCCC  :;;  fCCCCC                                                      " << std::endl;
  std::cout << "      . CCCC     CCCC .                                                       " << std::endl;
  std::cout << "       .CCCCCCCCCCCCCi                                                        " << std::endl;
  std::cout << "          iCCCCCLCf                                                           " << std::endl;
  std::cout << "           .  C. ,                                                            " << std::endl;
  std::cout << "              :                                                               " << std::endl;

  // create db backends and recorder
  FullBackend* fback = NULL;
  RecBackend* rback = NULL;
  RecBackend::Deleter bdel;
  Recorder rec;  // must be after backend deleter because ~Rec does flushing

  std::string ext = fs::path(ai.output_path).extension().generic_string();
  std::string stem = fs::path(ai.output_path).stem().generic_string();
  if (ext == ".h5") {
    fback = new Hdf5Back(ai.output_path.c_str());
    rec.RegisterBackend(fback);
    bdel.Add(fback);
  } else {
    fback = new SqliteBack(ai.output_path);
    rec.RegisterBackend(fback);
    bdel.Add(fback);
  }

  // read input file and initialize db from input file
  try {
    if (ai.flat_schema) {
      XMLFlatLoader l(&rec, fback, ai.schema_path, infile);
      l.LoadSim();
    } else {
      XMLFileLoader l(&rec, fback, ai.schema_path, infile);
      l.LoadSim();
    }
  } catch (cyclus::Error e) {
    CLOG(LEV_ERROR) << e.what();
    return 1;
  }

  // initialize sim from output db and run it
  SimInit si;
  si.Init(&rec, fback);
  si.timer()->RunSim();

  rec.Flush();

  std::cout << std::endl;
  std::cout << "Status: Cyclus run successful!" << std::endl;
  std::cout << "Output location: " << ai.output_path << std::endl;
  std::cout << "Simulation ID: " << boost::lexical_cast<std::string>
               (si.context()->sim_id()) << std::endl;

  return 0;
}

int ParseCliArgs(ArgInfo* ai, int argc, char* argv[]) {
  // verbosity help msg
  std::string vmessage = "output log verbosity. Can be text:\n\n";
  vmessage +=
      "   LEV_ERROR (least verbose, default), LEV_WARN, \n"
      "   LEV_INFO1 (through 5), and LEV_DEBUG1 (through 5).\n\n";
  vmessage +=
      "Or an integer:\n\n   0 (LEV_ERROR equiv) through 11 (LEV_DEBUG5 equiv)\n";

  // parse command line options
  ai->desc.add_options()
      ("help,h", "produce help message")
      ("include", "print the cyclus include directory")
      ("version", "print cyclus core and dependency versions and quit")
      ("schema",
       "dump the cyclus master schema including all installed module schemas")
      ("agent-schema", po::value<std::string>(),
       "dump the schema for the named agent")
      ("schema-path", po::value<std::string>(),
       "manually specify the path to the cyclus master schema")
      ("flat-schema", "use the flat master simulation schema")
      ("agent-annotations", po::value<std::string>(),
       "dump the annotations for the named agent")
      ("no-agent", "only print log entries from cyclus core code")
      ("no-mem", "exclude memory log statement from logger output")
      ("verb,v", po::value<std::string>(), vmessage.c_str())
      ("output-path,o", po::value<std::string>(), "output path")
      ("input-file", po::value<std::string>(), "input file")
      ("warn-limit", po::value<unsigned int>(),
       "number of warnings to issue per kind, defaults to 1")
      ("warn-as-error", "throw errors when warnings are issued")
      ;

  po::variables_map vm;
  try {
    po::store(po::parse_command_line(argc, argv, ai->desc), ai->vm);
  } catch(std::exception err) {
    std::cout << "Invalid arguments.\n"
              <<  usage << "\n\n"
              << ai->desc << "\n";
    return 1;
  }
  po::notify(ai->vm);

  po::positional_options_description p;
  p.add("input-file", 1);

  po::store(po::command_line_parser(argc, argv).
            options(ai->desc).positional(p).run(), ai->vm);
  po::notify(ai->vm);
  return -1;
}

int EarlyExitArgs(const ArgInfo& ai) {
  // respond to command line args that don't run a simulation
  if (ai.vm.count("help")) {
    std::cout << usage << "\n\n"
              << ai.desc << "\n";
    return 0;
  } else if (ai.vm.count("version")) {
    std::cout << "Cyclus Core " << version::core()
              << " (" << version::describe() << ")"
              << "\n\nDependencies:\n";
    std::cout << "   Boost    " << version::boost() << "\n";
    std::cout << "   Coin-Cbc " << version::coincbc() << "\n";
    std::cout << "   Hdf5     " << version::hdf5() << "\n";
    std::cout << "   Sqlite3  " << version::sqlite3() << "\n";
    std::cout << "   xml2     " << version::xml2() << "\n";
    return 0;
  } else if (ai.vm.count("include")) {
    std::cout << Env::GetInstallPath() << "/include/cyclus/\n";
    return 0;
  } else if (ai.vm.count("schema")) {
    std::stringstream f;
    LoadStringstreamFromFile(f, ai.schema_path);
    std::cout << f.str() << "\n";
    return 0;
  } else if (ai.vm.count("agent-schema")) {
    std::string name(ai.vm["agent-schema"].as<std::string>());
    try {
      Recorder rec;
      Timer ti;
      Context* ctx = new Context(&ti, &rec);
      Agent* m = DynamicModule::Make(ctx, name);
      std::cout << m->schema();
      ctx->DelAgent(m);
    } catch (cyclus::IOError err) {
      std::cout << err.what() << "\n";
    }
    return 0;
  } else if (ai.vm.count("agent-annotations")) {
    std::string name(ai.vm["agent-annotations"].as<std::string>());
    try {
      Recorder rec;
      Timer ti;
      Context* ctx = new Context(&ti, &rec);
      Agent* m = DynamicModule::Make(ctx, name);
      Json::StyledWriter writer;
      std::cout << writer.write(m->annotations());
      ctx->DelAgent(m);
    } catch (cyclus::IOError err) {
      std::cout << err.what() << "\n";
    }
    return 0;
  }
  return -1;  // main should not return early
}

void GetSimInfo(ArgInfo* ai) {
  // schema info
  ai->flat_schema = ai->vm.count("flat-schema") > 0;
  ai->schema_path = Env::rng_schema(ai->flat_schema);

  // logging params
  if (ai->vm.count("no-agent")) {
    Logger::NoAgent() = true;
  }
  if (ai->vm.count("no-mem")) {
    Logger::NoMem() = true;
  }
  if (ai->vm.count("verb")) {
    std::string v_level = ai->vm["verb"].as<std::string>();
    if (v_level.length() < 3) {
      Logger::ReportLevel() = (LogLevel)strtol(v_level.c_str(), NULL, 10);
    } else {
      Logger::ReportLevel() = Logger::ToLogLevel(v_level);
    }
  }

  // warning params
  if (ai->vm.count("warn-limit"))
    cyclus::warn_limit = ai->vm["warn-limit"].as<unsigned int>();
  if (ai->vm.count("warn-as-error"))
    cyclus::warn_as_error = true;

  // output path
  ai->output_path = "cyclus.sqlite";
  if (ai->vm.count("output-path")) {
    ai->output_path = ai->vm["output-path"].as<std::string>();
  }
}
<commit_msg>removed dead/old rback var from cyclus.cc<commit_after>#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <boost/program_options.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/filesystem.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "cyclus.h"
#include "hdf5_back.h"
#include "pyne.h"
#include "query_backend.h"
#include "sim_init.h"
#include "sqlite_back.h"
#include "xml_file_loader.h"
#include "xml_flat_loader.h"

namespace po = boost::program_options;
namespace fs = boost::filesystem;

using namespace cyclus;

struct ArgInfo {
  po::variables_map vm;  // holds parsed/specified cli opts and values
  po::options_description desc;  // holds cli opts description;
  bool flat_schema;
  std::string schema_path;
  std::string output_path;
};

// Describes and parses cli arguments. Returns the error code that main should
// return early OR -1 if main should not return early.
int ParseCliArgs(ArgInfo* ai, int argc, char* argv[]);

// Processes and handles args that don't run a simulation. Returns the error
// code that main should return early OR -1 if main should not return early.
int EarlyExitArgs(const ArgInfo& ai);

// Using cli flags, retrieves and sets global params for the simulation.
void GetSimInfo(ArgInfo* ai);

static std::string usage = "Usage:   cyclus [opts] [input-file]";

//-----------------------------------------------------------------------
// Main entry point for the test application...
//-----------------------------------------------------------------------
int main(int argc, char* argv[]) {
  // close all dlopen'd modules AFTER everything else destructs
  DynamicModule::Closer cl;

  // tell ENV the path between the cwd and the cyclus executable
  std::string path = Env::PathBase(argv[0]);

  // tell pyne about the path to nuc data
  Env::SetNucDataPath();

  // handle cli option flags
  ArgInfo ai;
  int ret = ParseCliArgs(&ai, argc, argv);
  if (ret > -1) {
    return ret;
  }
  GetSimInfo(&ai);
  ret = EarlyExitArgs(ai);
  if (ret > -1) {
    return ret;
  }

  // process positional args
  if (!ai.vm.count("input-file")) {
    std::cout << "No input file specified.\n"
              << usage << "\n\n"
              << ai.desc << "\n";
    return 1;
  }
  std::string infile = ai.vm["input-file"].as<std::string>();

  // announce yourself
  std::cout << "              :                                                               " << std::endl;
  std::cout << "          .CL:CC CC             _Q     _Q  _Q_Q    _Q    _Q              _Q   " << std::endl;
  std::cout << "        CC;CCCCCCCC:C;         /_\\)   /_\\)/_/\\\\)  /_\\)  /_\\)            /_\\)  " << std::endl;
  std::cout << "        CCCCCCCCCCCCCl       __O|/O___O|/O_OO|/O__O|/O__O|/O____________O|/O__" << std::endl;
  std::cout << "     CCCCCCf     iCCCLCC     /////////////////////////////////////////////////" << std::endl;
  std::cout << "     iCCCt  ;;;;;.  CCCC                                                      " << std::endl;
  std::cout << "    CCCC  ;;;;;;;;;. CClL.                          c                         " << std::endl;
  std::cout << "   CCCC ,;;       ;;: CCCC  ;                   : CCCCi                       " << std::endl;
  std::cout << "    CCC ;;         ;;  CC   ;;:                CCC`   `C;                     " << std::endl;
  std::cout << "  lCCC ;;              CCCC  ;;;:             :CC .;;. C;   ;    :   ;  :;;   " << std::endl;
  std::cout << "  CCCC ;.              CCCC    ;;;,           CC ;    ; Ci  ;    :   ;  :  ;  " << std::endl;
  std::cout << "   iCC :;               CC       ;;;,        ;C ;       CC  ;    :   ; .      " << std::endl;
  std::cout << "  CCCi ;;               CCC        ;;;.      .C ;       tf  ;    :   ;  ;.    " << std::endl;
  std::cout << "  CCC  ;;               CCC          ;;;;;;; fC :       lC  ;    :   ;    ;:  " << std::endl;
  std::cout << "   iCf ;;               CC         :;;:      tC ;       CC  ;    :   ;     ;  " << std::endl;
  std::cout << "  fCCC :;              LCCf      ;;;:         LC :.  ,: C   ;    ;   ; ;   ;  " << std::endl;
  std::cout << "  CCCC  ;;             CCCC    ;;;:           CCi `;;` CC.  ;;;; :;.;.  ; ,;  " << std::endl;
  std::cout << "    CCl ;;             CC    ;;;;              CCC    CCL                     " << std::endl;
  std::cout << "   tCCC  ;;        ;; CCCL  ;;;                  tCCCCC.                      " << std::endl;
  std::cout << "    CCCC  ;;     :;; CCCCf  ;                     ,L                          " << std::endl;
  std::cout << "     lCCC   ;;;;;;  CCCL                                                      " << std::endl;
  std::cout << "     CCCCCC  :;;  fCCCCC                                                      " << std::endl;
  std::cout << "      . CCCC     CCCC .                                                       " << std::endl;
  std::cout << "       .CCCCCCCCCCCCCi                                                        " << std::endl;
  std::cout << "          iCCCCCLCf                                                           " << std::endl;
  std::cout << "           .  C. ,                                                            " << std::endl;
  std::cout << "              :                                                               " << std::endl;

  // create db backends and recorder
  FullBackend* fback = NULL;
  RecBackend::Deleter bdel;
  Recorder rec;  // must be after backend deleter because ~Rec does flushing

  std::string ext = fs::path(ai.output_path).extension().generic_string();
  std::string stem = fs::path(ai.output_path).stem().generic_string();
  if (ext == ".h5") {
    fback = new Hdf5Back(ai.output_path.c_str());
    rec.RegisterBackend(fback);
    bdel.Add(fback);
  } else {
    fback = new SqliteBack(ai.output_path);
    rec.RegisterBackend(fback);
    bdel.Add(fback);
  }

  // read input file and initialize db from input file
  try {
    if (ai.flat_schema) {
      XMLFlatLoader l(&rec, fback, ai.schema_path, infile);
      l.LoadSim();
    } else {
      XMLFileLoader l(&rec, fback, ai.schema_path, infile);
      l.LoadSim();
    }
  } catch (cyclus::Error e) {
    CLOG(LEV_ERROR) << e.what();
    return 1;
  }

  // initialize sim from output db and run it
  SimInit si;
  si.Init(&rec, fback);
  si.timer()->RunSim();

  rec.Flush();

  std::cout << std::endl;
  std::cout << "Status: Cyclus run successful!" << std::endl;
  std::cout << "Output location: " << ai.output_path << std::endl;
  std::cout << "Simulation ID: " << boost::lexical_cast<std::string>
               (si.context()->sim_id()) << std::endl;

  return 0;
}

int ParseCliArgs(ArgInfo* ai, int argc, char* argv[]) {
  // verbosity help msg
  std::string vmessage = "output log verbosity. Can be text:\n\n";
  vmessage +=
      "   LEV_ERROR (least verbose, default), LEV_WARN, \n"
      "   LEV_INFO1 (through 5), and LEV_DEBUG1 (through 5).\n\n";
  vmessage +=
      "Or an integer:\n\n   0 (LEV_ERROR equiv) through 11 (LEV_DEBUG5 equiv)\n";

  // parse command line options
  ai->desc.add_options()
      ("help,h", "produce help message")
      ("include", "print the cyclus include directory")
      ("version", "print cyclus core and dependency versions and quit")
      ("schema",
       "dump the cyclus master schema including all installed module schemas")
      ("agent-schema", po::value<std::string>(),
       "dump the schema for the named agent")
      ("schema-path", po::value<std::string>(),
       "manually specify the path to the cyclus master schema")
      ("flat-schema", "use the flat master simulation schema")
      ("agent-annotations", po::value<std::string>(),
       "dump the annotations for the named agent")
      ("no-agent", "only print log entries from cyclus core code")
      ("no-mem", "exclude memory log statement from logger output")
      ("verb,v", po::value<std::string>(), vmessage.c_str())
      ("output-path,o", po::value<std::string>(), "output path")
      ("input-file", po::value<std::string>(), "input file")
      ("warn-limit", po::value<unsigned int>(),
       "number of warnings to issue per kind, defaults to 1")
      ("warn-as-error", "throw errors when warnings are issued")
      ;

  po::variables_map vm;
  try {
    po::store(po::parse_command_line(argc, argv, ai->desc), ai->vm);
  } catch(std::exception err) {
    std::cout << "Invalid arguments.\n"
              <<  usage << "\n\n"
              << ai->desc << "\n";
    return 1;
  }
  po::notify(ai->vm);

  po::positional_options_description p;
  p.add("input-file", 1);

  po::store(po::command_line_parser(argc, argv).
            options(ai->desc).positional(p).run(), ai->vm);
  po::notify(ai->vm);
  return -1;
}

int EarlyExitArgs(const ArgInfo& ai) {
  // respond to command line args that don't run a simulation
  if (ai.vm.count("help")) {
    std::cout << usage << "\n\n"
              << ai.desc << "\n";
    return 0;
  } else if (ai.vm.count("version")) {
    std::cout << "Cyclus Core " << version::core()
              << " (" << version::describe() << ")"
              << "\n\nDependencies:\n";
    std::cout << "   Boost    " << version::boost() << "\n";
    std::cout << "   Coin-Cbc " << version::coincbc() << "\n";
    std::cout << "   Hdf5     " << version::hdf5() << "\n";
    std::cout << "   Sqlite3  " << version::sqlite3() << "\n";
    std::cout << "   xml2     " << version::xml2() << "\n";
    return 0;
  } else if (ai.vm.count("include")) {
    std::cout << Env::GetInstallPath() << "/include/cyclus/\n";
    return 0;
  } else if (ai.vm.count("schema")) {
    std::stringstream f;
    LoadStringstreamFromFile(f, ai.schema_path);
    std::cout << f.str() << "\n";
    return 0;
  } else if (ai.vm.count("agent-schema")) {
    std::string name(ai.vm["agent-schema"].as<std::string>());
    try {
      Recorder rec;
      Timer ti;
      Context* ctx = new Context(&ti, &rec);
      Agent* m = DynamicModule::Make(ctx, name);
      std::cout << m->schema();
      ctx->DelAgent(m);
    } catch (cyclus::IOError err) {
      std::cout << err.what() << "\n";
    }
    return 0;
  } else if (ai.vm.count("agent-annotations")) {
    std::string name(ai.vm["agent-annotations"].as<std::string>());
    try {
      Recorder rec;
      Timer ti;
      Context* ctx = new Context(&ti, &rec);
      Agent* m = DynamicModule::Make(ctx, name);
      Json::StyledWriter writer;
      std::cout << writer.write(m->annotations());
      ctx->DelAgent(m);
    } catch (cyclus::IOError err) {
      std::cout << err.what() << "\n";
    }
    return 0;
  }
  return -1;  // main should not return early
}

void GetSimInfo(ArgInfo* ai) {
  // schema info
  ai->flat_schema = ai->vm.count("flat-schema") > 0;
  ai->schema_path = Env::rng_schema(ai->flat_schema);

  // logging params
  if (ai->vm.count("no-agent")) {
    Logger::NoAgent() = true;
  }
  if (ai->vm.count("no-mem")) {
    Logger::NoMem() = true;
  }
  if (ai->vm.count("verb")) {
    std::string v_level = ai->vm["verb"].as<std::string>();
    if (v_level.length() < 3) {
      Logger::ReportLevel() = (LogLevel)strtol(v_level.c_str(), NULL, 10);
    } else {
      Logger::ReportLevel() = Logger::ToLogLevel(v_level);
    }
  }

  // warning params
  if (ai->vm.count("warn-limit"))
    cyclus::warn_limit = ai->vm["warn-limit"].as<unsigned int>();
  if (ai->vm.count("warn-as-error"))
    cyclus::warn_as_error = true;

  // output path
  ai->output_path = "cyclus.sqlite";
  if (ai->vm.count("output-path")) {
    ai->output_path = ai->vm["output-path"].as<std::string>();
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 1998 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT)
#ident "$Id: main.cc,v 1.13 1999/02/01 00:26:49 steve Exp $"
#endif

# include  <stdio.h>
# include  <iostream.h>
# include  <fstream>
# include  <queue>
# include  <map>
# include  <unistd.h>
# include  "pform.h"
# include  "netlist.h"
# include  "target.h"

extern void pform_parse();

const char*target = "null";
string start_module = "";

map<string,string> flags;

static void parm_to_flagmap(const string&flag)
{
      string key, value;
      unsigned off = flag.find('=');
      if (off > flag.size()) {
	    key = flag;
	    value = "";

      } else {
	    key = flag.substr(0, off);
	    value = flag.substr(off+1);
      }

      flags[key] = value;
}

extern Design* elaborate(const map<string,Module*>&modules,
			 const map<string,PUdp*>&primitives,
			 const string&root);
extern void emit(ostream&o, const Design*, const char*);

extern void cprop(Design*des);
extern void propinit(Design*des);
extern void sigfold(Design*des);
extern void stupid(Design*des);
extern void nobufz(Design*des);
extern void xnfio(Design*des);

typedef void (*net_func)(Design*);
static struct net_func_map {
      const char*name;
      void (*func)(Design*);
} func_table[] = {
      { "cprop",   &cprop },
      { "nobufz",  &nobufz },
      { "propinit", &propinit },
      { "sigfold", &sigfold },
      { "stupid",  &stupid },
      { "xnfio",   &xnfio },
      { 0, 0 }
};

net_func name_to_net_func(const string&name)
{
      for (unsigned idx = 0 ;  func_table[idx].name ;  idx += 1)
	    if (name == func_table[idx].name)
		  return func_table[idx].func;

      return 0;
}

int main(int argc, char*argv[])
{
      bool dump_flag = false;
      bool help_flag = false;
      const char* out_path = 0;
      int opt;
      unsigned flag_errors = 0;
      queue<net_func> net_func_queue;

      while ((opt = getopt(argc, argv, "DF:f:ho:s:t:")) != EOF) switch (opt) {
	  case 'D':
	    dump_flag = true;
	    break;
	  case 'F': {
		net_func tmp = name_to_net_func(optarg);
		if (tmp == 0) {
		      cerr << "No such design transform function ``"
			   << optarg << "''." << endl;
		      flag_errors += 1;
		      break;
		}
		net_func_queue.push(tmp);
		break;
	  }
	  case 'f':
	    parm_to_flagmap(optarg);
	    break;
	  case 'h':
	    help_flag = true;
	    break;
	  case 'o':
	    out_path = optarg;
	    break;
	  case 's':
	    start_module = optarg;
	    break;
	  case 't':
	    target = optarg;
	    break;
	  default:
	    flag_errors += 1;
	    break;
      }

      if (flag_errors)
	    return flag_errors;

      if (help_flag) {
	    cout << "Netlist functions:" << endl;
	    for (unsigned idx = 0 ;  func_table[idx].name ;  idx += 1)
		  cout << "    " << func_table[idx].name << endl;
	    cout << "Target types:" << endl;
	    for (unsigned idx = 0 ;  target_table[idx] ;  idx += 1)
		  cout << "    " << target_table[idx]->name << endl;
	    return 0;
      }

      if (optind == argc) {
	    cerr << "No input files." << endl;
	    return 1;
      }

	/* Parse the input. Make the pform. */
      map<string,Module*> modules;
      map<string,PUdp*>   primitives;
      int rc = pform_parse(argv[optind], modules, primitives);

      if (rc) {
	    return rc;
      }

      if (dump_flag) {
	    ofstream out ("a.pf");
	    out << "PFORM DUMP MODULES:" << endl;
	    for (map<string,Module*>::iterator mod = modules.begin()
		       ; mod != modules.end()
		       ; mod ++ ) {
		  pform_dump(out, (*mod).second);
	    }
	    out << "PFORM DUMP PRIMITIVES:" << endl;
	    for (map<string,PUdp*>::iterator idx = primitives.begin()
		       ; idx != primitives.end()
		       ; idx ++ ) {
		  (*idx).second->dump(out);
	    }
      }

	/* Select a root module, and elaborate the design. */
      if (start_module == "") {
	    start_module = "main";
      }

      Design*des = elaborate(modules, primitives, start_module);
      if (des == 0) {
	    cerr << "Unable to elaborate design." << endl;
	    return 1;
      }
      if (des->errors) {
	    cerr << des->errors << " error(s) elaborating design." << endl;
	    return des->errors;
      }

      des->set_flags(flags);

      while (!net_func_queue.empty()) {
	    net_func func = net_func_queue.front();
	    net_func_queue.pop();
	    func(des);
      }

      if (dump_flag) {
	    ofstream out ("a.net");
	    des->dump(out);
      }

      if (out_path) {
	    ofstream out;
	    out.open(out_path);
	    if (! out.is_open()) {
		  cerr << "Unable to open " << out_path << " for writing."
		       << endl;
		  return 1;
	    }

	    emit(out, des, target);

      } else {
	    emit(cout, des, target);
      }

      return 0;
}

/*
 * $Log: main.cc,v $
 * Revision 1.13  1999/02/01 00:26:49  steve
 *  Carry some line info to the netlist,
 *  Dump line numbers for processes.
 *  Elaborate prints errors about port vector
 *  width mismatch
 *  Emit better handles null statements.
 *
 * Revision 1.12  1999/01/24 01:35:36  steve
 *  Support null target for generating no output.
 *
 * Revision 1.11  1998/12/20 02:05:41  steve
 *  Function to calculate wire initial value.
 *
 * Revision 1.10  1998/12/09 04:02:47  steve
 *  Support the include directive.
 *
 * Revision 1.9  1998/12/07 04:53:17  steve
 *  Generate OBUF or IBUF attributes (and the gates
 *  to garry them) where a wire is a pad. This involved
 *  figuring out enough of the netlist to know when such
 *  was needed, and to generate new gates and signales
 *  to handle what's missing.
 *
 * Revision 1.8  1998/12/02 04:37:13  steve
 *  Add the nobufz function to eliminate bufz objects,
 *  Object links are marked with direction,
 *  constant propagation is more careful will wide links,
 *  Signal folding is aware of attributes, and
 *  the XNF target can dump UDP objects based on LCA
 *  attributes.
 *
 * Revision 1.7  1998/12/01 00:42:14  steve
 *  Elaborate UDP devices,
 *  Support UDP type attributes, and
 *  pass those attributes to nodes that
 *  are instantiated by elaboration,
 *  Put modules into a map instead of
 *  a simple list.
 *
 * Revision 1.6  1998/11/25 02:35:53  steve
 *  Parse UDP primitives all the way to pform.
 *
 * Revision 1.5  1998/11/18 04:25:22  steve
 *  Add -f flags for generic flag key/values.
 *
 * Revision 1.4  1998/11/16 05:03:52  steve
 *  Add the sigfold function that unlinks excess
 *  signal nodes, and add the XNF target.
 *
 * Revision 1.3  1998/11/13 06:23:17  steve
 *  Introduce netlist optimizations with the
 *  cprop function to do constant propogation.
 *
 * Revision 1.2  1998/11/07 17:05:05  steve
 *  Handle procedural conditional, and some
 *  of the conditional expressions.
 *
 *  Elaborate signals and identifiers differently,
 *  allowing the netlist to hold signal information.
 *
 * Revision 1.1  1998/11/03 23:28:59  steve
 *  Introduce verilog to CVS.
 *
 */

<commit_msg> Make debug output file parameters.<commit_after>/*
 * Copyright (c) 1998 Stephen Williams (steve@icarus.com)
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */
#if !defined(WINNT)
#ident "$Id: main.cc,v 1.14 1999/04/23 04:34:32 steve Exp $"
#endif

# include  <stdio.h>
# include  <iostream.h>
# include  <fstream>
# include  <queue>
# include  <map>
# include  <unistd.h>
# include  "pform.h"
# include  "netlist.h"
# include  "target.h"

extern void pform_parse();

const char*target = "null";
string start_module = "";

map<string,string> flags;

static void parm_to_flagmap(const string&flag)
{
      string key, value;
      unsigned off = flag.find('=');
      if (off > flag.size()) {
	    key = flag;
	    value = "";

      } else {
	    key = flag.substr(0, off);
	    value = flag.substr(off+1);
      }

      flags[key] = value;
}

extern Design* elaborate(const map<string,Module*>&modules,
			 const map<string,PUdp*>&primitives,
			 const string&root);
extern void emit(ostream&o, const Design*, const char*);

extern void cprop(Design*des);
extern void propinit(Design*des);
extern void sigfold(Design*des);
extern void stupid(Design*des);
extern void nobufz(Design*des);
extern void xnfio(Design*des);

typedef void (*net_func)(Design*);
static struct net_func_map {
      const char*name;
      void (*func)(Design*);
} func_table[] = {
      { "cprop",   &cprop },
      { "nobufz",  &nobufz },
      { "propinit", &propinit },
      { "sigfold", &sigfold },
      { "stupid",  &stupid },
      { "xnfio",   &xnfio },
      { 0, 0 }
};

net_func name_to_net_func(const string&name)
{
      for (unsigned idx = 0 ;  func_table[idx].name ;  idx += 1)
	    if (name == func_table[idx].name)
		  return func_table[idx].func;

      return 0;
}

int main(int argc, char*argv[])
{
      bool help_flag = false;
      const char* net_path = 0;
      const char* out_path = 0;
      const char* pf_path = 0;
      int opt;
      unsigned flag_errors = 0;
      queue<net_func> net_func_queue;

      while ((opt = getopt(argc, argv, "F:f:hN:o:P:s:t:")) != EOF) switch (opt) {
	  case 'F': {
		net_func tmp = name_to_net_func(optarg);
		if (tmp == 0) {
		      cerr << "No such design transform function ``"
			   << optarg << "''." << endl;
		      flag_errors += 1;
		      break;
		}
		net_func_queue.push(tmp);
		break;
	  }
	  case 'f':
	    parm_to_flagmap(optarg);
	    break;
	  case 'h':
	    help_flag = true;
	    break;
	  case 'N':
	    net_path = optarg;
	    break;
	  case 'o':
	    out_path = optarg;
	    break;
	  case 'P':
	    pf_path = optarg;
	    break;
	  case 's':
	    start_module = optarg;
	    break;
	  case 't':
	    target = optarg;
	    break;
	  default:
	    flag_errors += 1;
	    break;
      }

      if (flag_errors)
	    return flag_errors;

      if (help_flag) {
	    cout << "Netlist functions:" << endl;
	    for (unsigned idx = 0 ;  func_table[idx].name ;  idx += 1)
		  cout << "    " << func_table[idx].name << endl;
	    cout << "Target types:" << endl;
	    for (unsigned idx = 0 ;  target_table[idx] ;  idx += 1)
		  cout << "    " << target_table[idx]->name << endl;
	    return 0;
      }

      if (optind == argc) {
	    cerr << "No input files." << endl;
	    return 1;
      }

	/* Parse the input. Make the pform. */
      map<string,Module*> modules;
      map<string,PUdp*>   primitives;
      int rc = pform_parse(argv[optind], modules, primitives);

      if (rc) {
	    return rc;
      }

      if (pf_path) {
	    ofstream out (pf_path);
	    out << "PFORM DUMP MODULES:" << endl;
	    for (map<string,Module*>::iterator mod = modules.begin()
		       ; mod != modules.end()
		       ; mod ++ ) {
		  pform_dump(out, (*mod).second);
	    }
	    out << "PFORM DUMP PRIMITIVES:" << endl;
	    for (map<string,PUdp*>::iterator idx = primitives.begin()
		       ; idx != primitives.end()
		       ; idx ++ ) {
		  (*idx).second->dump(out);
	    }
      }

	/* Select a root module, and elaborate the design. */
      if (start_module == "") {
	    start_module = "main";
      }

      Design*des = elaborate(modules, primitives, start_module);
      if (des == 0) {
	    cerr << "Unable to elaborate design." << endl;
	    return 1;
      }
      if (des->errors) {
	    cerr << des->errors << " error(s) elaborating design." << endl;
	    return des->errors;
      }

      des->set_flags(flags);

      while (!net_func_queue.empty()) {
	    net_func func = net_func_queue.front();
	    net_func_queue.pop();
	    func(des);
      }

      if (net_path) {
	    ofstream out (net_path);
	    des->dump(out);
      }

      if (out_path) {
	    ofstream out;
	    out.open(out_path);
	    if (! out.is_open()) {
		  cerr << "Unable to open " << out_path << " for writing."
		       << endl;
		  return 1;
	    }

	    emit(out, des, target);

      } else {
	    emit(cout, des, target);
      }

      return 0;
}

/*
 * $Log: main.cc,v $
 * Revision 1.14  1999/04/23 04:34:32  steve
 *  Make debug output file parameters.
 *
 * Revision 1.13  1999/02/01 00:26:49  steve
 *  Carry some line info to the netlist,
 *  Dump line numbers for processes.
 *  Elaborate prints errors about port vector
 *  width mismatch
 *  Emit better handles null statements.
 *
 * Revision 1.12  1999/01/24 01:35:36  steve
 *  Support null target for generating no output.
 *
 * Revision 1.11  1998/12/20 02:05:41  steve
 *  Function to calculate wire initial value.
 *
 * Revision 1.10  1998/12/09 04:02:47  steve
 *  Support the include directive.
 *
 * Revision 1.9  1998/12/07 04:53:17  steve
 *  Generate OBUF or IBUF attributes (and the gates
 *  to garry them) where a wire is a pad. This involved
 *  figuring out enough of the netlist to know when such
 *  was needed, and to generate new gates and signales
 *  to handle what's missing.
 *
 * Revision 1.8  1998/12/02 04:37:13  steve
 *  Add the nobufz function to eliminate bufz objects,
 *  Object links are marked with direction,
 *  constant propagation is more careful will wide links,
 *  Signal folding is aware of attributes, and
 *  the XNF target can dump UDP objects based on LCA
 *  attributes.
 *
 * Revision 1.7  1998/12/01 00:42:14  steve
 *  Elaborate UDP devices,
 *  Support UDP type attributes, and
 *  pass those attributes to nodes that
 *  are instantiated by elaboration,
 *  Put modules into a map instead of
 *  a simple list.
 *
 * Revision 1.6  1998/11/25 02:35:53  steve
 *  Parse UDP primitives all the way to pform.
 *
 * Revision 1.5  1998/11/18 04:25:22  steve
 *  Add -f flags for generic flag key/values.
 *
 * Revision 1.4  1998/11/16 05:03:52  steve
 *  Add the sigfold function that unlinks excess
 *  signal nodes, and add the XNF target.
 *
 * Revision 1.3  1998/11/13 06:23:17  steve
 *  Introduce netlist optimizations with the
 *  cprop function to do constant propogation.
 *
 * Revision 1.2  1998/11/07 17:05:05  steve
 *  Handle procedural conditional, and some
 *  of the conditional expressions.
 *
 *  Elaborate signals and identifiers differently,
 *  allowing the netlist to hold signal information.
 *
 * Revision 1.1  1998/11/03 23:28:59  steve
 *  Introduce verilog to CVS.
 *
 */

<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <future>

#include "channel.hh"

static const int kGo = 0;
static const int kQuit = 1;
static const int kDone = 2;

int
main( int argc, char ** argv )
{
  channel<int> sayHello(0), sayWorld(0), quitter(0);

  std::cerr << "sayHello: " << &sayHello << "\n";
  std::cerr << "sayWorld: " << &sayWorld << "\n";
  std::cerr << "quitter: " << &quitter << "\n";

  auto d = std::async( std::launch::async, [&]
      {
        for ( int i = 0; i < 1000; ++i )
        {
          std::cout << "Hello ";
          sayWorld << kGo;
          int a;
          sayHello >> a;
        }
        sayWorld << kQuit;
      } );

  auto b = std::async( std::launch::async, [&]
      {
        while ( true )
        {
          int reply;
          sayWorld >> reply;
          if ( reply == kQuit )
            break;
          std::cout << "world!\n";
          sayHello << kGo;
        }
        quitter << kDone;
      } );

  int a;
  quitter >> a;

  // test channel of capacity > 1

  channel<int> chan( 6 );
  for ( int i = 0; i < 6; ++i )
    chan << i;

  for ( int i = 0; i < 6; ++i )
  {
    int k;
    chan >> k;
    std::cerr << k << " ";
  }
  std::cerr << "\n";

  return 0;
}
<commit_msg>main back to original concurrent hello world implementation<commit_after>#include <iostream>
#include <string>
#include <future>

#include "channel.hh"

static const int kGo = 0;
static const int kQuit = 1;
static const int kDone = 2;

int
main( int argc, char ** argv )
{
  channel<int> sayHello, sayWorld, quitter;

  auto d = std::async( std::launch::async, [&]
      {
        for ( int i = 0; i < 1000; ++i )
        {
          std::cout << "Hello ";
          sayWorld << kGo;
          int a;
          sayHello >> a;
        }
        sayWorld << kQuit;
      } );

  auto b = std::async( std::launch::async, [&]
      {
        while ( true )
        {
          int reply;
          sayWorld >> reply;
          if ( reply == kQuit )
            break;
          std::cout << "world!\n";
          sayHello << kGo;
        }
        quitter << kDone;
      } );

  int a;
  quitter >> a;

  return 0;
}
<|endoftext|>


<commit_before>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <curses.h>
#include <signal.h>
#include "buffer.h"
#include "render.h"
#include "terminal_collaborator.h"
#include "terminal_color.h"

constexpr char ctrl(char c) { return c & 037; }

class Application {
 public:
  Application(const char* filename)
      : done_(false),
        buffer_(filename, AnnotatedString()),
        terminal_collaborator_(buffer_.MakeCollaborator<TerminalCollaborator>(
            [this]() { Invalidate(); })) {
    auto theme = std::unique_ptr<Theme>(new Theme(Theme::DEFAULT));
    initscr();
    raw();
    noecho();
    set_escdelay(25);
    start_color();
    color_.reset(new TerminalColor{std::move(theme)});
    bkgd(color_->Theme({}, 0));
    keypad(stdscr, true);
  }

  ~Application() { endwin(); }

  void Quit() {
    absl::MutexLock lock(&mu_);
    done_ = true;
  }

  void Invalidate() {
    {
      absl::MutexLock lock(&mu_);
      invalidated_ = true;
    }
    kill(getpid(), SIGWINCH);
  }

  void Run() {
    bool refresh = true;
    absl::Time last_key_press = absl::Now();
    std::unique_ptr<LogTimer> log_timer(new LogTimer("main_loop"));
    for (;;) {
      bool animating = false;
      if (refresh) {
        erase();
        animating = Render(log_timer.get(), last_key_press);
        log_timer->Mark("rendered");
      }
      timeout(animating ? 10 : -1);
      log_timer.reset();
      int c = getch();
      log_timer.reset(new LogTimer("main_loop"));
      Log() << "GOTKEY: " << c;
      last_key_press = absl::Now();

      refresh = true;
      switch (c) {
        case ERR:
          break;
        case KEY_RESIZE:
          refresh = false;
          break;
        case 27:
          Quit();
          break;
        default:
          terminal_collaborator_->ProcessKey(&app_env_, c);
      }

      log_timer->Mark("input_processed");

      absl::MutexLock lock(&mu_);
      if (done_) return;
      if (invalidated_) {
        refresh = true;
        invalidated_ = false;
      }

      log_timer->Mark("signalled");
    }
  }

 private:
  bool Render(LogTimer* log_timer, absl::Time last_key_press) {
    TerminalRenderer renderer;
    int fb_rows, fb_cols;
    getmaxyx(stdscr, fb_rows, fb_cols);
    auto top = renderer.AddContainer(LAY_COLUMN).FixSize(fb_cols, fb_rows);
    TerminalRenderContainers containers{
        top.AddContainer(LAY_FILL, LAY_ROW),
        top.AddContainer(LAY_BOTTOM | LAY_HFILL, LAY_COLUMN),
        top.AddContainer(LAY_HFILL, LAY_ROW).FixSize(0, 1),
    };
    terminal_collaborator_->Render(containers);
    log_timer->Mark("collected_layout");
    renderer.Layout();
    log_timer->Mark("layout");
    TerminalRenderContext ctx{color_.get(), nullptr, -1, -1, false};
    renderer.Draw(&ctx);
    log_timer->Mark("draw");

    auto frame_time = absl::Now() - last_key_press;
    std::ostringstream out;
    out << frame_time;
    std::string ftstr = out.str();
    mvaddstr(fb_rows - 1, fb_cols - ftstr.length(), ftstr.c_str());

    if (ctx.crow != -1) {
      move(ctx.crow, ctx.ccol);
    }

    return ctx.animating;
  }

  absl::Mutex mu_;
  bool done_ GUARDED_BY(mu_);
  bool invalidated_ GUARDED_BY(mu_);

  Buffer buffer_;
  TerminalCollaborator* const terminal_collaborator_;
  std::unique_ptr<TerminalColor> color_;
  AppEnv app_env_;
};

int main(int argc, char** argv) {
  if (argc != 2) {
    fprintf(stderr, "USAGE: ced <filename.{h,cc}>\n");
    return 1;
  }
  try {
    Application(argv[1]).Run();
  } catch (std::exception& e) {
    Log() << "FATAL ERROR: " << e.what();
    fprintf(stderr, "ERROR: %s", e.what());
    _exit(1);
  }
  return 0;
}
<commit_msg>Highlight bad frame times<commit_after>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <curses.h>
#include <signal.h>
#include "buffer.h"
#include "render.h"
#include "terminal_collaborator.h"
#include "terminal_color.h"

constexpr char ctrl(char c) { return c & 037; }

class Application {
 public:
  Application(const char* filename)
      : done_(false),
        buffer_(filename, AnnotatedString()),
        terminal_collaborator_(buffer_.MakeCollaborator<TerminalCollaborator>(
            [this]() { Invalidate(); })) {
    auto theme = std::unique_ptr<Theme>(new Theme(Theme::DEFAULT));
    initscr();
    raw();
    noecho();
    set_escdelay(25);
    start_color();
    color_.reset(new TerminalColor{std::move(theme)});
    bkgd(color_->Theme({}, 0));
    keypad(stdscr, true);
  }

  ~Application() { endwin(); }

  void Quit() {
    absl::MutexLock lock(&mu_);
    done_ = true;
  }

  void Invalidate() {
    {
      absl::MutexLock lock(&mu_);
      invalidated_ = true;
    }
    kill(getpid(), SIGWINCH);
  }

  void Run() {
    bool refresh = true;
    absl::Time last_key_press = absl::Now();
    std::unique_ptr<LogTimer> log_timer(new LogTimer("main_loop"));
    for (;;) {
      bool animating = false;
      if (refresh) {
        erase();
        animating = Render(log_timer.get(), last_key_press);
        log_timer->Mark("rendered");
      }
      timeout(animating ? 10 : -1);
      log_timer.reset();
      int c = getch();
      log_timer.reset(new LogTimer("main_loop"));
      Log() << "GOTKEY: " << c;
      last_key_press = absl::Now();

      refresh = true;
      switch (c) {
        case ERR:
          break;
        case KEY_RESIZE:
          refresh = false;
          break;
        case 27:
          Quit();
          break;
        default:
          terminal_collaborator_->ProcessKey(&app_env_, c);
      }

      log_timer->Mark("input_processed");

      absl::MutexLock lock(&mu_);
      if (done_) return;
      if (invalidated_) {
        refresh = true;
        invalidated_ = false;
      }

      log_timer->Mark("signalled");
    }
  }

 private:
  bool Render(LogTimer* log_timer, absl::Time last_key_press) {
    TerminalRenderer renderer;
    int fb_rows, fb_cols;
    getmaxyx(stdscr, fb_rows, fb_cols);
    auto top = renderer.AddContainer(LAY_COLUMN).FixSize(fb_cols, fb_rows);
    TerminalRenderContainers containers{
        top.AddContainer(LAY_FILL, LAY_ROW),
        top.AddContainer(LAY_BOTTOM | LAY_HFILL, LAY_COLUMN),
        top.AddContainer(LAY_HFILL, LAY_ROW).FixSize(0, 1),
    };
    terminal_collaborator_->Render(containers);
    log_timer->Mark("collected_layout");
    renderer.Layout();
    log_timer->Mark("layout");
    TerminalRenderContext ctx{color_.get(), nullptr, -1, -1, false};
    renderer.Draw(&ctx);
    log_timer->Mark("draw");

    auto frame_time = absl::Now() - last_key_press;
    std::ostringstream out;
    out << frame_time;
    std::string ftstr = out.str();
    chtype attr = frame_time > absl::Milliseconds(10)
                      ? color_->Theme({"invalid"}, 0)
                      : color_->Theme({}, 0);
    for (size_t i = 0; i < ftstr.length(); i++) {
      mvaddch(fb_rows - 1, fb_cols - ftstr.length() + i, ftstr[i] | attr);
    }

    if (ctx.crow != -1) {
      move(ctx.crow, ctx.ccol);
    }

    return ctx.animating;
  }

  absl::Mutex mu_;
  bool done_ GUARDED_BY(mu_);
  bool invalidated_ GUARDED_BY(mu_);

  Buffer buffer_;
  TerminalCollaborator* const terminal_collaborator_;
  std::unique_ptr<TerminalColor> color_;
  AppEnv app_env_;
};

int main(int argc, char** argv) {
  if (argc != 2) {
    fprintf(stderr, "USAGE: ced <filename.{h,cc}>\n");
    return 1;
  }
  try {
    Application(argv[1]).Run();
  } catch (std::exception& e) {
    Log() << "FATAL ERROR: " << e.what();
    fprintf(stderr, "ERROR: %s", e.what());
    _exit(1);
  }
  return 0;
}
<|endoftext|>


<commit_before>//
//  main.cpp
//  euler
//
//  Created by Duncan Smith on 19/10/2013.
//  Copyright (c) 2013 Duncan Smith. All rights reserved.
//

#include <iostream>

#include "projects.h"

int main(int argc, const char * argv[])
{
  const int max_multiple = 1e6;

  project_1(max_multiple);
  project_1_s(max_multiple);
}

<commit_msg>rm comment<commit_after>//  main.cpp
//  euler
//
//  Created by Duncan Smith on 19/10/2013.
//  Copyright (c) 2013 Duncan Smith. All rights reserved.
//

#include <iostream>

#include "projects.h"

int main(int argc, const char * argv[])
{
  const int max_multiple = 1e6;

  project_1(max_multiple);
  project_1_s(max_multiple);
}

<|endoftext|>


<commit_before>// Copyright 2013 Tanel Lebedev

#include <iostream> // NOLINT
#include <cstdlib>
#include <vector>

#include "./toggl_api_client.h"
#include "./database.h"
#include "./main.h"

#include "Poco/Message.h"
#include "Poco/Logger.h"
#include "Poco/Util/Application.h"

namespace kopsik {

    int Kopsik::main(const std::vector<std::string>& args) {
        Poco::Logger &logger = Poco::Logger::get("");
        logger.setLevel(Poco::Message::PRIO_DEBUG);

        char* apiToken = getenv("TOGGL_API_TOKEN");
        if (!apiToken) {
            std::cerr << "Please set TOGGL_API_TOKEN in environment"
                << std::endl;
            return Poco::Util::Application::EXIT_USAGE;
        }
        if (args.empty()) {
            std::cout << "Recognized commands are: push, pull, start, stop"
                << std::endl;
            return Poco::Util::Application::EXIT_USAGE;
        }

        Database db("kopsik.db");

        // Load user - we know current user by the TOGGL_API_TOKEN parameter.
        User user;
        error err = db.Load(apiToken, &user, true);
        if (err != noError) {
            logger.error(err);
            return Poco::Util::Application::EXIT_SOFTWARE;
        }
        poco_assert(!user.APIToken.empty());

        // Run a command on the user that has been loaded
        if ("pull" == args[0]) {
            err = user.Pull();
        } else if ("push" == args[0]) {
            err = user.Push();
        } else if ("start" == args[0]) {
            TimeEntry *te = user.Start();
            if (te) {
                logger.debug("Time entry started: " + te->String());
            }
        } else if ("stop" == args[0]) {
            std::vector<TimeEntry *>stopped = user.Stop();
            for (std::vector<TimeEntry *>::const_iterator it = stopped.begin();
                    it != stopped.end(); it++) {
                logger.debug("Time entry stopped: " + (*it)->String());
            }
        }

        // Check command result
        if (err != noError) {
            logger.error(err);
            return Poco::Util::Application::EXIT_SOFTWARE;
        }

        // If still not blown up, save state and exit.
        err = db.Save(&user, true);
        if (err != noError) {
            logger.error(err);
            return Poco::Util::Application::EXIT_SOFTWARE;
        }

        return Poco::Util::Application::EXIT_OK;
    }

}  // namespace kopsik
<commit_msg>status command prints running time entry<commit_after>// Copyright 2013 Tanel Lebedev

#include <iostream> // NOLINT
#include <cstdlib>
#include <vector>

#include "./toggl_api_client.h"
#include "./database.h"
#include "./main.h"

#include "Poco/Message.h"
#include "Poco/Logger.h"
#include "Poco/Util/Application.h"

namespace kopsik {

    int Kopsik::main(const std::vector<std::string>& args) {
        Poco::Logger &logger = Poco::Logger::get("");
        logger.setLevel(Poco::Message::PRIO_DEBUG);

        char* apiToken = getenv("TOGGL_API_TOKEN");
        if (!apiToken) {
            std::cerr << "Please set TOGGL_API_TOKEN in environment"
                << std::endl;
            return Poco::Util::Application::EXIT_USAGE;
        }
        if (args.empty()) {
            std::cout << "Recognized commands are: push, pull, start, stop"
                << std::endl;
            return Poco::Util::Application::EXIT_USAGE;
        }

        Database db("kopsik.db");

        // Load user - we know current user by the TOGGL_API_TOKEN parameter.
        User user;
        error err = db.Load(apiToken, &user, true);
        if (err != noError) {
            logger.error(err);
            return Poco::Util::Application::EXIT_SOFTWARE;
        }
        poco_assert(!user.APIToken.empty());

        // Run a command on the user that has been loaded
        std::string cmd = args[0];
        if ("pull" == cmd) {
            err = user.Pull();
        } else if ("push" == cmd) {
            err = user.Push();
        } else if ("status" == cmd) {
            TimeEntry *te = user.RunningTimeEntry();
            if (te) {
                logger.information("Tracking: " + te->String());
            } else {
                logger.information("Stopped.");
            }
        } else if ("start" == cmd) {
            TimeEntry *te = user.Start();
            if (te) {
                logger.information("Started: " + te->String());
            }
        } else if ("stop" == cmd) {
            std::vector<TimeEntry *>stopped = user.Stop();
            for (std::vector<TimeEntry *>::const_iterator it = stopped.begin();
                    it != stopped.end(); it++) {
                logger.information("Stopped: " + (*it)->String());
            }
        }

        // Check command result
        if (err != noError) {
            logger.error(err);
            return Poco::Util::Application::EXIT_SOFTWARE;
        }

        // If still not blown up, save state and exit.
        err = db.Save(&user, true);
        if (err != noError) {
            logger.error(err);
            return Poco::Util::Application::EXIT_SOFTWARE;
        }

        return Poco::Util::Application::EXIT_OK;
    }

}  // namespace kopsik
<|endoftext|>


<commit_before>#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
#include <string.h>
using namespace std;

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_File_Chooser.H>
#include "Fl_Rotated_Text/Fl_Rotated_Text.H"
#include "cartesian/Cartesian.H"

#include "cvFltkWidget.hh"
#include "ffmpegInterface.hh"
#include "cameraSource.hh"

extern "C"
{
#include "wormProcessing.h"
}

#define DATA_FRAME_RATE_FPS     (1.0 / 15.0) /* I collect at 15 frames per second */
#define PLAYBACK_FRAME_RATE_FPS 15
#define CIRCLE_RADIUS           50
#define CIRCLE_COLOR            CV_RGB(0xFF, 0, 0)
#define POINTED_CIRCLE_COLOR    CV_RGB(0, 0xFF, 0)

#define FRAME_W       480
#define FRAME_H       480
#define CROP_RECT     cvRect(80, 0, FRAME_W, FRAME_H)
#define WINDOW_W      1000
#define WINDOW_H      (FRAME_H + BUTTON_H + PLOT_H + X_AXIS_HEIGHT + AXIS_EXTRA_SPACE)
#define BUTTON_W      100
#define BUTTON_H      30
#define PLOT_W        (WINDOW_W - (Y_AXIS_WIDTH + AXIS_EXTRA_SPACE))
#define PLOT_H        400
#define X_AXIS_HEIGHT 30
#define Y_AXIS_WIDTH  30

// due to a bug (most likely), the axis aren't drawn completely inside their box. Thus I leave a bit
// of extra space to see the labels
#define AXIS_EXTRA_SPACE 30

#define AM_READING_CAMERA (dynamic_cast<CameraSource*>(source) != NULL)

static FrameSource*  source;
static CvFltkWidget* widgetImage;
static Fl_Button*    goResetButton;
static Ca_Canvas*    plot = NULL;
static Ca_X_Axis*    Xaxis;
static Ca_Y_Axis*    Yaxis;

// the analysis could be idle, running, or idle examining data (STOPPED)
static enum { RESET, RUNNING, STOPPED } analysisState;

static int           numPoints;
static Ca_LinePoint* lastLeftPoint       = NULL;
static Ca_LinePoint* lastRightPoint      = NULL;
static CvPoint       leftCircleCenter    = cvPoint(-1, -1);
static CvPoint       rightCircleCenter   = cvPoint(-1, -1);
static CvPoint       pointedCircleCenter = cvPoint(-1, -1);

#define HAVE_LEFT_CIRCLE    (leftCircleCenter .x > 0 && leftCircleCenter .y > 0)
#define HAVE_RIGHT_CIRCLE   (rightCircleCenter.x > 0 && rightCircleCenter.y > 0)
#define HAVE_CIRCLES        (HAVE_LEFT_CIRCLE && HAVE_RIGHT_CIRCLE)
#define HAVE_POINTED_CIRCLE (pointedCircleCenter.x > 0 && pointedCircleCenter.y > 0)

void gotNewFrame(IplImage* buffer, uint64_t timestamp_us __attribute__((unused)))
{
    cvMerge(buffer, buffer, buffer, NULL, *widgetImage);

    const CvMat* result = isolateWorms(buffer);
    cvSetImageCOI(*widgetImage, 1);
    cvCopy(result, *widgetImage);
    cvSetImageCOI(*widgetImage, 0);

    if(HAVE_LEFT_CIRCLE)
        cvCircle(*widgetImage, leftCircleCenter,    CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_RIGHT_CIRCLE)
        cvCircle(*widgetImage, rightCircleCenter,   CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_POINTED_CIRCLE)
        cvCircle(*widgetImage, pointedCircleCenter, CIRCLE_RADIUS, POINTED_CIRCLE_COLOR, 1, 8);

    // This critical section is likely larger than it needs to be, but this keeps me safe. The
    // analysis state can change in the FLTK thread, so I err on the side of safety
    Fl::lock();
    {
        if(analysisState == RUNNING)
        {
            double leftOccupancy, rightOccupancy;
            computeWormOccupancy(result, &leftCircleCenter, &rightCircleCenter,
                                 CIRCLE_RADIUS,
                                 &leftOccupancy, &rightOccupancy);

            Yaxis->rescale(CA_WHEN_MAX, fmax(leftOccupancy, rightOccupancy) );

            lastLeftPoint  = new Ca_LinePoint(lastLeftPoint,
                                              numPoints, leftOccupancy,  1,FL_RED,   CA_NO_POINT);
            lastRightPoint = new Ca_LinePoint(lastRightPoint,
                                              numPoints, rightOccupancy, 1,FL_GREEN, CA_NO_POINT);
            Xaxis->maximum(numPoints);
            numPoints++;
        }

        widgetImage->redrawNewFrame();
    }
    Fl::unlock();
}

static void widgetImageCallback(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if(Fl::event() == FL_LEAVE)
    {
        // I want to make sure to never miss this, so I handle it unconditionally
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    if(analysisState == RUNNING)
    {
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    bool onLeftHalf = (Fl::event_x() - widget->x()) < FRAME_W/2;
    switch(Fl::event())
    {
    case FL_MOVE:
        pointedCircleCenter.x = Fl::event_x() - widget->x();
        pointedCircleCenter.y = Fl::event_y() - widget->y();
        break;

    case FL_LEAVE:
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    case FL_PUSH:
        if(onLeftHalf)
        {
            leftCircleCenter.x = Fl::event_x() - widget->x();
            leftCircleCenter.y = Fl::event_y() - widget->y();
        }
        else
        {
            rightCircleCenter.x = Fl::event_x() - widget->x();
            rightCircleCenter.y = Fl::event_y() - widget->y();
        }

        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    default: ;
    }

    if(HAVE_CIRCLES && analysisState == RESET)
        goResetButton->activate();
}

static void setResetAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA_BOLD);
    goResetButton->labelcolor(FL_RED);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Analyze");

    numPoints = 0;
    if(plot) plot->clear();
    lastLeftPoint = lastRightPoint = NULL;

    analysisState = RESET;
}

static void setRunningAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Stop analysis");

    pointedCircleCenter.x = pointedCircleCenter.y = -1;

    analysisState = RUNNING;
}

static void setStoppedAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_NORMAL_BUTTON);
    goResetButton->label("Reset analysis data");

    analysisState = STOPPED;
}

static void pressedGoReset(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if     (analysisState == RUNNING) setStoppedAnalysis();
    else if(analysisState == STOPPED) setResetAnalysis();
    else                              setRunningAnalysis();
}

int main(int argc, char* argv[])
{
    Fl::lock();
    Fl::visual(FL_RGB);

    // open the first source. If there's an argument, assume it's an input video. Otherwise, try
    // reading a camera
    if(argc >= 2) source = new FFmpegDecoder(argv[1], FRAMESOURCE_GRAYSCALE, false, CROP_RECT);
    else          source = new CameraSource (FRAMESOURCE_GRAYSCALE, false, 0, CROP_RECT);

    if(! *source)
    {
        fprintf(stderr, "couldn't open source\n");
        delete source;
        return 0;
    }

    IplImage* buffer = cvCreateImage(cvSize(source->w(), source->h()), IPL_DEPTH_8U, 1);

    Fl_Double_Window* window =
        new Fl_Double_Window(WINDOW_W, WINDOW_H, "Wormtracker 3");
    widgetImage = new CvFltkWidget(0, 0, source->w(), source->h(),
                                   WIDGET_COLOR);

    widgetImage->callback(widgetImageCallback);

    goResetButton = new Fl_Button( 0, source->h(), BUTTON_W, BUTTON_H);
    setResetAnalysis();
    goResetButton->callback(pressedGoReset);
    goResetButton->deactivate();

    plot = new Ca_Canvas( Y_AXIS_WIDTH + AXIS_EXTRA_SPACE, goResetButton->y() + goResetButton->h(), PLOT_W, PLOT_H,
                          "Worm occupancy");
    plot->align(FL_ALIGN_TOP);

    // This is extremely important for some reason. Without it the plots do not refresh property and
    // there're artifacts every time the plot is resized
    plot->box(FL_DOWN_BOX);

    Xaxis = new Ca_X_Axis(plot->x(), plot->y() + plot->h(), plot->w(), X_AXIS_HEIGHT, "Points");
    Xaxis->align(FL_ALIGN_BOTTOM);
    Xaxis->minimum(0);
    Xaxis->maximum(1);
    Xaxis->label_format("%g");
    Xaxis->major_step(10);
    Xaxis->label_step(10);
    Xaxis->axis_color(FL_BLACK);
    Xaxis->axis_align(CA_BOTTOM | CA_LINE);

    Yaxis = new Ca_Y_Axis(AXIS_EXTRA_SPACE, plot->y(), Y_AXIS_WIDTH, plot->h());
    Fl_Rotated_Text YaxisLabel("occupancy ratio", FL_HELVETICA, 14, 0, 1);
    Yaxis->image(&YaxisLabel);
    Yaxis->minimum(0);
    Yaxis->maximum(0.01);
    Yaxis->align(FL_ALIGN_LEFT);
    Yaxis->axis_align(CA_LEFT | CA_LINE);
    Yaxis->axis_color(FL_BLACK);

    window->resizable(window);
    window->end();
    window->show();

    processingInit(source->w(), source->h());

    // I read the data with a tiny delay. This makes sure that I skip old frames (only an issue if I
    // can't keep up with the data rate), but yet got as fast as I can
    source->startSourceThread(&gotNewFrame, 1e6/PLAYBACK_FRAME_RATE_FPS, buffer);

    while (Fl::wait())
    {
    }

    Fl::unlock();

    delete source;
    delete window;
    cvReleaseImage(&buffer);

    processingCleanup();
    return 0;
}
<commit_msg>added widgets to show the integrated results<commit_after>#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
#include <string.h>
using namespace std;

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_File_Chooser.H>
#include "Fl_Rotated_Text/Fl_Rotated_Text.H"
#include "cartesian/Cartesian.H"

#include "cvFltkWidget.hh"
#include "ffmpegInterface.hh"
#include "cameraSource.hh"

extern "C"
{
#include "wormProcessing.h"
}

#define DATA_FRAME_RATE_FPS     (1.0 / 15.0) /* I collect at 15 frames per second */
#define PLAYBACK_FRAME_RATE_FPS 15
#define CIRCLE_RADIUS           50
#define CIRCLE_COLOR            CV_RGB(0xFF, 0, 0)
#define POINTED_CIRCLE_COLOR    CV_RGB(0, 0xFF, 0)

#define FRAME_W       480
#define FRAME_H       480
#define CROP_RECT     cvRect(80, 0, FRAME_W, FRAME_H)
#define WINDOW_W      1000
#define WINDOW_H      (FRAME_H + BUTTON_H + PLOT_H + X_AXIS_HEIGHT + AXIS_EXTRA_SPACE)
#define BUTTON_W      100
#define BUTTON_H      30
#define PLOT_W        (WINDOW_W - (Y_AXIS_WIDTH + AXIS_EXTRA_SPACE))
#define PLOT_H        400
#define X_AXIS_HEIGHT 30
#define Y_AXIS_WIDTH  30
#define ACCUM_W       100
#define ACCUM_H       BUTTON_H

// due to a bug (most likely), the axis aren't drawn completely inside their box. Thus I leave a bit
// of extra space to see the labels
#define AXIS_EXTRA_SPACE 30

#define AM_READING_CAMERA (dynamic_cast<CameraSource*>(source) != NULL)

static FrameSource*  source;
static CvFltkWidget* widgetImage;
static Fl_Button*    goResetButton;
static Ca_Canvas*    plot = NULL;
static Ca_X_Axis*    Xaxis;
static Ca_Y_Axis*    Yaxis;

static Fl_Output* leftAccum;
static Fl_Output* rightAccum;
static double     leftAccumValue  = 0.0;
static double     rightAccumValue = 0.0;

// the analysis could be idle, running, or idle examining data (STOPPED)
static enum { RESET, RUNNING, STOPPED } analysisState;

static int           numPoints;
static Ca_LinePoint* lastLeftPoint       = NULL;
static Ca_LinePoint* lastRightPoint      = NULL;
static CvPoint       leftCircleCenter    = cvPoint(-1, -1);
static CvPoint       rightCircleCenter   = cvPoint(-1, -1);
static CvPoint       pointedCircleCenter = cvPoint(-1, -1);

#define HAVE_LEFT_CIRCLE    (leftCircleCenter .x > 0 && leftCircleCenter .y > 0)
#define HAVE_RIGHT_CIRCLE   (rightCircleCenter.x > 0 && rightCircleCenter.y > 0)
#define HAVE_CIRCLES        (HAVE_LEFT_CIRCLE && HAVE_RIGHT_CIRCLE)
#define HAVE_POINTED_CIRCLE (pointedCircleCenter.x > 0 && pointedCircleCenter.y > 0)

void gotNewFrame(IplImage* buffer, uint64_t timestamp_us __attribute__((unused)))
{
    cvMerge(buffer, buffer, buffer, NULL, *widgetImage);

    const CvMat* result = isolateWorms(buffer);
    cvSetImageCOI(*widgetImage, 1);
    cvCopy(result, *widgetImage);
    cvSetImageCOI(*widgetImage, 0);

    if(HAVE_LEFT_CIRCLE)
        cvCircle(*widgetImage, leftCircleCenter,    CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_RIGHT_CIRCLE)
        cvCircle(*widgetImage, rightCircleCenter,   CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_POINTED_CIRCLE)
        cvCircle(*widgetImage, pointedCircleCenter, CIRCLE_RADIUS, POINTED_CIRCLE_COLOR, 1, 8);

    // This critical section is likely larger than it needs to be, but this keeps me safe. The
    // analysis state can change in the FLTK thread, so I err on the side of safety
    Fl::lock();
    {
        if(analysisState == RUNNING)
        {
            double leftOccupancy, rightOccupancy;
            computeWormOccupancy(result, &leftCircleCenter, &rightCircleCenter,
                                 CIRCLE_RADIUS,
                                 &leftOccupancy, &rightOccupancy);

            Yaxis->rescale(CA_WHEN_MAX, fmax(leftOccupancy, rightOccupancy) );

            lastLeftPoint  = new Ca_LinePoint(lastLeftPoint,
                                              numPoints, leftOccupancy,  1,FL_RED,   CA_NO_POINT);
            lastRightPoint = new Ca_LinePoint(lastRightPoint,
                                              numPoints, rightOccupancy, 1,FL_GREEN, CA_NO_POINT);
            Xaxis->maximum(numPoints);
            numPoints++;

            leftAccumValue  += leftOccupancy  / DATA_FRAME_RATE_FPS;
            rightAccumValue += rightOccupancy / DATA_FRAME_RATE_FPS;
            char results[128];
            snprintf(results, sizeof(results), "%.3f", leftAccumValue);
            leftAccum->value(results);
            snprintf(results, sizeof(results), "%.3f", rightAccumValue);
            rightAccum->value(results);
        }

        widgetImage->redrawNewFrame();
    }
    Fl::unlock();
}

static void widgetImageCallback(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if(Fl::event() == FL_LEAVE)
    {
        // I want to make sure to never miss this, so I handle it unconditionally
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    if(analysisState == RUNNING)
    {
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    bool onLeftHalf = (Fl::event_x() - widget->x()) < FRAME_W/2;
    switch(Fl::event())
    {
    case FL_MOVE:
        pointedCircleCenter.x = Fl::event_x() - widget->x();
        pointedCircleCenter.y = Fl::event_y() - widget->y();
        break;

    case FL_LEAVE:
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    case FL_PUSH:
        if(onLeftHalf)
        {
            leftCircleCenter.x = Fl::event_x() - widget->x();
            leftCircleCenter.y = Fl::event_y() - widget->y();
        }
        else
        {
            rightCircleCenter.x = Fl::event_x() - widget->x();
            rightCircleCenter.y = Fl::event_y() - widget->y();
        }

        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    default: ;
    }

    if(HAVE_CIRCLES && analysisState == RESET)
        goResetButton->activate();
}

static void setResetAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA_BOLD);
    goResetButton->labelcolor(FL_RED);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Analyze");

    numPoints       = 0;
    if(plot) plot->clear();
    lastLeftPoint   = lastRightPoint = NULL;
    leftAccumValue  = 0.0;
    rightAccumValue = 0.0;
    leftAccum ->value("0.0");
    rightAccum->value("0.0");

    analysisState = RESET;
}

static void setRunningAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Stop analysis");

    pointedCircleCenter.x = pointedCircleCenter.y = -1;

    analysisState = RUNNING;
}

static void setStoppedAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_NORMAL_BUTTON);
    goResetButton->label("Reset analysis data");

    analysisState = STOPPED;
}

static void pressedGoReset(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if     (analysisState == RUNNING) setStoppedAnalysis();
    else if(analysisState == STOPPED) setResetAnalysis();
    else                              setRunningAnalysis();
}

int main(int argc, char* argv[])
{
    Fl::lock();
    Fl::visual(FL_RGB);

    // open the first source. If there's an argument, assume it's an input video. Otherwise, try
    // reading a camera
    if(argc >= 2) source = new FFmpegDecoder(argv[1], FRAMESOURCE_GRAYSCALE, false, CROP_RECT);
    else          source = new CameraSource (FRAMESOURCE_GRAYSCALE, false, 0, CROP_RECT);

    if(! *source)
    {
        fprintf(stderr, "couldn't open source\n");
        delete source;
        return 0;
    }

    IplImage* buffer = cvCreateImage(cvSize(source->w(), source->h()), IPL_DEPTH_8U, 1);

    Fl_Double_Window* window =
        new Fl_Double_Window(WINDOW_W, WINDOW_H, "Wormtracker 3");
    widgetImage = new CvFltkWidget(0, 0, source->w(), source->h(),
                                   WIDGET_COLOR);

    widgetImage->callback(widgetImageCallback);

    goResetButton = new Fl_Button( 0, source->h(), BUTTON_W, BUTTON_H);
    goResetButton->callback(pressedGoReset);
    goResetButton->deactivate();

    plot = new Ca_Canvas( Y_AXIS_WIDTH + AXIS_EXTRA_SPACE, goResetButton->y() + goResetButton->h(), PLOT_W, PLOT_H,
                          "Worm occupancy");
    plot->align(FL_ALIGN_TOP);

    // This is extremely important for some reason. Without it the plots do not refresh property and
    // there're artifacts every time the plot is resized
    plot->box(FL_DOWN_BOX);

    Xaxis = new Ca_X_Axis(plot->x(), plot->y() + plot->h(), plot->w(), X_AXIS_HEIGHT, "Points");
    Xaxis->align(FL_ALIGN_BOTTOM);
    Xaxis->minimum(0);
    Xaxis->maximum(1);
    Xaxis->label_format("%g");
    Xaxis->major_step(10);
    Xaxis->label_step(10);
    Xaxis->axis_color(FL_BLACK);
    Xaxis->axis_align(CA_BOTTOM | CA_LINE);

    Yaxis = new Ca_Y_Axis(AXIS_EXTRA_SPACE, plot->y(), Y_AXIS_WIDTH, plot->h());
    Fl_Rotated_Text YaxisLabel("occupancy ratio", FL_HELVETICA, 14, 0, 1);
    Yaxis->image(&YaxisLabel);
    Yaxis->minimum(0);
    Yaxis->maximum(0.01);
    Yaxis->align(FL_ALIGN_LEFT);
    Yaxis->axis_align(CA_LEFT | CA_LINE);
    Yaxis->axis_color(FL_BLACK);

    window->resizable(window);
    leftAccum  = new Fl_Output(widgetImage->x() + widgetImage->w(), widgetImage->y(),
                              ACCUM_W, ACCUM_H, "Left accumulator (occupancy-seconds)");
    rightAccum = new Fl_Output(leftAccum->x(), leftAccum->y() + leftAccum->h(),
                              ACCUM_W, ACCUM_H, "Right accumulator (occupancy-seconds)");
    leftAccum ->align(FL_ALIGN_RIGHT);
    rightAccum->align(FL_ALIGN_RIGHT);
    leftAccum ->labelcolor(FL_RED);
    rightAccum->labelcolor(FL_GREEN);

    window->end();
    window->show();

    processingInit(source->w(), source->h());

    setResetAnalysis();

    // I read the data with a tiny delay. This makes sure that I skip old frames (only an issue if I
    // can't keep up with the data rate), but yet got as fast as I can
    source->startSourceThread(&gotNewFrame, 1e6/PLAYBACK_FRAME_RATE_FPS, buffer);

    while (Fl::wait())
    {
    }

    Fl::unlock();

    delete source;
    delete window;
    cvReleaseImage(&buffer);

    processingCleanup();
    return 0;
}
<|endoftext|>