<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CCopasiTask.cpp,v $
   $Revision: 1.36 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/11/06 14:30:10 $
   End CVS Header */

/**
 *  CCopasiTask class.
 *  This class is used to describe a task in COPASI. This class is
 *  intended to be used as the parent class for all tasks whithin COPASI.
 *
 *  Created for Copasi by Stefan Hoops 2003
 */

#include "copasi.h"

#include "CCopasiTask.h"
#include "CCopasiProblem.h"
#include "CCopasiMethod.h"
#include "report/CReport.h"
#include "report/CKeyFactory.h"
#include "utilities/COutputHandler.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "report/CCopasiObjectReference.h"

const std::string CCopasiTask::TypeName[] =
  {
    "Steady-State",
    "Time-Course",
    "Scan",
    "Elementary Flux Modes",
    "Optimization",
    "Parameter Fitting",
    "Metabolic Control Analysis",
    "Time scale separation",
    "Sensitivities",
    ""
  };

const char* CCopasiTask::XMLType[] =
  {
    "steadyState",
    "timeCourse",
    "scan",
    "fluxMode",
    "optimization",
    "parameterFitting",
    "metabolicControlAnalysis",
    "timeScaleSeparation",
    "sensitivities",
    NULL
  };

const unsigned C_INT32 CCopasiTask::ValidMethods[] =
  {
    CCopasiMethod::unset
  };

//static
CCopasiTask::Type CCopasiTask::XMLNameToEnum(const char * xmlTypeName)
{
  unsigned C_INT32 i = 0;
  while (XMLType[i] && strcmp(xmlTypeName, XMLType[i])) i++;

  if (XMLType[i]) return (CCopasiTask::Type) i;
  else return CCopasiTask::unset;
}

CCopasiTask::CCopasiTask(const std::string & name,
                         const CCopasiContainer * pParent,
                         const std::string & type):
    CCopasiContainer(name, pParent, type),
    mType(CCopasiTask::unset),
    mKey(GlobalKeys.add("Task", this)),
    mDescription(this),
    mResult(this),
    mScheduled(false),
    mUpdateModel(false),
    mpInitialState(NULL),
    mpProblem(NULL),
    mpMethod(NULL),
    mReport(),
    mpCurrentReport(&mReport),
    mpOutputHandler(NULL),
    mpCallBack(NULL),
    mpSliders(NULL),
    mDoOutput(OUTPUT_COMPLETE),
    mOutputCounter(0)
{initObjects();}

CCopasiTask::CCopasiTask(const CCopasiTask::Type & taskType,
                         const CCopasiContainer * pParent,
                         const std::string & type):
    CCopasiContainer(CCopasiTask::TypeName[taskType], pParent, type),
    mType(taskType),
    mKey(GlobalKeys.add("Task", this)),
    mDescription(this),
    mResult(this),
    mScheduled(false),
    mUpdateModel(false),
    mpInitialState(NULL),
    mpProblem(NULL),
    mpMethod(NULL),
    mReport(),
    mpCurrentReport(&mReport),
    mpOutputHandler(NULL),
    mpCallBack(NULL),
    mpSliders(NULL),
    mDoOutput(OUTPUT_COMPLETE),
    mOutputCounter(0)
{initObjects();}

CCopasiTask::CCopasiTask(const CCopasiTask & src,
                         const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mType(src.mType),
    mKey(GlobalKeys.add("Task", this)),
    mDescription(src.mDescription, this),
    mResult(src.mResult, this),
    mScheduled(src.mScheduled),
    mUpdateModel(src.mUpdateModel),
    mpInitialState(src.mpInitialState ? new CState(*src.mpInitialState) : NULL),
    mpProblem(NULL),
    mpMethod(NULL),
    mReport(src.mReport),
    mpCurrentReport(src.mpCurrentReport),
    mpOutputHandler(NULL),
    mpCallBack(NULL),
    mpSliders(NULL),
    mDoOutput(OUTPUT_COMPLETE),
    mOutputCounter(0)
{initObjects();}

CCopasiTask::~CCopasiTask()
{
  GlobalKeys.remove(mKey);

  pdelete(mpInitialState);
  pdelete(mpProblem);
  pdelete(mpMethod);
  pdelete(mpSliders);
}

//const std::string & CCopasiTask::getName() const {return getObjectName();}

bool CCopasiTask::setName(const std::string & name)
{return setObjectName(name);}

CCopasiTask::Type CCopasiTask::getType() const {return mType;}

void CCopasiTask::setType(const CCopasiTask::Type & type) {mType = type;}

const std::string & CCopasiTask::getKey() const {return mKey;}

void CCopasiTask::setScheduled(const bool & scheduled) {mScheduled = scheduled;}

const bool & CCopasiTask::isScheduled() const {return mScheduled;}

void CCopasiTask::setUpdateModel(const bool & updateModel) {mUpdateModel = updateModel;}

const bool & CCopasiTask::isUpdateModel() const {return mUpdateModel;}

bool CCopasiTask::setCallBack(CProcessReport * pCallBack)
{
  mpCallBack = pCallBack;
  return true;
}

CProcessReport * CCopasiTask::getCallBack() const
  {
    return mpCallBack;
  }

bool CCopasiTask::initialize(const OutputFlag & of,
                             std::ostream * pOstream)
{
  bool success = true;

  if (!mpProblem)
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 1, getObjectName().c_str());
      return false;
    }
  if (!mpProblem->getModel())
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 2, getObjectName().c_str());
      return false;
    }
  if (!mpMethod)
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 3, getObjectName().c_str());
      return false;
    }

  if (!mpProblem->getModel()->compileIfNecessary())
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 4, mpProblem->getModel()->getObjectName().c_str());
      return false;
    }

  mDoOutput = of;
  if (mDoOutput == NO_OUTPUT) return true;

  if (!mReport.open(pOstream))
    {
      // Warning
      CCopasiMessage(CCopasiMessage::WARNING, MCCopasiTask + 5, mReport.getObjectName().c_str());
      success = false;
    }
  if (!mReport.compile())
    {
      // Warning
      CCopasiMessage(CCopasiMessage::WARNING, MCCopasiTask + 6, mReport.getObjectName().c_str());
      success = false;
    }

  if (!mUpdateModel)
    {
      pdelete(mpInitialState);
      mpInitialState = new CState(mpProblem->getModel()->getInitialState());
    }

  return success;
}

bool CCopasiTask::process(const bool &)
{return false;}

//bool CCopasiTask::processForScan(bool C_UNUSED(useInitialConditions), bool C_UNUSED(doOutput)) {return false;}

bool CCopasiTask::restore()
{
  //mReport.close();
  setCallBack(NULL);

  if (!mUpdateModel && mpInitialState)
    mpProblem->getModel()->setInitialState(mpInitialState);

  return true;
}

CCopasiProblem * CCopasiTask::getProblem() {return mpProblem;}

const CCopasiProblem * CCopasiTask::getProblem() const {return mpProblem;}

bool CCopasiTask::setMethodType(const int & C_UNUSED(type))
{return false;}

CCopasiMethod * CCopasiTask::getMethod() {return mpMethod;}

const CCopasiMethod * CCopasiTask::getMethod() const {return mpMethod;}

CReport & CCopasiTask::getReport() {return mReport;}

const CCopasiTask::CDescription & CCopasiTask::getDescription() const
  {return mDescription;}

const CCopasiTask::CResult & CCopasiTask::getResult() const
  {return mResult;}

void CCopasiTask::cleanup() {}

void CCopasiTask::setOutputHandler(CCallbackHandler* pHandler)
{mpOutputHandler = pHandler;}

CCallbackHandler* CCopasiTask::getOutputHandlerAddr()
{return mpOutputHandler;}

/*
void CCopasiTask::setProgressHandler(CProcessReport * pHandler)
{mpCallBack = pHandler;}
 */

CCopasiParameterGroup * CCopasiTask::getSliders()
{return mpSliders;}

// output stuff

bool CCopasiTask::initOutput()
{
  mOutputCounter = 0;

  if (mDoOutput == OUTPUT_COMPLETE)
    {
      if (mpCurrentReport) mpCurrentReport->printHeader();
      if (mpOutputHandler) mpOutputHandler->init();
    }
  return true;
}

bool CCopasiTask::doOutput()
{
  if (mDoOutput)
    {
      if (mpCurrentReport) mpCurrentReport->printBody();
      if (mpOutputHandler) mpOutputHandler->doOutput();
    }
  ++mOutputCounter;
  return true;
}

bool CCopasiTask::finishOutput()
{
  if (mDoOutput == OUTPUT_COMPLETE)
    {
      if (mpCurrentReport)
        {
          mpCurrentReport->printFooter();
          mpCurrentReport->close();
        }
      if (mpOutputHandler) mpOutputHandler->finish();
    }
  return true;
}

bool CCopasiTask::separatorOutput()
{
  if (mDoOutput == OUTPUT_COMPLETE)
    {
      if (mpCurrentReport) mpCurrentReport->printEmptyLine();
      if (mpOutputHandler) mpOutputHandler->doSeparator();
    }
  return true;
}

void CCopasiTask::initObjects()
{
  addObjectReference("Output counter", mOutputCounter, CCopasiObject::ValueInt);
}

CCopasiTask::CDescription::CDescription(const CCopasiContainer * pParent):
CCopasiObject("Description", pParent, "Object")
{}

CCopasiTask::CDescription::CDescription(const CCopasiTask::CDescription & src,
                                        const CCopasiContainer * pParent):
    CCopasiObject(src, pParent)
{}

CCopasiTask::CDescription::~CDescription() {}

void CCopasiTask::CDescription::print(std::ostream * ostream) const
  {*ostream << *this;}

std::ostream &operator<<(std::ostream &os,
                         const CCopasiTask::CDescription & o)
{
  const CCopasiTask & Task = *static_cast<const CCopasiTask *>(o.getObjectParent());

  os << Task.getObjectName() << " Task" << std::endl << std::endl;

  if (Task.getProblem())
    {
      Task.getProblem()->print(&os);
      os << std::endl;
    }
  else
    os << "No Problem Specified!" << std::endl;

  if (Task.getMethod())
    {
      Task.getMethod()->print(&os);
      os << std::endl;
    }
  else
    os << "No Method Specified!" << std::endl;

  return os;
}

CCopasiTask::CResult::CResult(const CCopasiContainer * pParent):
    CCopasiObject("Result", pParent, "Object")
{}

CCopasiTask::CResult::CResult(const CCopasiTask::CResult & src,
                              const CCopasiContainer * pParent):
    CCopasiObject(src, pParent)
{}

CCopasiTask::CResult::~CResult() {}

void CCopasiTask::CResult::print(std::ostream * ostream) const
  {*ostream << *this;}

std::ostream &operator<<(std::ostream &os,
                         const CCopasiTask::CResult & o)
{
  const CCopasiTask & Task = *static_cast<const CCopasiTask *>(o.getObjectParent());

  os << Task.getObjectName() << " Result:" << std::endl << std::endl;

  if (Task.getProblem())
    {
      Task.getProblem()->printResult(&os);
      os << std::endl;
    }
  else
    os << "No Problem Specified!" << std::endl;

  return os;
}
<commit_msg>restore calls now mpProblem->restore if mUpdateModel is false.<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/utilities/CCopasiTask.cpp,v $
   $Revision: 1.37 $
   $Name:  $
   $Author: shoops $
   $Date: 2005/11/11 12:40:26 $
   End CVS Header */

/**
 *  CCopasiTask class.
 *  This class is used to describe a task in COPASI. This class is
 *  intended to be used as the parent class for all tasks whithin COPASI.
 *
 *  Created for Copasi by Stefan Hoops 2003
 */

#include "copasi.h"

#include "CCopasiTask.h"
#include "CCopasiProblem.h"
#include "CCopasiMethod.h"
#include "report/CReport.h"
#include "report/CKeyFactory.h"
#include "utilities/COutputHandler.h"
#include "model/CModel.h"
#include "model/CState.h"
#include "report/CCopasiObjectReference.h"

const std::string CCopasiTask::TypeName[] =
  {
    "Steady-State",
    "Time-Course",
    "Scan",
    "Elementary Flux Modes",
    "Optimization",
    "Parameter Fitting",
    "Metabolic Control Analysis",
    "Time scale separation",
    "Sensitivities",
    ""
  };

const char* CCopasiTask::XMLType[] =
  {
    "steadyState",
    "timeCourse",
    "scan",
    "fluxMode",
    "optimization",
    "parameterFitting",
    "metabolicControlAnalysis",
    "timeScaleSeparation",
    "sensitivities",
    NULL
  };

const unsigned C_INT32 CCopasiTask::ValidMethods[] =
  {
    CCopasiMethod::unset
  };

//static
CCopasiTask::Type CCopasiTask::XMLNameToEnum(const char * xmlTypeName)
{
  unsigned C_INT32 i = 0;
  while (XMLType[i] && strcmp(xmlTypeName, XMLType[i])) i++;

  if (XMLType[i]) return (CCopasiTask::Type) i;
  else return CCopasiTask::unset;
}

CCopasiTask::CCopasiTask(const std::string & name,
                         const CCopasiContainer * pParent,
                         const std::string & type):
    CCopasiContainer(name, pParent, type),
    mType(CCopasiTask::unset),
    mKey(GlobalKeys.add("Task", this)),
    mDescription(this),
    mResult(this),
    mScheduled(false),
    mUpdateModel(false),
    mpInitialState(NULL),
    mpProblem(NULL),
    mpMethod(NULL),
    mReport(),
    mpCurrentReport(&mReport),
    mpOutputHandler(NULL),
    mpCallBack(NULL),
    mpSliders(NULL),
    mDoOutput(OUTPUT_COMPLETE),
    mOutputCounter(0)
{initObjects();}

CCopasiTask::CCopasiTask(const CCopasiTask::Type & taskType,
                         const CCopasiContainer * pParent,
                         const std::string & type):
    CCopasiContainer(CCopasiTask::TypeName[taskType], pParent, type),
    mType(taskType),
    mKey(GlobalKeys.add("Task", this)),
    mDescription(this),
    mResult(this),
    mScheduled(false),
    mUpdateModel(false),
    mpInitialState(NULL),
    mpProblem(NULL),
    mpMethod(NULL),
    mReport(),
    mpCurrentReport(&mReport),
    mpOutputHandler(NULL),
    mpCallBack(NULL),
    mpSliders(NULL),
    mDoOutput(OUTPUT_COMPLETE),
    mOutputCounter(0)
{initObjects();}

CCopasiTask::CCopasiTask(const CCopasiTask & src,
                         const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mType(src.mType),
    mKey(GlobalKeys.add("Task", this)),
    mDescription(src.mDescription, this),
    mResult(src.mResult, this),
    mScheduled(src.mScheduled),
    mUpdateModel(src.mUpdateModel),
    mpInitialState(src.mpInitialState ? new CState(*src.mpInitialState) : NULL),
    mpProblem(NULL),
    mpMethod(NULL),
    mReport(src.mReport),
    mpCurrentReport(src.mpCurrentReport),
    mpOutputHandler(NULL),
    mpCallBack(NULL),
    mpSliders(NULL),
    mDoOutput(OUTPUT_COMPLETE),
    mOutputCounter(0)
{initObjects();}

CCopasiTask::~CCopasiTask()
{
  GlobalKeys.remove(mKey);

  pdelete(mpInitialState);
  pdelete(mpProblem);
  pdelete(mpMethod);
  pdelete(mpSliders);
}

//const std::string & CCopasiTask::getName() const {return getObjectName();}

bool CCopasiTask::setName(const std::string & name)
{return setObjectName(name);}

CCopasiTask::Type CCopasiTask::getType() const {return mType;}

void CCopasiTask::setType(const CCopasiTask::Type & type) {mType = type;}

const std::string & CCopasiTask::getKey() const {return mKey;}

void CCopasiTask::setScheduled(const bool & scheduled) {mScheduled = scheduled;}

const bool & CCopasiTask::isScheduled() const {return mScheduled;}

void CCopasiTask::setUpdateModel(const bool & updateModel) {mUpdateModel = updateModel;}

const bool & CCopasiTask::isUpdateModel() const {return mUpdateModel;}

bool CCopasiTask::setCallBack(CProcessReport * pCallBack)
{
  mpCallBack = pCallBack;
  return true;
}

CProcessReport * CCopasiTask::getCallBack() const
  {
    return mpCallBack;
  }

bool CCopasiTask::initialize(const OutputFlag & of,
                             std::ostream * pOstream)
{
  bool success = true;

  if (!mpProblem)
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 1, getObjectName().c_str());
      return false;
    }
  if (!mpProblem->getModel())
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 2, getObjectName().c_str());
      return false;
    }
  if (!mpMethod)
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 3, getObjectName().c_str());
      return false;
    }

  if (!mpProblem->getModel()->compileIfNecessary())
    {
      CCopasiMessage(CCopasiMessage::ERROR, MCCopasiTask + 4, mpProblem->getModel()->getObjectName().c_str());
      return false;
    }

  mDoOutput = of;
  if (mDoOutput == NO_OUTPUT) return true;

  if (!mReport.open(pOstream))
    {
      // Warning
      CCopasiMessage(CCopasiMessage::WARNING, MCCopasiTask + 5, mReport.getObjectName().c_str());
      success = false;
    }
  if (!mReport.compile())
    {
      // Warning
      CCopasiMessage(CCopasiMessage::WARNING, MCCopasiTask + 6, mReport.getObjectName().c_str());
      success = false;
    }

  if (!mUpdateModel)
    {
      pdelete(mpInitialState);
      mpInitialState = new CState(mpProblem->getModel()->getInitialState());
    }

  return success;
}

bool CCopasiTask::process(const bool &)
{return false;}

//bool CCopasiTask::processForScan(bool C_UNUSED(useInitialConditions), bool C_UNUSED(doOutput)) {return false;}

bool CCopasiTask::restore()
{
  //mReport.close();
  setCallBack(NULL);

  if (!mUpdateModel)
    {
      if (mpInitialState)
        mpProblem->getModel()->setInitialState(mpInitialState);

      mpProblem->restore();
    }

  return true;
}

CCopasiProblem * CCopasiTask::getProblem() {return mpProblem;}

const CCopasiProblem * CCopasiTask::getProblem() const {return mpProblem;}

bool CCopasiTask::setMethodType(const int & C_UNUSED(type))
{return false;}

CCopasiMethod * CCopasiTask::getMethod() {return mpMethod;}

const CCopasiMethod * CCopasiTask::getMethod() const {return mpMethod;}

CReport & CCopasiTask::getReport() {return mReport;}

const CCopasiTask::CDescription & CCopasiTask::getDescription() const
  {return mDescription;}

const CCopasiTask::CResult & CCopasiTask::getResult() const
  {return mResult;}

void CCopasiTask::cleanup() {}

void CCopasiTask::setOutputHandler(CCallbackHandler* pHandler)
{mpOutputHandler = pHandler;}

CCallbackHandler* CCopasiTask::getOutputHandlerAddr()
{return mpOutputHandler;}

/*
void CCopasiTask::setProgressHandler(CProcessReport * pHandler)
{mpCallBack = pHandler;}
 */

CCopasiParameterGroup * CCopasiTask::getSliders()
{return mpSliders;}

// output stuff

bool CCopasiTask::initOutput()
{
  mOutputCounter = 0;

  if (mDoOutput == OUTPUT_COMPLETE)
    {
      if (mpCurrentReport) mpCurrentReport->printHeader();
      if (mpOutputHandler) mpOutputHandler->init();
    }
  return true;
}

bool CCopasiTask::doOutput()
{
  if (mDoOutput)
    {
      if (mpCurrentReport) mpCurrentReport->printBody();
      if (mpOutputHandler) mpOutputHandler->doOutput();
    }
  ++mOutputCounter;
  return true;
}

bool CCopasiTask::finishOutput()
{
  if (mDoOutput == OUTPUT_COMPLETE)
    {
      if (mpCurrentReport)
        {
          mpCurrentReport->printFooter();
          mpCurrentReport->close();
        }
      if (mpOutputHandler) mpOutputHandler->finish();
    }
  return true;
}

bool CCopasiTask::separatorOutput()
{
  if (mDoOutput == OUTPUT_COMPLETE)
    {
      if (mpCurrentReport) mpCurrentReport->printEmptyLine();
      if (mpOutputHandler) mpOutputHandler->doSeparator();
    }
  return true;
}

void CCopasiTask::initObjects()
{
  addObjectReference("Output counter", mOutputCounter, CCopasiObject::ValueInt);
}

CCopasiTask::CDescription::CDescription(const CCopasiContainer * pParent):
CCopasiObject("Description", pParent, "Object")
{}

CCopasiTask::CDescription::CDescription(const CCopasiTask::CDescription & src,
                                        const CCopasiContainer * pParent):
    CCopasiObject(src, pParent)
{}

CCopasiTask::CDescription::~CDescription() {}

void CCopasiTask::CDescription::print(std::ostream * ostream) const
  {*ostream << *this;}

std::ostream &operator<<(std::ostream &os,
                         const CCopasiTask::CDescription & o)
{
  const CCopasiTask & Task = *static_cast<const CCopasiTask *>(o.getObjectParent());

  os << Task.getObjectName() << " Task" << std::endl << std::endl;

  if (Task.getProblem())
    {
      Task.getProblem()->print(&os);
      os << std::endl;
    }
  else
    os << "No Problem Specified!" << std::endl;

  if (Task.getMethod())
    {
      Task.getMethod()->print(&os);
      os << std::endl;
    }
  else
    os << "No Method Specified!" << std::endl;

  return os;
}

CCopasiTask::CResult::CResult(const CCopasiContainer * pParent):
    CCopasiObject("Result", pParent, "Object")
{}

CCopasiTask::CResult::CResult(const CCopasiTask::CResult & src,
                              const CCopasiContainer * pParent):
    CCopasiObject(src, pParent)
{}

CCopasiTask::CResult::~CResult() {}

void CCopasiTask::CResult::print(std::ostream * ostream) const
  {*ostream << *this;}

std::ostream &operator<<(std::ostream &os,
                         const CCopasiTask::CResult & o)
{
  const CCopasiTask & Task = *static_cast<const CCopasiTask *>(o.getObjectParent());

  os << Task.getObjectName() << " Result:" << std::endl << std::endl;

  if (Task.getProblem())
    {
      Task.getProblem()->printResult(&os);
      os << std::endl;
    }
  else
    os << "No Problem Specified!" << std::endl;

  return os;
}
<|endoftext|>


<commit_before>/*
 * Tests for the next hop computation (LFDB).
 *
 * Copyright (C) 2018 Vincenzo Maffione
 * Author: Vincenzo Maffione <v.maffione@gmail.com>
 *
 * This file is part of rlite.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */
#include <iostream>
#include <sstream>
#include <list>
#include <vector>
#include <cassert>
#include <chrono>
#include <unistd.h>
#include <cmath>

#include "uipcp-normal-lfdb.hpp"

using NextHops = std::unordered_map<rlite::NodeId, std::list<rlite::NodeId>>;

struct TestLFDB : public rlite::LFDB {
    using LinksList = std::vector<std::pair<int, int>>;
    LinksList links;

    TestLFDB(const LinksList &links, bool lfa_enabled)
        : rlite::LFDB(lfa_enabled, /*verbose=*/false), links(links)
    {
        for (const auto &link : links) {
            gpb::LowerFlow lf1, lf2;

            lf1.set_local_node(std::to_string(link.first));
            lf1.set_remote_node(std::to_string(link.second));
            lf2.set_local_node(std::to_string(link.second));
            lf2.set_remote_node(std::to_string(link.first));
            lf1.set_cost(1);
            lf2.set_cost(1);
            lf1.set_seqnum(1);
            lf2.set_seqnum(1);
            lf1.set_state(true);
            lf2.set_state(true);
            lf1.set_age(0);
            lf2.set_age(0);

            db[lf1.local_node()][lf1.remote_node()] = lf1;
            db[lf2.local_node()][lf2.remote_node()] = lf2;
        }
    }

    bool reachable(int src_node, int dst_node, int n)
    {
        std::string src = std::to_string(src_node);
        std::string dst = std::to_string(dst_node);
        std::string cur = src;

        for (; n >= 0; n--) {
        }
        return true;
    }
};

static void
usage()
{
    std::cout << "lfdb-test -n SIZE\n"
                 "          -v be verbose\n"
                 "          -h show this help and exit\n";
}

int
main(int argc, char **argv)
{
    int verbosity = 0;
    int n         = 100;
    int opt;

    while ((opt = getopt(argc, argv, "hvn:")) != -1) {
        switch (opt) {
        case 'h':
            usage();
            return 0;

        case 'v':
            verbosity++;
            break;

        case 'n':
            n = std::atoi(optarg);
            break;

        default:
            std::cout << "    Unrecognized option " << static_cast<char>(opt)
                      << std::endl;
            usage();
            return -1;
        }
    }

    std::list<TestLFDB::LinksList> test_vectors = {
        {{0, 2}, {0, 3}, {0, 4}, {2, 4}, {3, 4}}};

    {
        /* Grid-shaped network of size NxN. */
        TestLFDB::LinksList links;
        int sqn = static_cast<int>(std::sqrt(n));

        if (sqn < 2) {
            sqn = 2;
        }

        auto coord = [sqn](int i, int j) { return i * sqn + j; };

        for (int i = 0; i < sqn; i++) {
            for (int j = 0; j < sqn - 1; j++) {
                links.push_back({coord(i, j), coord(i, j + 1)});
                links.push_back({coord(j, i), coord(j + 1, i)});
            }
        }

        test_vectors.push_back(std::move(links));
    }

    int counter = 1;
    for (const auto &links : test_vectors) {
        std::cout << "Test vector #" << counter++ << std::endl;

        TestLFDB lfdb(links, /*lfa_enabled=*/false);

        if (verbosity) {
            std::stringstream ss;
            lfdb.dump(ss);
            std::cout << ss.str();
        }
        assert(!links.empty());

        std::unordered_map<rlite::NodeId, NextHops> rtables;

        auto start = std::chrono::system_clock::now();
        for (const auto &kv : lfdb.db) {
            const rlite::NodeId &source = kv.first;

            lfdb.compute_next_hops(source);
            if (verbosity) {
                std::stringstream ss;
                lfdb.dump_routing(ss, source);
                std::cout << ss.str();
            }
            rtables[source] = std::move(lfdb.next_hops);
        }
        auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now() - start);

        std::cout << "Completed in " << delta.count() << " ms" << std::endl;
    }

    return 0;
}
<commit_msg>uipcps: lfdb-test: implement reachability test<commit_after>/*
 * Tests for the next hop computation (LFDB).
 *
 * Copyright (C) 2018 Vincenzo Maffione
 * Author: Vincenzo Maffione <v.maffione@gmail.com>
 *
 * This file is part of rlite.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */
#include <iostream>
#include <sstream>
#include <list>
#include <vector>
#include <cassert>
#include <chrono>
#include <unistd.h>
#include <cmath>

#include "uipcp-normal-lfdb.hpp"

using NextHops = std::unordered_map<rlite::NodeId, std::list<rlite::NodeId>>;
using RoutingTables =
    std::unordered_map<rlite::NodeId, std::pair<NextHops, rlite::NodeId>>;

struct TestLFDB : public rlite::LFDB {
    using LinksList = std::vector<std::pair<int, int>>;
    LinksList links;

    TestLFDB(const LinksList &links, bool lfa_enabled)
        : rlite::LFDB(lfa_enabled, /*verbose=*/false), links(links)
    {
        for (const auto &link : links) {
            gpb::LowerFlow lf1, lf2;

            lf1.set_local_node(std::to_string(link.first));
            lf1.set_remote_node(std::to_string(link.second));
            lf2.set_local_node(std::to_string(link.second));
            lf2.set_remote_node(std::to_string(link.first));
            lf1.set_cost(1);
            lf2.set_cost(1);
            lf1.set_seqnum(1);
            lf2.set_seqnum(1);
            lf1.set_state(true);
            lf2.set_state(true);
            lf1.set_age(0);
            lf2.set_age(0);

            db[lf1.local_node()][lf1.remote_node()] = lf1;
            db[lf2.local_node()][lf2.remote_node()] = lf2;
        }
    }
};

static bool
reachable(const RoutingTables &rtables, int src_node, int dst_node, int n)
{
    rlite::NodeId dst = std::to_string(dst_node);
    rlite::NodeId cur = std::to_string(src_node);

    for (; n >= 0 && cur != dst; n--) {
        const auto &rt                 = rtables.at(cur);
        NextHops::const_iterator nhops = rt.first.find(dst);

        if (nhops != rt.first.end()) {
            /* Entry find in the routing table. */
            cur = nhops->second.front();
        } else {
            /* Not found, use default next hop. */
            cur = rt.second;
        }
    }
    return cur == dst && n == 0;
}

static void
usage()
{
    std::cout << "lfdb-test -n SIZE\n"
                 "          -v be verbose\n"
                 "          -h show this help and exit\n";
}

int
main(int argc, char **argv)
{
    int verbosity = 0;
    int n         = 100;
    int opt;

    while ((opt = getopt(argc, argv, "hvn:")) != -1) {
        switch (opt) {
        case 'h':
            usage();
            return 0;

        case 'v':
            verbosity++;
            break;

        case 'n':
            n = std::atoi(optarg);
            break;

        default:
            std::cout << "    Unrecognized option " << static_cast<char>(opt)
                      << std::endl;
            usage();
            return -1;
        }
    }

    std::list<TestLFDB::LinksList> test_vectors = {
        {{0, 1}, {0, 2}, {0, 3}, {1, 3}, {2, 3}}};

    {
        /* Grid-shaped network of size NxN. */
        TestLFDB::LinksList links;
        int sqn = static_cast<int>(std::sqrt(n));

        if (sqn < 2) {
            sqn = 2;
        }

        auto coord = [sqn](int i, int j) { return i * sqn + j; };

        for (int i = 0; i < sqn; i++) {
            for (int j = 0; j < sqn - 1; j++) {
                links.push_back({coord(i, j), coord(i, j + 1)});
                links.push_back({coord(j, i), coord(j + 1, i)});
            }
        }

        test_vectors.push_back(std::move(links));
    }

    int counter = 1;
    for (const auto &links : test_vectors) {
        std::cout << "Test vector #" << counter++ << std::endl;

        TestLFDB lfdb(links, /*lfa_enabled=*/false);

        if (verbosity) {
            std::stringstream ss;
            lfdb.dump(ss);
            std::cout << ss.str();
        }
        assert(!links.empty());

        RoutingTables rtables;

        auto start = std::chrono::system_clock::now();
        for (const auto &kv : lfdb.db) {
            const rlite::NodeId &source = kv.first;

            lfdb.compute_next_hops(source);
            if (verbosity) {
                std::stringstream ss;
                lfdb.dump_routing(ss, source);
                std::cout << ss.str();
            }
            rtables[source] =
                make_pair(std::move(lfdb.next_hops), std::move(lfdb.dflt_nhop));
        }
        auto delta = std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::system_clock::now() - start);

        if (reachable(rtables, 0, 1, 1)) {
            std::cout << "Reachable!" << std::endl;
        }

        std::cout << "Completed in " << delta.count() << " ms" << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>/* medViewContainer.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Mon Oct 26 21:54:57 2009 (+0100)
 * Version: $Id$
 * Last-Updated: Tue Jun 15 16:26:36 2010 (+0200)
 *           By: Julien Wintz
 *     Update #: 425
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "medViewContainer.h"
#include "medViewContainer_p.h"
#include "medViewPool.h"

#include <QtGui>

#include <dtkCore/dtkAbstractView.h>
#include <medCore/medDataIndex.h>

medViewContainer::medViewContainer(QWidget *parent) : QWidget(parent), d(new medViewContainerPrivate)
{
    d->layout = new QGridLayout(this);
    d->layout->setContentsMargins(0, 0, 0, 0);
    d->layout->setSpacing(2);

    d->view = NULL;
    d->current = this;

    d->pool = new medViewPool;

    if(medViewContainer *container = dynamic_cast<medViewContainer *>(parent)) {
        connect(this, SIGNAL(dropped(const medDataIndex&)), container, SIGNAL(dropped(const medDataIndex&)));
        connect(this, SIGNAL(focused(dtkAbstractView*)), container, SIGNAL(focused(dtkAbstractView*)));
    }

    this->setAcceptDrops(true);
    this->setFocusPolicy(Qt::ClickFocus);
    this->setMouseTracking(true);
}

medViewContainer::~medViewContainer(void)
{
    delete d;

    d = NULL;
}

medViewContainer::Type medViewContainer::type(void)
{
    return Default;
}

medViewContainer *medViewContainer::current(void)
{
    return d->current;
}

void medViewContainer::split(int rows, int cols)
{
    Q_UNUSED(rows);
    Q_UNUSED(cols);
}

dtkAbstractView *medViewContainer::view(void) const
{
    return d->view;
}

QList<dtkAbstractView *> medViewContainer::views(void) const
{
    QList<dtkAbstractView *> views;
    if (d->view)
        views << d->view;

    return views;
}

medViewPool *medViewContainer::pool (void)
{
    return d->pool;
}

void medViewContainer::setView(dtkAbstractView *view)
{
    if (!view)
        return;

    if (view==d->view)
        return;

    d->view = view;

    // pass properties to the view
    QHash<QString,QString>::iterator it = d->viewProperties.begin();
    while (it!=d->viewProperties.end()) {
        view->setProperty (it.key(), it.value());
	++it;
    }
}

void medViewContainer::setCurrent(medViewContainer *container)
{
    if(medViewContainer *parent = dynamic_cast<medViewContainer *>(this->parentWidget()))
        parent->setCurrent(container);
    else
        d->current = container;
}

void medViewContainer::dragEnterEvent(QDragEnterEvent *event)
{
    event->acceptProposedAction();
}

void medViewContainer::dragMoveEvent(QDragMoveEvent *event)
{
    event->acceptProposedAction();
}

void medViewContainer::dragLeaveEvent(QDragLeaveEvent *event)
{
    event->accept();
}

void medViewContainer::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData();

    if (mimeData->hasFormat("med/index")) {
        QStringList ids = QString(mimeData->data("med/index")).split(":");
        int patientId = ids.at(0).toInt();
        int   studyId = ids.at(1).toInt();
        int  seriesId = ids.at(2).toInt();
        int   imageId = ids.at(3).toInt();

        emit dropped(medDataIndex(patientId, studyId, seriesId, imageId));
    }

    event->acceptProposedAction();
}

void medViewContainer::focusInEvent(QFocusEvent *event)
{
    Q_UNUSED(event);

    medViewContainer *former = this->current();

    this->setCurrent(this);

    if(dtkAbstractView *view = this->view())
        emit focused(view);

	if (former)
        former->update();
    this->update();
}

void medViewContainer::focusOutEvent(QFocusEvent *event)
{
    Q_UNUSED(event);
}

void medViewContainer::paintEvent(QPaintEvent *event)
{
    if(this->layout()->count() > 1)
        return;

    QWidget::paintEvent(event);

    QPainter painter;
    painter.begin(this);

    if (this->view() && this->view()->property ("Daddy")=="true")
        painter.setPen(Qt::red);
    else {
      if (d->current == this)
        painter.setPen(QColor(0x9a, 0xb3, 0xd5));
      else
        painter.setPen(Qt::darkGray);
    }

    painter.setBrush(QColor(0x38, 0x38, 0x38));
    painter.drawRect(this->rect().adjusted(0, 0, -1, -1));

    if (!this->view() && d->viewProperties.count()) {
        painter.setPen(Qt::white);
	QFont font = painter.font();
	font.setPointSize (18);
	painter.setFont (font);
	QString text;
	QList<QString> keys = d->viewProperties.keys();
	foreach (QString key, keys)
	  text += d->viewProperties[key] + "\n";
	painter.drawText (event->rect(), Qt::AlignCenter, text);
    }

    painter.end();
}

void medViewContainer::setViewProperty (const QString &key, const QString &value)
{
    d->viewProperties[key] = value;
}

QString medViewContainer::viewProperty (const QString &key) const
{
    if (d->viewProperties.contains (key))
        return d->viewProperties[key];

    return QString();
}

void medViewContainer::onViewFullScreen (bool value)
{
    Q_UNUSED (value);
}
<commit_msg>Giving an expanding size policy to container is better for switching a view in full screen<commit_after>/* medViewContainer.cpp ---
 *
 * Author: Julien Wintz
 * Copyright (C) 2008 - Julien Wintz, Inria.
 * Created: Mon Oct 26 21:54:57 2009 (+0100)
 * Version: $Id$
 * Last-Updated: Tue Jun 15 16:26:36 2010 (+0200)
 *           By: Julien Wintz
 *     Update #: 425
 */

/* Commentary:
 *
 */

/* Change log:
 *
 */

#include "medViewContainer.h"
#include "medViewContainer_p.h"
#include "medViewPool.h"

#include <QtGui>

#include <dtkCore/dtkAbstractView.h>
#include <medCore/medDataIndex.h>

medViewContainer::medViewContainer(QWidget *parent) : QWidget(parent), d(new medViewContainerPrivate)
{
    d->layout = new QGridLayout(this);
    d->layout->setContentsMargins(0, 0, 0, 0);
    d->layout->setSpacing(2);

    d->view = NULL;
    d->current = this;

    d->pool = new medViewPool;

    if(medViewContainer *container = dynamic_cast<medViewContainer *>(parent)) {
        connect(this, SIGNAL(dropped(const medDataIndex&)), container, SIGNAL(dropped(const medDataIndex&)));
        connect(this, SIGNAL(focused(dtkAbstractView*)), container, SIGNAL(focused(dtkAbstractView*)));
    }

    this->setAcceptDrops(true);
    this->setFocusPolicy(Qt::ClickFocus);
    this->setMouseTracking(true);
    this->setSizePolicy (QSizePolicy::Expanding,QSizePolicy::Expanding);
}

medViewContainer::~medViewContainer(void)
{
    delete d;

    d = NULL;
}

medViewContainer::Type medViewContainer::type(void)
{
    return Default;
}

medViewContainer *medViewContainer::current(void)
{
    return d->current;
}

void medViewContainer::split(int rows, int cols)
{
    Q_UNUSED(rows);
    Q_UNUSED(cols);
}

dtkAbstractView *medViewContainer::view(void) const
{
    return d->view;
}

QList<dtkAbstractView *> medViewContainer::views(void) const
{
    QList<dtkAbstractView *> views;
    if (d->view)
        views << d->view;

    return views;
}

medViewPool *medViewContainer::pool (void)
{
    return d->pool;
}

void medViewContainer::setView(dtkAbstractView *view)
{
    if (!view)
        return;

    if (view==d->view)
        return;

    d->view = view;

    // pass properties to the view
    QHash<QString,QString>::iterator it = d->viewProperties.begin();
    while (it!=d->viewProperties.end()) {
        view->setProperty (it.key(), it.value());
	++it;
    }
}

void medViewContainer::setCurrent(medViewContainer *container)
{
    if(medViewContainer *parent = dynamic_cast<medViewContainer *>(this->parentWidget()))
        parent->setCurrent(container);
    else
        d->current = container;
}

void medViewContainer::dragEnterEvent(QDragEnterEvent *event)
{
    event->acceptProposedAction();
}

void medViewContainer::dragMoveEvent(QDragMoveEvent *event)
{
    event->acceptProposedAction();
}

void medViewContainer::dragLeaveEvent(QDragLeaveEvent *event)
{
    event->accept();
}

void medViewContainer::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData();

    if (mimeData->hasFormat("med/index")) {
        QStringList ids = QString(mimeData->data("med/index")).split(":");
        int patientId = ids.at(0).toInt();
        int   studyId = ids.at(1).toInt();
        int  seriesId = ids.at(2).toInt();
        int   imageId = ids.at(3).toInt();

        emit dropped(medDataIndex(patientId, studyId, seriesId, imageId));
    }

    event->acceptProposedAction();
}

void medViewContainer::focusInEvent(QFocusEvent *event)
{
    Q_UNUSED(event);

    medViewContainer *former = this->current();

    this->setCurrent(this);

    if(dtkAbstractView *view = this->view())
        emit focused(view);

	if (former)
        former->update();
    this->update();
}

void medViewContainer::focusOutEvent(QFocusEvent *event)
{
    Q_UNUSED(event);
}

void medViewContainer::paintEvent(QPaintEvent *event)
{
    if(this->layout()->count() > 1)
        return;

    QWidget::paintEvent(event);

    QPainter painter;
    painter.begin(this);

    if (this->view() && this->view()->property ("Daddy")=="true")
        painter.setPen(Qt::red);
    else {
      if (d->current == this)
        painter.setPen(QColor(0x9a, 0xb3, 0xd5));
      else
        painter.setPen(Qt::darkGray);
    }

    painter.setBrush(QColor(0x38, 0x38, 0x38));
    painter.drawRect(this->rect().adjusted(0, 0, -1, -1));

    if (!this->view() && d->viewProperties.count()) {
        painter.setPen(Qt::white);
	QFont font = painter.font();
	font.setPointSize (18);
	painter.setFont (font);
	QString text;
	QList<QString> keys = d->viewProperties.keys();
	foreach (QString key, keys)
	  text += d->viewProperties[key] + "\n";
	painter.drawText (event->rect(), Qt::AlignCenter, text);
    }

    painter.end();
}

void medViewContainer::setViewProperty (const QString &key, const QString &value)
{
    d->viewProperties[key] = value;
}

QString medViewContainer::viewProperty (const QString &key) const
{
    if (d->viewProperties.contains (key))
        return d->viewProperties[key];

    return QString();
}

void medViewContainer::onViewFullScreen (bool value)
{
    Q_UNUSED (value);
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <jitk/transformer.hpp>

using namespace std;

namespace bohrium {
namespace jitk {

namespace {

// Help function that swap the two axes, 'axis1' and 'axis2', in all instructions in 'instr_list'
vector<InstrPtr> swap_axis(const vector<InstrPtr> &instr_list, int64_t axis1, int64_t axis2) {
    vector<InstrPtr> ret;
    for (const InstrPtr &instr: instr_list) {
        bh_instruction tmp(*instr);
        tmp.transpose(axis1, axis2);
        ret.push_back(std::make_shared<bh_instruction>(tmp));
    }
    return ret;
}

// Help function that swap the 'parent' block with its 'child' block.
// NB: 'child' must point to a block in 'parent._block_list'
vector<Block> swap_blocks(const LoopB &parent, const LoopB *child) {
    vector<Block> ret;
    for (const Block &b: parent._block_list) {
        LoopB loop;
        loop.rank = parent.rank;
        if (b.isInstr() or &b.getLoop() != child) {
            loop.size = parent.size;
            loop._block_list.push_back(b);
        } else {
            loop.size = child->size;
            const vector<InstrPtr> t = swap_axis(child->getAllInstr(), parent.rank, child->rank);
            loop._block_list.push_back(create_nested_block(t, child->rank, parent.size));
        }
        loop.metadata_update();
        ret.push_back(Block(std::move(loop)));
    }
    return ret;
}

// Help function that find a loop block within 'parent' that it make sense to swappable
const LoopB *find_swappable_sub_block(const LoopB &parent) {
    // For each sweep, we look for a sub-block that contains that sweep instructions.
    for (const InstrPtr sweep: parent._sweeps) {
        for (const Block &b: parent._block_list) {
            if (not b.isInstr()) {
                for (const Block &instr_block: b.getLoop()._block_list) {
                    if (instr_block.isInstr()) {
                        if (*instr_block.getInstr() == *sweep) {
                            return &b.getLoop();
                        }
                    }
                }
            }
        }
    }
    return NULL;
}

// Help function that collapses 'axis' and 'axis+1' in all instructions within 'loop'
// Returns false if encountering a non-compatible instruction
bool collapse_instr_axes(LoopB &loop, const int axis) {
    for (Block &block: loop._block_list) {
        if (block.isInstr()) {
            bh_instruction instr(*block.getInstr());
            const int sa = instr.sweep_axis();
            assert(sa != axis);
            assert(sa != axis+1);
            if (sa == axis or sa == axis+1) {
                return false;
            }
            for (size_t i=0; i<instr.operand.size(); ++i) {
                bh_view &view = instr.operand[i];
                if (not bh_is_constant(&view)) {
                    int _axis = axis;
                    if (i==0 and bh_opcode_is_reduction(instr.opcode)) {
                        _axis = sa < _axis ? _axis-1 : _axis;
                    }
                    assert(view.ndim > _axis+1);
                    if (view.shape[_axis+1] * view.stride[_axis+1] != view.stride[_axis]) {
                        return false;
                    }
                    view.shape[_axis] *= view.shape[_axis+1];
                    view.stride[_axis] = view.stride[_axis+1];
                }
            }
            instr.remove_axis(axis+1);
            block.setInstr(instr);
        } else {
            --block.getLoop().rank;
            if (not collapse_instr_axes(block.getLoop(), axis)) {
                return false;
            }
        }
    }
    loop.metadata_update();
    assert(loop.validation());
    return true;
}

// Help function that collapses 'loop' with its child if possible
bool collapse_loop_with_child(LoopB &loop) {
    // In order to be collapsable, 'loop' can only have one child, that child must be a loop, and both 'loop'
    // and the child cannot be sweeped
    if (loop._sweeps.empty() and loop._block_list.size() == 1 and loop._reshapable) {
        Block &child = loop._block_list[0];
        if ((not child.isInstr()) and child.getLoop()._sweeps.empty() and child.getLoop()._reshapable) {
            // Let's collapse with our single child
            loop.size *= loop._block_list[0].getLoop().size;
            // NB: we need the temporary step in order to avoid copying deleted data
            auto tmp = std::move(loop._block_list[0].getLoop()._block_list);
            loop._block_list = std::move(tmp);
            return collapse_instr_axes(loop, loop.rank);
        }
    }
    return false;
}
}

void push_reductions_inwards(vector<Block> &block_list) {
    vector<Block> block_list2(block_list);
    for(Block &b: block_list2) {
        if (not b.isInstr()) {
            push_reductions_inwards(b.getLoop()._block_list);
        }
    }
    vector<Block> ret;
    for(const Block &b: block_list2) {
        const LoopB *swappable;
        if (not b.isInstr() and (swappable = find_swappable_sub_block(b.getLoop())) != NULL)  {
            const vector<Block>tmp = swap_blocks(b.getLoop(), swappable);
            ret.insert(ret.end(), tmp.begin(), tmp.end());
        } else {
            ret.push_back(b);
        }
    }
}

void split_for_threading(vector<Block> &block_list, uint64_t min_threading, uint64_t cur_threading) {
    vector<Block> ret;

    for (const Block &block: block_list) {
        // For now, we cannot make an instruction or a sweeped block threadable
        if (block.isInstr() or block.getLoop()._sweeps.size() > 0) {
            ret.push_back(block);
            continue;
        }
        const LoopB &loop = block.getLoop();
        uint64_t max_nelem = 0; // The maximum number of element in loop, which tells use the best-case scenario
        for (const InstrPtr instr: loop.getAllInstr()) {
            if (instr->operand.size() > 0) {
                const uint64_t nelem = static_cast<uint64_t>(bh_nelements(instr->operand[0]));
                if (nelem > max_nelem)
                    max_nelem = nelem;
            }
        }
        if (loop._block_list.size() > 1 // We need minimum two blocks in order to split!
            and max_nelem > min_threading // Is it even possible to achieve our goal?
            and util_find_threaded_blocks(loop).second < min_threading-cur_threading) { // Is the goal already achieved?

            for (auto it = loop._block_list.begin(); it != loop._block_list.end(); ++it) {
                // First we will place all sub-blocks that cannot be threaded in a shared block
                {
                    LoopB newloop;
                    newloop.rank = loop.rank;
                    newloop.size = loop.size;
                    while (it != loop._block_list.end() and (it->isInstr() or it->getLoop()._sweeps.size() > 0)) {
                        assert(it->rank() == newloop.rank+1);
                        newloop._block_list.push_back(*it);
                        ++it;
                    }
                    if (not newloop._block_list.empty()) {
                        newloop.metadata_update();
                        ret.push_back(Block(std::move(newloop)));
                    }
                }
                // Then we place the highly threaded sub-block in its own block
                if (it != loop._block_list.end()) {
                    assert(not it->isInstr());
                    assert(it->getLoop()._sweeps.size() == 0);
                    LoopB newloop;
                    newloop.rank = loop.rank;
                    newloop.size = loop.size;
                    newloop._block_list.push_back(*it);
                    newloop.metadata_update();
                    ret.push_back(Block(std::move(newloop)));
                } else {
                    break;
                }
            }
        } else {
            ret.push_back(block);
        }
    }
}

void collapse_redundant_axes(vector<Block> &block_list) {
    vector<Block> block_list2(block_list);
    for(Block &b: block_list2) {
        if (not b.isInstr()) {
            collapse_redundant_axes(b.getLoop()._block_list);
        }
    }
    vector<Block> ret;
    for (const Block &block: block_list) {
        if (not block.isInstr()) {
            Block b(block);
            if (collapse_loop_with_child(b.getLoop())) {
                ret.push_back(std::move(b));
            } else { // If it didn't succeeded, we just push the original block
                ret.push_back(block);
            }
        } else {
            ret.push_back(block);
        }
    }
}
} // jitk
} // bohrium

<commit_msg>jitk: transformers didn't update the block_list!<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

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

Bohrium 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 Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <jitk/transformer.hpp>

using namespace std;

namespace bohrium {
namespace jitk {

namespace {

// Help function that swap the two axes, 'axis1' and 'axis2', in all instructions in 'instr_list'
vector<InstrPtr> swap_axis(const vector<InstrPtr> &instr_list, int64_t axis1, int64_t axis2) {
    vector<InstrPtr> ret;
    for (const InstrPtr &instr: instr_list) {
        bh_instruction tmp(*instr);
        tmp.transpose(axis1, axis2);
        ret.push_back(std::make_shared<bh_instruction>(tmp));
    }
    return ret;
}

// Help function that swap the 'parent' block with its 'child' block.
// NB: 'child' must point to a block in 'parent._block_list'
vector<Block> swap_blocks(const LoopB &parent, const LoopB *child) {
    vector<Block> ret;
    for (const Block &b: parent._block_list) {
        LoopB loop;
        loop.rank = parent.rank;
        if (b.isInstr() or &b.getLoop() != child) {
            loop.size = parent.size;
            loop._block_list.push_back(b);
        } else {
            loop.size = child->size;
            const vector<InstrPtr> t = swap_axis(child->getAllInstr(), parent.rank, child->rank);
            loop._block_list.push_back(create_nested_block(t, child->rank, parent.size));
        }
        loop.metadata_update();
        ret.push_back(Block(std::move(loop)));
    }
    return ret;
}

// Help function that find a loop block within 'parent' that it make sense to swappable
const LoopB *find_swappable_sub_block(const LoopB &parent) {
    // For each sweep, we look for a sub-block that contains that sweep instructions.
    for (const InstrPtr sweep: parent._sweeps) {
        for (const Block &b: parent._block_list) {
            if (not b.isInstr()) {
                for (const Block &instr_block: b.getLoop()._block_list) {
                    if (instr_block.isInstr()) {
                        if (*instr_block.getInstr() == *sweep) {
                            return &b.getLoop();
                        }
                    }
                }
            }
        }
    }
    return NULL;
}

// Help function that collapses 'axis' and 'axis+1' in all instructions within 'loop'
// Returns false if encountering a non-compatible instruction
bool collapse_instr_axes(LoopB &loop, const int axis) {
    for (Block &block: loop._block_list) {
        if (block.isInstr()) {
            bh_instruction instr(*block.getInstr());
            const int sa = instr.sweep_axis();
            assert(sa != axis);
            assert(sa != axis+1);
            if (sa == axis or sa == axis+1) {
                return false;
            }
            for (size_t i=0; i<instr.operand.size(); ++i) {
                bh_view &view = instr.operand[i];
                if (not bh_is_constant(&view)) {
                    int _axis = axis;
                    if (i==0 and bh_opcode_is_reduction(instr.opcode)) {
                        _axis = sa < _axis ? _axis-1 : _axis;
                    }
                    assert(view.ndim > _axis+1);
                    if (view.shape[_axis+1] * view.stride[_axis+1] != view.stride[_axis]) {
                        return false;
                    }
                    view.shape[_axis] *= view.shape[_axis+1];
                    view.stride[_axis] = view.stride[_axis+1];
                }
            }
            instr.remove_axis(axis+1);
            block.setInstr(instr);
        } else {
            --block.getLoop().rank;
            if (not collapse_instr_axes(block.getLoop(), axis)) {
                return false;
            }
        }
    }
    loop.metadata_update();
    assert(loop.validation());
    return true;
}

// Help function that collapses 'loop' with its child if possible
bool collapse_loop_with_child(LoopB &loop) {
    // In order to be collapsable, 'loop' can only have one child, that child must be a loop, and both 'loop'
    // and the child cannot be sweeped
    if (loop._sweeps.empty() and loop._block_list.size() == 1 and loop._reshapable) {
        Block &child = loop._block_list[0];
        if ((not child.isInstr()) and child.getLoop()._sweeps.empty() and child.getLoop()._reshapable) {
            // Let's collapse with our single child
            loop.size *= loop._block_list[0].getLoop().size;
            // NB: we need the temporary step in order to avoid copying deleted data
            auto tmp = std::move(loop._block_list[0].getLoop()._block_list);
            loop._block_list = std::move(tmp);
            return collapse_instr_axes(loop, loop.rank);
        }
    }
    return false;
}
}

void push_reductions_inwards(vector<Block> &block_list) {
    vector<Block> block_list2(block_list);
    for(Block &b: block_list2) {
        if (not b.isInstr()) {
            push_reductions_inwards(b.getLoop()._block_list);
        }
    }
    vector<Block> ret;
    for(const Block &b: block_list2) {
        const LoopB *swappable;
        if (not b.isInstr() and (swappable = find_swappable_sub_block(b.getLoop())) != NULL)  {
            const vector<Block>tmp = swap_blocks(b.getLoop(), swappable);
            ret.insert(ret.end(), tmp.begin(), tmp.end());
        } else {
            ret.push_back(b);
        }
    }
    block_list = ret;
}

void split_for_threading(vector<Block> &block_list, uint64_t min_threading, uint64_t cur_threading) {
    vector<Block> ret;

    for (const Block &block: block_list) {
        // For now, we cannot make an instruction or a sweeped block threadable
        if (block.isInstr() or block.getLoop()._sweeps.size() > 0) {
            ret.push_back(block);
            continue;
        }
        const LoopB &loop = block.getLoop();
        uint64_t max_nelem = 0; // The maximum number of element in loop, which tells use the best-case scenario
        for (const InstrPtr instr: loop.getAllInstr()) {
            if (instr->operand.size() > 0) {
                const uint64_t nelem = static_cast<uint64_t>(bh_nelements(instr->operand[0]));
                if (nelem > max_nelem)
                    max_nelem = nelem;
            }
        }
        if (loop._block_list.size() > 1 // We need minimum two blocks (instructions) in order to split!
            and max_nelem > min_threading // Is it even possible to achieve our goal?
            and util_find_threaded_blocks(loop).second < min_threading-cur_threading) { // Is the goal already achieved?

            for (auto it = loop._block_list.begin(); it != loop._block_list.end(); ++it) {
                // First we will place all sub-blocks that cannot be threaded in a shared block
                {
                    LoopB newloop;
                    newloop.rank = loop.rank;
                    newloop.size = loop.size;
                    while (it != loop._block_list.end() and (it->isInstr() or it->getLoop()._sweeps.size() > 0)) {
                        assert(it->rank() == newloop.rank+1);
                        newloop._block_list.push_back(*it);
                        ++it;
                    }
                    if (not newloop._block_list.empty()) {
                        newloop.metadata_update();
                        ret.push_back(Block(std::move(newloop)));
                    }
                }
                // Then we place the highly threaded sub-block in its own block
                if (it != loop._block_list.end()) {
                    assert(not it->isInstr());
                    assert(it->getLoop()._sweeps.size() == 0);
                    LoopB newloop;
                    newloop.rank = loop.rank;
                    newloop.size = loop.size;
                    newloop._block_list.push_back(*it);
                    newloop.metadata_update();
                    ret.push_back(Block(std::move(newloop)));
                } else {
                    break;
                }
            }
        } else {
            ret.push_back(block);
        }
    }
    block_list = ret;
}

void collapse_redundant_axes(vector<Block> &block_list) {
    for(Block &b: block_list) {
        if (not b.isInstr()) {
            collapse_redundant_axes(b.getLoop()._block_list);
        }
    }
    vector<Block> ret;
    for (const Block &block: block_list) {
        if (not block.isInstr()) {
            Block b(block);
            if (collapse_loop_with_child(b.getLoop())) {
                ret.push_back(std::move(b));
            } else { // If it didn't succeeded, we just push the original block
                ret.push_back(block);
            }
        } else {
            ret.push_back(block);
        }
    }
    block_list = ret;
}
} // jitk
} // bohrium

<|endoftext|>


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

  Library: CppMicroServices

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "usUtils_p.h"

#include "usLog_p.h"
#include "usModuleInfo.h"
#include "usModuleSettings.h"

#include <string>
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <typeinfo>

#ifdef US_PLATFORM_POSIX
  #include <errno.h>
  #include <string.h>
  #include <dlfcn.h>
  #include <dirent.h>
#else
  #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
  #endif
  #include <windows.h>
  #include <crtdbg.h>
  #include "dirent_win32.h"
#endif

//-------------------------------------------------------------------
// Module auto-loading
//-------------------------------------------------------------------

namespace {
#if !defined(US_PLATFORM_LINUX)
std::string library_suffix()
{
#ifdef US_PLATFORM_WINDOWS
  return ".dll";
#elif defined(US_PLATFORM_APPLE)
  return ".dylib";
#else
  return ".so";
#endif
}
#endif

#ifdef US_PLATFORM_POSIX

const char DIR_SEP = '/';

bool load_impl(const std::string& modulePath)
{
  void* handle = dlopen(modulePath.c_str(), RTLD_NOW | RTLD_LOCAL);
  if (handle == NULL)
  {
    US_WARN << dlerror();
  }
  return (handle != NULL);
}

#elif defined(US_PLATFORM_WINDOWS)

const char DIR_SEP = '\\';

bool load_impl(const std::string& modulePath)
{
  void* handle = LoadLibrary(modulePath.c_str());
  if (handle == NULL)
  {
    US_WARN << us::GetLastErrorStr();
  }
  return (handle != NULL);
}

#else

  #ifdef US_ENABLE_AUTOLOADING_SUPPORT
    #error "Missing load_impl implementation for this platform."
  #else
bool load_impl(const std::string&) { return false; }
  #endif

#endif
}

US_BEGIN_NAMESPACE

std::vector<std::string> AutoLoadModulesFromPath(const std::string& absoluteBasePath, const std::string& subDir)
{
  std::vector<std::string> loadedModules;

  std::string loadPath = absoluteBasePath + DIR_SEP + subDir;

  DIR* dir = opendir(loadPath.c_str());
#ifdef CMAKE_INTDIR
  // Try intermediate output directories
  if (dir == NULL)
  {
    std::size_t indexOfLastSeparator = absoluteBasePath.find_last_of(DIR_SEP);
    if (indexOfLastSeparator != std::string::npos)
    {
      std::string intermediateDir = absoluteBasePath.substr(indexOfLastSeparator+1);
      bool equalSubDir = intermediateDir.size() == std::strlen(CMAKE_INTDIR);
      for (std::size_t i = 0; equalSubDir && i < intermediateDir.size(); ++i)
      {
        if (std::tolower(intermediateDir[i]) != std::tolower(CMAKE_INTDIR[i]))
        {
          equalSubDir = false;
        }
      }
      if (equalSubDir)
      {
        loadPath = absoluteBasePath.substr(0, indexOfLastSeparator+1) + subDir + DIR_SEP + CMAKE_INTDIR;
        dir = opendir(loadPath.c_str());
      }
    }
  }
#endif

  if (dir != NULL)
  {
    struct dirent *ent = NULL;
    while ((ent = readdir(dir)) != NULL)
    {
      bool loadFile = true;
#ifdef _DIRENT_HAVE_D_TYPE
      if (ent->d_type != DT_UNKNOWN && ent->d_type != DT_REG)
      {
        loadFile = false;
      }
#endif

      std::string entryFileName(ent->d_name);

      // On Linux, library file names can have version numbers appended. On other platforms, we
      // check the file ending. This could be refined for Linux in the future.
#if !defined(US_PLATFORM_LINUX)
      if (entryFileName.rfind(library_suffix()) != (entryFileName.size() - library_suffix().size()))
      {
        loadFile = false;
      }
#endif
      if (!loadFile) continue;

      std::string libPath = loadPath;
      if (!libPath.empty() && libPath.find_last_of(DIR_SEP) != libPath.size() -1)
      {
        libPath += DIR_SEP;
      }
      libPath += entryFileName;
      US_DEBUG << "Auto-loading module " << libPath;

      if (!load_impl(libPath))
      {
        US_WARN << "Auto-loading of module " << libPath << " failed.";
      }
      else
      {
        loadedModules.push_back(libPath);
      }
    }
    closedir(dir);
  }
  return loadedModules;
}

std::vector<std::string> AutoLoadModules(const ModuleInfo& moduleInfo)
{
  std::vector<std::string> loadedModules;

  if (moduleInfo.autoLoadDir.empty())
  {
    return loadedModules;
  }

  ModuleSettings::PathList autoLoadPaths = ModuleSettings::GetAutoLoadPaths();

  std::size_t indexOfLastSeparator = moduleInfo.location.find_last_of(DIR_SEP);
  std::string moduleBasePath = moduleInfo.location.substr(0, indexOfLastSeparator);

  for (ModuleSettings::PathList::iterator i = autoLoadPaths.begin();
       i != autoLoadPaths.end(); ++i)
  {
    if (*i == ModuleSettings::CURRENT_MODULE_PATH())
    {
      // Load all modules from a directory located relative to this modules location
      // and named after this modules library name.
      *i = moduleBasePath;
    }
  }

  // We could have introduced a duplicate above, so remove it.
  std::sort(autoLoadPaths.begin(), autoLoadPaths.end());
  autoLoadPaths.erase(std::unique(autoLoadPaths.begin(), autoLoadPaths.end()), autoLoadPaths.end());
  for (ModuleSettings::PathList::iterator i = autoLoadPaths.begin();
       i != autoLoadPaths.end(); ++i)
  {
    if (i->empty()) continue;
    std::vector<std::string> paths = AutoLoadModulesFromPath(*i, moduleInfo.autoLoadDir);
    loadedModules.insert(loadedModules.end(), paths.begin(), paths.end());
  }
  return loadedModules;
}

US_END_NAMESPACE

//-------------------------------------------------------------------
// Error handling
//-------------------------------------------------------------------

US_BEGIN_NAMESPACE

std::string GetLastErrorStr()
{
#ifdef US_PLATFORM_POSIX
  return std::string(strerror(errno));
#else
  // Retrieve the system error message for the last-error code
  LPVOID lpMsgBuf;
  DWORD dw = GetLastError();

  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    dw,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPTSTR) &lpMsgBuf,
    0, NULL );

  std::string errMsg((LPCTSTR)lpMsgBuf);

  LocalFree(lpMsgBuf);

  return errMsg;
#endif
}

static MsgHandler handler = 0;

MsgHandler installMsgHandler(MsgHandler h)
{
  MsgHandler old = handler;
  handler = h;
  return old;
}

void message_output(MsgType msgType, const char *buf)
{
  if (handler)
  {
    (*handler)(msgType, buf);
  }
  else
  {
    fprintf(stderr, "%s\n", buf);
    fflush(stderr);
  }

  if (msgType == ErrorMsg)
  {
  #if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
    // get the current report mode
    int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
    _CrtSetReportMode(_CRT_ERROR, reportMode);
    int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, CppMicroServices_VERSION_STR, buf);
    if (ret == 0  && reportMode & _CRTDBG_MODE_WNDW)
      return; // ignore
    else if (ret == 1)
      _CrtDbgBreak();
  #endif

  #ifdef US_PLATFORM_POSIX
    abort(); // trap; generates core dump
  #else
    exit(1); // goodbye cruel world
  #endif
  }
}

#ifdef US_HAVE_CXXABI_H
#include <cxxabi.h>
#endif

US_Core_EXPORT ::std::string GetDemangledName(const std::type_info& typeInfo)
{
  ::std::string result;
#ifdef US_HAVE_CXXABI_H
  int status = 0;
  char* demangled = abi::__cxa_demangle(typeInfo.name(), 0, 0, &status);
  if (demangled && status == 0)
  {
    result = demangled;
    free(demangled);
  }
#elif defined(US_PLATFORM_WINDOWS)
  const char* demangled = typeInfo.name();
  if (demangled != NULL)
  {
    result = demangled;
    // remove "struct" qualifiers
    std::size_t pos = 0;
    while (pos != std::string::npos)
    {
      if ((pos = result.find("struct ", pos)) != std::string::npos)
      {
        result = result.substr(0, pos) + result.substr(pos + 7);
        pos += 8;
      }
    }
    // remove "class" qualifiers
    pos = 0;
    while (pos != std::string::npos)
    {
      if ((pos = result.find("class ", pos)) != std::string::npos)
      {
        result = result.substr(0, pos) + result.substr(pos + 6);
        pos += 7;
      }
    }
  }
#else
  (void)typeInfo;
#endif
  return result;
}

US_END_NAMESPACE
<commit_msg>Fixed one more gcc MacOS namespace issue.<commit_after>/*=============================================================================

  Library: CppMicroServices

  Copyright (c) German Cancer Research Center,
    Division of Medical and Biological Informatics

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

#include "usUtils_p.h"

#include "usLog_p.h"
#include "usModuleInfo.h"
#include "usModuleSettings.h"

#include <string>
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <typeinfo>

#ifdef US_PLATFORM_POSIX
  #include <errno.h>
  #include <string.h>
  #include <dlfcn.h>
  #include <dirent.h>
#else
  #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
  #endif
  #include <windows.h>
  #include <crtdbg.h>
  #include "dirent_win32.h"
#endif

//-------------------------------------------------------------------
// Module auto-loading
//-------------------------------------------------------------------

namespace {
#if !defined(US_PLATFORM_LINUX)
std::string library_suffix()
{
#ifdef US_PLATFORM_WINDOWS
  return ".dll";
#elif defined(US_PLATFORM_APPLE)
  return ".dylib";
#else
  return ".so";
#endif
}
#endif

#ifdef US_PLATFORM_POSIX

const char DIR_SEP = '/';

bool load_impl(const std::string& modulePath)
{
  void* handle = dlopen(modulePath.c_str(), RTLD_NOW | RTLD_LOCAL);
  if (handle == NULL)
  {
    US_WARN << dlerror();
  }
  return (handle != NULL);
}

#elif defined(US_PLATFORM_WINDOWS)

const char DIR_SEP = '\\';

bool load_impl(const std::string& modulePath)
{
  void* handle = LoadLibrary(modulePath.c_str());
  if (handle == NULL)
  {
    US_WARN << us::GetLastErrorStr();
  }
  return (handle != NULL);
}

#else

  #ifdef US_ENABLE_AUTOLOADING_SUPPORT
    #error "Missing load_impl implementation for this platform."
  #else
bool load_impl(const std::string&) { return false; }
  #endif

#endif
}

US_BEGIN_NAMESPACE

std::vector<std::string> AutoLoadModulesFromPath(const std::string& absoluteBasePath, const std::string& subDir)
{
  std::vector<std::string> loadedModules;

  std::string loadPath = absoluteBasePath + DIR_SEP + subDir;

  DIR* dir = opendir(loadPath.c_str());
#ifdef CMAKE_INTDIR
  // Try intermediate output directories
  if (dir == NULL)
  {
    std::size_t indexOfLastSeparator = absoluteBasePath.find_last_of(DIR_SEP);
    if (indexOfLastSeparator != std::string::npos)
    {
      std::string intermediateDir = absoluteBasePath.substr(indexOfLastSeparator+1);
      bool equalSubDir = intermediateDir.size() == std::strlen(CMAKE_INTDIR);
      for (std::size_t i = 0; equalSubDir && i < intermediateDir.size(); ++i)
      {
        if (std::tolower(intermediateDir[i]) != std::tolower(CMAKE_INTDIR[i]))
        {
          equalSubDir = false;
        }
      }
      if (equalSubDir)
      {
        loadPath = absoluteBasePath.substr(0, indexOfLastSeparator+1) + subDir + DIR_SEP + CMAKE_INTDIR;
        dir = opendir(loadPath.c_str());
      }
    }
  }
#endif

  if (dir != NULL)
  {
    struct dirent *ent = NULL;
    while ((ent = readdir(dir)) != NULL)
    {
      bool loadFile = true;
#ifdef _DIRENT_HAVE_D_TYPE
      if (ent->d_type != DT_UNKNOWN && ent->d_type != DT_REG)
      {
        loadFile = false;
      }
#endif

      std::string entryFileName(ent->d_name);

      // On Linux, library file names can have version numbers appended. On other platforms, we
      // check the file ending. This could be refined for Linux in the future.
#if !defined(US_PLATFORM_LINUX)
      if (entryFileName.rfind(library_suffix()) != (entryFileName.size() - library_suffix().size()))
      {
        loadFile = false;
      }
#endif
      if (!loadFile) continue;

      std::string libPath = loadPath;
      if (!libPath.empty() && libPath.find_last_of(DIR_SEP) != libPath.size() -1)
      {
        libPath += DIR_SEP;
      }
      libPath += entryFileName;
      US_DEBUG << "Auto-loading module " << libPath;

      if (!load_impl(libPath))
      {
        US_WARN << "Auto-loading of module " << libPath << " failed.";
      }
      else
      {
        loadedModules.push_back(libPath);
      }
    }
    closedir(dir);
  }
  return loadedModules;
}

std::vector<std::string> AutoLoadModules(const ModuleInfo& moduleInfo)
{
  std::vector<std::string> loadedModules;

  if (moduleInfo.autoLoadDir.empty())
  {
    return loadedModules;
  }

  ModuleSettings::PathList autoLoadPaths = ModuleSettings::GetAutoLoadPaths();

  std::size_t indexOfLastSeparator = moduleInfo.location.find_last_of(DIR_SEP);
  std::string moduleBasePath = moduleInfo.location.substr(0, indexOfLastSeparator);

  for (ModuleSettings::PathList::iterator i = autoLoadPaths.begin();
       i != autoLoadPaths.end(); ++i)
  {
    if (*i == ModuleSettings::CURRENT_MODULE_PATH())
    {
      // Load all modules from a directory located relative to this modules location
      // and named after this modules library name.
      *i = moduleBasePath;
    }
  }

  // We could have introduced a duplicate above, so remove it.
  std::sort(autoLoadPaths.begin(), autoLoadPaths.end());
  autoLoadPaths.erase(std::unique(autoLoadPaths.begin(), autoLoadPaths.end()), autoLoadPaths.end());
  for (ModuleSettings::PathList::iterator i = autoLoadPaths.begin();
       i != autoLoadPaths.end(); ++i)
  {
    if (i->empty()) continue;
    std::vector<std::string> paths = AutoLoadModulesFromPath(*i, moduleInfo.autoLoadDir);
    loadedModules.insert(loadedModules.end(), paths.begin(), paths.end());
  }
  return loadedModules;
}

US_END_NAMESPACE

//-------------------------------------------------------------------
// Error handling
//-------------------------------------------------------------------

US_BEGIN_NAMESPACE

std::string GetLastErrorStr()
{
#ifdef US_PLATFORM_POSIX
  return std::string(strerror(errno));
#else
  // Retrieve the system error message for the last-error code
  LPVOID lpMsgBuf;
  DWORD dw = GetLastError();

  FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    dw,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPTSTR) &lpMsgBuf,
    0, NULL );

  std::string errMsg((LPCTSTR)lpMsgBuf);

  LocalFree(lpMsgBuf);

  return errMsg;
#endif
}

static MsgHandler handler = 0;

MsgHandler installMsgHandler(MsgHandler h)
{
  MsgHandler old = handler;
  handler = h;
  return old;
}

void message_output(MsgType msgType, const char *buf)
{
  if (handler)
  {
    (*handler)(msgType, buf);
  }
  else
  {
    fprintf(stderr, "%s\n", buf);
    fflush(stderr);
  }

  if (msgType == ErrorMsg)
  {
  #if defined(_MSC_VER) && !defined(NDEBUG) && defined(_DEBUG) && defined(_CRT_ERROR)
    // get the current report mode
    int reportMode = _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_WNDW);
    _CrtSetReportMode(_CRT_ERROR, reportMode);
    int ret = _CrtDbgReport(_CRT_ERROR, __FILE__, __LINE__, CppMicroServices_VERSION_STR, buf);
    if (ret == 0  && reportMode & _CRTDBG_MODE_WNDW)
      return; // ignore
    else if (ret == 1)
      _CrtDbgBreak();
  #endif

  #ifdef US_PLATFORM_POSIX
    abort(); // trap; generates core dump
  #else
    exit(1); // goodbye cruel world
  #endif
  }
}

#ifdef US_HAVE_CXXABI_H
#include <cxxabi.h>
#endif

US_Core_EXPORT ::std::string GetDemangledName(const ::std::type_info& typeInfo)
{
  ::std::string result;
#ifdef US_HAVE_CXXABI_H
  int status = 0;
  char* demangled = abi::__cxa_demangle(typeInfo.name(), 0, 0, &status);
  if (demangled && status == 0)
  {
    result = demangled;
    free(demangled);
  }
#elif defined(US_PLATFORM_WINDOWS)
  const char* demangled = typeInfo.name();
  if (demangled != NULL)
  {
    result = demangled;
    // remove "struct" qualifiers
    std::size_t pos = 0;
    while (pos != std::string::npos)
    {
      if ((pos = result.find("struct ", pos)) != std::string::npos)
      {
        result = result.substr(0, pos) + result.substr(pos + 7);
        pos += 8;
      }
    }
    // remove "class" qualifiers
    pos = 0;
    while (pos != std::string::npos)
    {
      if ((pos = result.find("class ", pos)) != std::string::npos)
      {
        result = result.substr(0, pos) + result.substr(pos + 6);
        pos += 7;
      }
    }
  }
#else
  (void)typeInfo;
#endif
  return result;
}

US_END_NAMESPACE
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->ErrorLabel->setText("No error :)");

    foreach(const QHostAddress &address, QNetworkInterface::allAddresses())
    {
        if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress(QHostAddress::LocalHost))
             MyIpAddr = address.toString();
    }
    ui->MyIP->setText("My ip: " + MyIpAddr);

    CaptureCamera.open(0);
    if(CaptureCamera.isOpened() == false)
    {
        ui->ErrorLabel->setText("Camera Error");
        std::cerr<< "Camera open error" <<std::endl;
    }

    CamSize = OriginalImageMat.size();
    Processer = new ImageProcesser(CamSize);
    ProcessTimer = new QTimer(this);
    connect(ProcessTimer, SIGNAL(timeout()), this, SLOT(processVideoAndUpdateQUI()));

    ProcessTimer->start(50);

    ///Add the graphics to graphicsview
    scene = new QGraphicsScene(0,0,Settings::SCREEN_WIDTH,Settings::SCREEN_HEIGHT,ui->graphicsView);
    ui->graphicsView->setScene(scene);
    myRoad = new Road();
    scene->addItem(myRoad);

    ///Start the game
    QObject::connect(&timer, SIGNAL(timeout()),scene, SLOT(advance()));
    timer.start(Settings::FREQUENCY);
    NetworkStarted =  false;
}

void MainWindow::processVideoAndUpdateQUI()
{
    CaptureCamera.read(OriginalImageMat);

    if (OriginalImageMat.empty()) return;

    if(CamSize.height == 0)
    {
        CamSize = OriginalImageMat.size();
        Processer->setCamSize(CamSize);
    }
    if(!NetworkStarted)
    {
        //QThread producerThread;
        //n.moveToThread(&producerThread);
        n = new Network();
        //MainWindow::connect(n, SIGNAL(Network::receivedImage(QImage)),SLOT(receiveNetworkImage(QImage)));
        QObject::connect(n, SIGNAL(receivedImage(QImage)), this, SLOT(receiveNetworkImage(QImage)));
        NetworkStarted = true;
    }

    //int move = Processer->getMove(OriginalImageMat);
    //std::cout << "move: " << move <<std::endl;
//240,150
    cv::resize(OriginalImageMat, ResizedImageMat, cv::Size(352,220), 0, 0, cv::INTER_CUBIC);
    cv::cvtColor(ResizedImageMat, ResizedImageMat, CV_BGR2RGB);
    cv::flip(ResizedImageMat, ResizedImageMat, 1);
    QImage OriginalImage((uchar*)ResizedImageMat.data,
                         ResizedImageMat.cols,
                         ResizedImageMat.rows,
                         ResizedImageMat.step,
                         QImage::Format_RGB888);
    QImage NetworkSendImage = OriginalImage;

    //QImage debug = QImage("debug/images/kep.png").scaledToHeight(150).scaledToHeight(240);

    n->sendData(NetworkSendImage);

    //NetworkGetImage = n->get_image();
//    cv::resize(NetworkGetImage,NetworkGetImage,cv::Size(400,250),0,0, cv::INTER_CUBIC);

    ///Move car
    //myRoad->moveCar(move);
}

///Public slot that receives the image from the networking thread
void MainWindow::receiveNetworkImage(QImage q)
{
    ui->NetworkCamVideo->setPixmap(QPixmap::fromImage(q));
}

MainWindow::~MainWindow()
{
    delete ui;
    delete ProcessTimer;
    delete Processer;
    delete n;
    delete scene;
    delete myCar;
    delete myRoad;
}

void MainWindow::closeVideoStream()
{
    ProcessTimer->stop();
    std::cout << "Video process timer stopped" <<std::endl;
    CaptureCamera.release();
    std::cout << "Camera released" <<std::endl;
}

// Kezeli a billentyűlenyomást
void MainWindow::keyPressEvent(QKeyEvent *event){
    switch (event->key())
    {
        case Qt::Key_Right:
                myRoad->moveCar(1); //turn right;
            break;
        case Qt::Key_Left:
                myRoad->moveCar(-1); //turn left;
            break;
        case Qt::Key_Escape:
            closeVideoStream();
            close();
            exit(0);
            break;
        default:
            break;
    }
}
<commit_msg>Resolved missing original image.<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->ErrorLabel->setText("No error :)");

    foreach(const QHostAddress &address, QNetworkInterface::allAddresses())
    {
        if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress(QHostAddress::LocalHost))
             MyIpAddr = address.toString();
    }
    ui->MyIP->setText("My ip: " + MyIpAddr);

    CaptureCamera.open(0);
    if(CaptureCamera.isOpened() == false)
    {
        ui->ErrorLabel->setText("Camera Error");
        std::cerr<< "Camera open error" <<std::endl;
    }

    CamSize = OriginalImageMat.size();
    Processer = new ImageProcesser(CamSize);
    ProcessTimer = new QTimer(this);
    connect(ProcessTimer, SIGNAL(timeout()), this, SLOT(processVideoAndUpdateQUI()));

    ProcessTimer->start(50);

    ///Add the graphics to graphicsview
    scene = new QGraphicsScene(0,0,Settings::SCREEN_WIDTH,Settings::SCREEN_HEIGHT,ui->graphicsView);
    ui->graphicsView->setScene(scene);
    myRoad = new Road();
    scene->addItem(myRoad);

    ///Start the game
    QObject::connect(&timer, SIGNAL(timeout()),scene, SLOT(advance()));
    timer.start(Settings::FREQUENCY);
    NetworkStarted =  false;
}

void MainWindow::processVideoAndUpdateQUI()
{
    CaptureCamera.read(OriginalImageMat);

    if (OriginalImageMat.empty()) return;

    if(CamSize.height == 0)
    {
        CamSize = OriginalImageMat.size();
        Processer->setCamSize(CamSize);
    }
    if(!NetworkStarted)
    {
        //QThread producerThread;
        //n.moveToThread(&producerThread);
        n = new Network();
        //MainWindow::connect(n, SIGNAL(Network::receivedImage(QImage)),SLOT(receiveNetworkImage(QImage)));
        QObject::connect(n, SIGNAL(receivedImage(QImage)), this, SLOT(receiveNetworkImage(QImage)));
        NetworkStarted = true;
    }

    //int move = Processer->getMove(OriginalImageMat);
    //std::cout << "move: " << move <<std::endl;
//240,150
    cv::resize(OriginalImageMat, ResizedImageMat, cv::Size(352,220), 0, 0, cv::INTER_CUBIC);
    cv::cvtColor(ResizedImageMat, ResizedImageMat, CV_BGR2RGB);
    cv::flip(ResizedImageMat, ResizedImageMat, 1);
    QImage OriginalImage((uchar*)ResizedImageMat.data,
                         ResizedImageMat.cols,
                         ResizedImageMat.rows,
                         ResizedImageMat.step,
                         QImage::Format_RGB888);
    QImage NetworkSendImage = OriginalImage;

    //QImage debug = QImage("debug/images/kep.png").scaledToHeight(150).scaledToHeight(240);
    ui->MyVideoLabel->setPixmap(QPixmap::fromImage(OriginalImage));

    n->sendData(NetworkSendImage);

    //NetworkGetImage = n->get_image();
//    cv::resize(NetworkGetImage,NetworkGetImage,cv::Size(400,250),0,0, cv::INTER_CUBIC);

    ///Move car
    //myRoad->moveCar(move);
}

///Public slot that receives the image from the networking thread
void MainWindow::receiveNetworkImage(QImage q)
{
    ui->NetworkCamVideo->setPixmap(QPixmap::fromImage(q));
}

MainWindow::~MainWindow()
{
    delete ui;
    delete ProcessTimer;
    delete Processer;
    delete n;
    delete scene;
    delete myCar;
    delete myRoad;
}

void MainWindow::closeVideoStream()
{
    ProcessTimer->stop();
    std::cout << "Video process timer stopped" <<std::endl;
    CaptureCamera.release();
    std::cout << "Camera released" <<std::endl;
}

// Kezeli a billentyűlenyomást
void MainWindow::keyPressEvent(QKeyEvent *event){
    switch (event->key())
    {
        case Qt::Key_Right:
                myRoad->moveCar(1); //turn right;
            break;
        case Qt::Key_Left:
                myRoad->moveCar(-1); //turn left;
            break;
        case Qt::Key_Escape:
            closeVideoStream();
            close();
            exit(0);
            break;
        default:
            break;
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fftw3.h>
#include <vector>
#include <stdio.h>
#include <math.h>

typedef unsigned char sample_res;
typedef unsigned char sample_res_unsigned;

fftw_complex *fft_in;
fftw_complex *fft_out;
fftw_complex *fft_result;
sample_res *fft_samples;
float *window;
double window_len;
double window_half;

void genSqr(sample_res *bfr,  const float &period, const sample_res_unsigned &amplitude, float &phase, const unsigned long &len)
{
    if(period == 0 || amplitude == 0)
        return;

    long offset = phase*period;

    //unsigned long lowlen = len - (len % long(period));

    //Offset the length and initial phase by the phase
    const long prd = period;
    unsigned long i;
    for(i = 0; i < len; i++)
        bfr[i] += ((((i+offset)%prd) < (period/2))-0.5f)*amplitude;
    phase = ((i+offset)%prd) / period;
}

void genNoise_White(sample_res *bfr, const float &period, const sample_res_unsigned &height, float &phase, const unsigned long &len)
{
    if(height == 0)
        return;
    int halfamp = height/2;
    //Note, not actually white noise, for the record
    for(unsigned long i = 0; i < len; i++)
        bfr[i] += (rand() % height) - halfamp;
}

fftw_complex *filter_lowpass(fftw_complex *in, unsigned int lowpass, const unsigned int &filter_len)
{
    //fftw_complex *out = (fftw_complex*)fftw_malloc ( sizeof ( fftw_complex ) * filter_len );
    fftw_complex *out = in;

    int righthalf=window_half+1;

    double flavor_lowpass = lowpass/window_half;
    flavor_lowpass*= flavor_lowpass;
    lowpass = flavor_lowpass*window_half;

    unsigned int minpass = std::min((unsigned int)(righthalf), lowpass);
    //OOOH. It never filters anything if minpass<2
    if(minpass < 2) //Yes 2
        minpass = 2;
    for(int i = 1; i < minpass; i++)
    {
        out[i][0] = 0;
        out[i][1] = 0;
    }

    return out;
}

fftw_complex *filter_highpass(fftw_complex *in, unsigned int highpass, const unsigned int &filter_len)
{
    fftw_complex *out = in;

    if(highpass > window_half)//Yes 2
        return out;

    //The higher end sounds nicer. So lets transform it by x=y^2, y=sqrt(x) [0,1]
    double flavor_highpass = highpass/window_half;
    flavor_highpass= std::sqrt(flavor_highpass);
    highpass = flavor_highpass*window_half;

    if(highpass < 2)//Yes 2
        highpass = 2;

    for(int i = highpass; i < window_half+1; i++)
    {
        out[i][0] = 0;
        out[i][1] = 0;
    }

    return out;
}

fftw_complex *filter_modulopass(fftw_complex *in, unsigned int mod, const unsigned int &filter_len)
{
    //fftw_complex *out = (fftw_complex*)fftw_malloc ( sizeof ( fftw_complex ) * filter_len );
    fftw_complex *out = in;
    if(mod == 0)
        mod = 1;

    for(int i = 1; i < window_half; i++)
    {
        if((i % mod) == 0)
        {
            out[i][0] = 0;
            out[i][1] = 0;
        }
    }

    return out;
}

fftw_complex *fourierTransform(sample_res *bfr, const unsigned int &len)
{
    //Copy sample data into input fft and window it with global window
    for(int i = 0; i < len; i++)
    {
        fft_in[i][0] = bfr[i]*window[i];
        fft_in[i][1] = 0.0;
    }

    fftw_plan plan_forward = fftw_plan_dft_1d (window_len, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE );
    fftw_execute ( plan_forward );
    fftw_destroy_plan( plan_forward );
    return fft_out;
}

sample_res *backFourierTransform(sample_res *buffer, const unsigned int &len)
{
    //double *out = (double*)fftw_malloc ( sizeof ( double ) * len);
    fftw_plan plan_backward = fftw_plan_dft_1d (window_len, fft_out, fft_result, FFTW_BACKWARD, FFTW_ESTIMATE );
    fftw_execute ( plan_backward );

    fftw_destroy_plan( plan_backward);
    for(int i = 0; i < len; i++)
    {
        //std::cerr << fft_result[i][0]/window_len << '\n';
        //buffer[i] = out[i]/len_dbl;
        buffer[i] = ((fft_result[i][0]/window_len)/window[i]);
    }
    return buffer;

}

void play(sample_res *buffer, unsigned int bytes)
{
    //Output all of the data from one byte buffer to stdout
    for(unsigned int i = 0; i < bytes; i++)
    {
        //TODO will need to be revised if sample_res ever changes
        if(sizeof(sample_res) ==1)
            putchar(buffer[i]);
        else if(sizeof(sample_res) == 2)
        {
            putchar((char)(buffer[i]&0xFF));
            putchar((char)((buffer[i]&0xFF00) >> 8));
        }
    }
}

// Create a hamming window of windowLength samples in buffer
void hamming() {

    for(int i = 0; i < window_len; i++) {

        window[i] = 0.54 - (0.46 * std::cos( 2 * M_PI * (i / ((window_len - 1) * 1.0))));
    }
}

unsigned int chooseWindowLength(unsigned int a)
{
    unsigned int i = 1;
    while ((i<<=1)<=a);
    if (i < 2048)
        i=2048;
    return i;
}

int main()
{
    int seconds = 8;
    int bytes = seconds*44100;
    int subdivisions = (bytes)/0x1CB0;
    int bytespersub = bytes/subdivisions;

    window_len = chooseWindowLength(bytespersub);
    window_half = window_len/2;
    fft_in = (fftw_complex *)fftw_malloc ( sizeof ( fftw_complex ) * window_len );
    fft_out = (fftw_complex *)fftw_malloc ( sizeof ( fftw_complex ) * window_len );
    fft_result = (fftw_complex *)fftw_malloc ( sizeof ( fftw_complex ) * window_len );
    fft_samples = new sample_res[bytespersub];
    window = new float[(long)window_len];
    //std::cerr << "ALLOCATED\n";
    for(int i = bytespersub; i < window_len; i++)
    {
        fft_in[i][0] = 0.0;
        fft_in[i][1] = 0.0;
    }
    //std::cerr << "INITIALIZED fft_in\n";
    hamming();
    //std::cerr << "HAMMED\n";

    //How many more of the available frequencies are we removing at each iteration:
    float filterstep = (1.25f/subdivisions)*(window_half);
    //float filterstep = 90;

    sample_res bfr[bytes];
    float phase = 0;
    for(int i = 0 ; i < bytes; i++)
        bfr[i] = 128;
    //genNoise_White(bfr, 256, 255, phase, bytes);
    genSqr(bfr, 256, 250, phase, bytes);

    //std::cerr << "GENERATED\n";

    for(int i = 0; i < subdivisions; i++)
    {
        int lstbfr = (i)*bytespersub;
        std::cerr << "Iteration " << i+1 << '/' << subdivisions << " filter=" << std::sqrt((filterstep*i)/window_half) << '\n';

        fourierTransform(bfr+lstbfr, bytespersub);
        filter_highpass(fft_out, filterstep*(i), bytespersub);
        backFourierTransform(bfr+lstbfr, bytespersub);
    }

    fftw_free(fft_in);
    fftw_free(fft_out);
    delete [] fft_result;
    delete [] window;

    play(bfr, bytes);
    return 0;
}

<commit_msg>Get Low pass filtering to work<commit_after>#include <iostream>
#include <fftw3.h>
#include <vector>
#include <stdio.h>
#include <math.h>

typedef unsigned char sample_res;
typedef unsigned char sample_res_unsigned;

fftw_complex *fft_in;
fftw_complex *fft_out;
fftw_complex *fft_result;
sample_res *fft_samples;
float *window;
double window_len;
double window_half;

void genSqr(sample_res *bfr,  const float &period, const sample_res_unsigned &amplitude, float &phase, const unsigned long &len)
{
    if(period == 0 || amplitude == 0)
        return;

    long offset = phase*period;

    //unsigned long lowlen = len - (len % long(period));

    //Offset the length and initial phase by the phase
    const long prd = period;
    unsigned long i;
    for(i = 0; i < len; i++)
        bfr[i] += ((((i+offset)%prd) < (period/2))-0.5f)*amplitude;
    phase = ((i+offset)%prd) / period;
}

void genNoise_White(sample_res *bfr, const float &period, const sample_res_unsigned &height, float &phase, const unsigned long &len)
{
    if(height == 0)
        return;
    int halfamp = height/2;
    //Note, not actually white noise, for the record
    for(unsigned long i = 0; i < len; i++)
        bfr[i] += (rand() % height) - halfamp;
}

fftw_complex *filter_lowpass(fftw_complex *in, unsigned int lowpass, const unsigned int &filter_len)
{
    //fftw_complex *out = (fftw_complex*)fftw_malloc ( sizeof ( fftw_complex ) * filter_len );
    fftw_complex *out = in;

    int righthalf=window_half+1;

    double flavor_lowpass = lowpass/window_half;
    flavor_lowpass*= flavor_lowpass;
    lowpass = flavor_lowpass*window_half;

    unsigned int minpass = std::min((unsigned int)(righthalf), lowpass);
    if(minpass < 1)
        minpass = 1;
    for(int i = 0; i < minpass; i++)
    {
        out[i][0] = 0;
        out[i][1] = 0;
    }

    return out;
}

fftw_complex *filter_highpass(fftw_complex *in, unsigned int highpass, const unsigned int &filter_len)
{
    fftw_complex *out = in;

    if(highpass > window_half)//Yes 2
        return out;

    //The higher end sounds nicer. So lets transform it by x=y^2, y=sqrt(x) [0,1]
    double flavor_highpass = highpass/window_len;
    flavor_highpass= std::sqrt(flavor_highpass);
    highpass = flavor_highpass*window_len;

    for(int i = highpass; i < window_len; i++)
    {
        out[i][0] = 0;
        out[i][1] = 0;
    }

    return out;
}
fftw_complex *fourierTransform(sample_res *bfr, const unsigned int &len)
{
    //Copy sample data into input fft and window it with global window
    for(int i = 0; i < len; i++)
    {
        fft_in[i][0] = bfr[i]*window[i];
        fft_in[i][1] = 0.0;
    }

    fftw_plan plan_forward = fftw_plan_dft_1d (window_len, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE );
    fftw_execute ( plan_forward );
    fftw_destroy_plan( plan_forward );
    return fft_out;
}

sample_res *backFourierTransform(sample_res *buffer, const unsigned int &len)
{
    //double *out = (double*)fftw_malloc ( sizeof ( double ) * len);
    fftw_plan plan_backward = fftw_plan_dft_1d (window_len, fft_out, fft_result, FFTW_BACKWARD, FFTW_ESTIMATE );
    fftw_execute ( plan_backward );

    fftw_destroy_plan( plan_backward);
    for(int i = 0; i < len; i++)
    {
        double result = (fft_result[i][0]/window_len)/window[i];
        if(result > 255 || result < 0)
            std::cerr << result << '\n';
        //buffer[i] = out[i]/len_dbl;
        buffer[i] = result;
    }
    return buffer;

}

void play(sample_res *buffer, unsigned int bytes)
{
    //Output all of the data from one byte buffer to stdout
    for(unsigned int i = 0; i < bytes; i++)
    {
        //TODO will need to be revised if sample_res ever changes
        if(sizeof(sample_res) ==1)
            putchar(buffer[i]);
        else if(sizeof(sample_res) == 2)
        {
            putchar((char)(buffer[i]&0xFF));
            putchar((char)((buffer[i]&0xFF00) >> 8));
        }
    }
}

// Create a hamming window of windowLength samples in buffer
void hamming() {

    for(int i = 0; i < window_len; i++) {

        window[i] = 0.54 - (0.46 * std::cos( 2 * M_PI * (i / ((window_len - 1) * 1.0))));
    }
}

unsigned int chooseWindowLength(unsigned int a)
{
    unsigned int i = 1;
    while ((i<<=1)<=a);
    if (i < 2048)
        i=2048;
    return i;
}

int main()
{
    //Play at a rate of 44100
    //GOAL: Filter chunks of signal by different filter values at each subdivision
    int seconds = 8;
    int bytes = seconds*44100;
    int subdivisions = (bytes)/0x1CB0;
    int bytespersub = bytes/subdivisions; //Bytes in a subdivision

    window_len = chooseWindowLength(bytespersub);
    window_half = window_len/2;
    fft_in = (fftw_complex *)fftw_malloc ( sizeof ( fftw_complex ) * window_len );
    fft_out = (fftw_complex *)fftw_malloc ( sizeof ( fftw_complex ) * window_len );
    fft_result = (fftw_complex *)fftw_malloc ( sizeof ( fftw_complex ) * window_len );
    fft_samples = new sample_res[bytespersub];
    window = new float[(long)window_len];
    //std::cerr << "ALLOCATED\n";

    //Zero out the section of the input fft that will never ve written by a subdivision to 0
    //(The subdivisions are ALL the same size, even the final one)
    for(int i = bytespersub; i < window_len; i++)
    {
        fft_in[i][0] = 0.0;
        fft_in[i][1] = 0.0;
    }
    hamming();
    //std::cerr << "COOKED UP A HAM FOR LATER USE\n";

    //How many more of the available frequencies are we removing at each iteration:
    float filterstep = (1.25f/subdivisions)*(window_half);

    sample_res bfr[bytes];
    for(int i = 0 ; i < bytes; i++)
        bfr[i] = 128;

    //Generate a waveform in a `bytes` long sample_res buffer
    //genNoise_White(bfr, 256, 255, phase, bytes);
    float phase = 0;
    genSqr(bfr, 256, 100, phase, bytes);

    //std::cerr << "GENERATED\n";

    //Loop through each subdivision cutting out the appropriate bytes
    //  Create a fourierTransform which populates fft_in and forward transforms it into fft_out
    //  Filter the fourier transform by zeroing terms
    //  Convert transform back into sample_res buffer
    for(int i = 0; i < subdivisions; i++)
    {
        int lstbfr = (i)*bytespersub;
        std::cerr << "Iteration " << i+1 << '/' << subdivisions << " filter=" << std::sqrt((filterstep*i)/window_half) << '\n';

        fourierTransform(bfr+lstbfr, bytespersub);
        filter_lowpass(fft_out, filterstep*(i), bytespersub);
        backFourierTransform(bfr+lstbfr, bytespersub);
    }

    //Free memory and play filterred buffer
    fftw_free(fft_in);
    fftw_free(fft_out);
    delete [] fft_result;
    delete [] window;

    play(bfr, bytes);
    return 0;
}

fftw_complex *filter_modulopass(fftw_complex *in, unsigned int mod, const unsigned int &filter_len)
{
    //fftw_complex *out = (fftw_complex*)fftw_malloc ( sizeof ( fftw_complex ) * filter_len );
    fftw_complex *out = in;
    if(mod == 0)
        mod = 1;

    for(int i = 1; i < window_half; i++)
    {
        if((i % mod) == 0)
        {
            out[i][0] = 0;
            out[i][1] = 0;
        }
    }

    return out;
}

<|endoftext|>