<commit_before>/**
* @file TeamMessageStatistics.cpp
*/

#include "TeamMessageStatistics.h"

TeamMessageStatistics::TeamMessageStatistics()
{
  getDebugParameterList().add(&parameters);
}

TeamMessageStatistics::~TeamMessageStatistics()
{
  getDebugParameterList().remove(&parameters);
}

void TeamMessageStatistics::execute() {
  //Check, from which robots we have received a message, and update the corresponding statistics
  for (std::map<unsigned int, TeamMessage::Data>::const_iterator i = getTeamMessage().data.begin(); i != getTeamMessage().data.end(); ++i) {
    unsigned int robotNumber = i->first;
    unsigned int receiveTime = getFrameInfo().getTime();
    unsigned int receiveTime_sender = i->second.frameInfo.getTime();
    std::map<unsigned int, RobotMessageStatistics*>::const_iterator r = robotMap.find(robotNumber);
    if (r != robotMap.end()) {
      if ((*r->second).lastMessageReceived_sender < receiveTime_sender) {
        double currentMessageInterval = receiveTime - (*r->second).lastMessageReceived;

        //Update statistics for the corresponding robot
        (*r->second).messageReceived(receiveTime);
        (*r->second).lastMessageReceived_sender = receiveTime_sender;
        getTeamMessageStatisticsModel().amountsOfMessages[robotNumber] = (*r->second).amountOfMessages;
        getTeamMessageStatisticsModel().averages[robotNumber] = (*r->second).avgMsgInterval;
        getTeamMessageStatisticsModel().variances[robotNumber] = (*r->second).varianceMsgInterval;
        PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(robotNumber)+std::string("):MessageInterval"), currentMessageInterval);

        //Update statistics for the whole team
        if (robotNumber == getPlayerInfo().gameData.playerNumber) {
          continue; //Don't consider our own messages
        }
        double old_amountOfMessages = getTeamMessageStatisticsModel().amountOfMessages++;
        if (parameters.interpolation == 0.0 || old_amountOfMessages == 0 || 1.0/getTeamMessageStatisticsModel().amountOfMessages > parameters.interpolation) {
          //No interpolation, compute unweighted average
          getTeamMessageStatisticsModel().avgMsgInterval = (getTeamMessageStatisticsModel().avgMsgInterval * old_amountOfMessages + currentMessageInterval)
            /getTeamMessageStatisticsModel().amountOfMessages;
          getTeamMessageStatisticsModel().expectation_xSquared = (getTeamMessageStatisticsModel().expectation_xSquared * old_amountOfMessages +
            std::pow(currentMessageInterval, 2))/getTeamMessageStatisticsModel().amountOfMessages;
          getTeamMessageStatisticsModel().varianceMsgInterval = getTeamMessageStatisticsModel().expectation_xSquared -
            std::pow(getTeamMessageStatisticsModel().avgMsgInterval, 2);
        }
        else {
          //Interpolation of message intervals
          getTeamMessageStatisticsModel().avgMsgInterval = parameters.interpolation * currentMessageInterval +
            (1.0 - parameters.interpolation) * getTeamMessageStatisticsModel().avgMsgInterval;
          getTeamMessageStatisticsModel().expectation_xSquared = parameters.interpolation * std::pow(currentMessageInterval, 2) +
            (1.0 - parameters.interpolation) * getTeamMessageStatisticsModel().expectation_xSquared;
          getTeamMessageStatisticsModel().varianceMsgInterval = getTeamMessageStatisticsModel().expectation_xSquared -
            std::pow(getTeamMessageStatisticsModel().avgMsgInterval, 2);
        }
        PLOT("MessageStatistics:Team:MessageInterval", currentMessageInterval);
      }
    }
    //If we haven't received a message from this robot before; add it to the map
    else {
      RobotMessageStatistics* rms = new RobotMessageStatistics(robotNumber);
      rms->messageReceived(receiveTime);
      rms->lastMessageReceived_sender = receiveTime_sender;
      robotMap.insert(std::make_pair(robotNumber, rms));
    }
  }
  PLOT("MessageStatistics:Team:stddevMessageInterval", std::sqrt(getTeamMessageStatisticsModel().varianceMsgInterval));
  PLOT("MessageStatistics:Team:averageMessageInterval", getTeamMessageStatisticsModel().avgMsgInterval);

  //Run the update procedure (incremental computation of probability of failure) for each robot
  unsigned int currentTime = getFrameInfo().getTime();
  for (std::map<unsigned int, RobotMessageStatistics*>::const_iterator rms = robotMap.begin(); rms != robotMap.end(); rms++) {
    (*rms->second).update(currentTime);
    getTeamMessageStatisticsModel().failureProbabilities.insert(std::make_pair(rms->first, (*rms->second).probability_messageReceived_upToNow));
    PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(rms->first)+std::string("):averageMessageInterval"), (*rms->second).avgMsgInterval);
    PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(rms->first)+std::string("):stddevMesssageInterval"), std::sqrt((*rms->second).varianceMsgInterval));
    PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(rms->first)+std::string("):probability"), 1.0-(*rms->second).probability_messageReceived_upToNow);
  }
}

void TeamMessageStatistics::reset() {
  getTeamMessageStatisticsModel().amountOfMessages = 0;
  getTeamMessageStatisticsModel().avgMsgInterval = 0.0;
  getTeamMessageStatisticsModel().varianceMsgInterval = 0.0;
  getTeamMessageStatisticsModel().expectation_xSquared = 0.0;

  robotMap.clear();
}

double TeamMessageStatistics::probability(double lower, double upper) {
  if (upper <= 0.0) {
    return 0.0;
  }
  double probability = riemann_integral(&TeamMessageStatistics::normalDensity, lower, upper, 1);

  return probability;
}

double TeamMessageStatistics::exponentialDistribution(double x) {
  return 1.0 - std::exp(-getTeamMessageStatisticsModel().avgMsgInterval * x);
}

/**
** Computes the Riemann Integral of some function for the given interval [a, b] and an amount of rectangles.
**/
double TeamMessageStatistics::riemann_integral(double (TeamMessageStatistics::*func)(double), double a, double b, int amountOfRectangles) {

	double *arguments = new double[amountOfRectangles];
	for (int i = 1; i <= amountOfRectangles; i++) {
		arguments[i-1] = a + i * (b - a)/amountOfRectangles;
	}

  double sum = 0.0;
	double x = a;
	for (int index = 0; index < amountOfRectangles; index++) {
		double newX = arguments[index];
		double value = (this->*func)((x+newX)/2.0);
		double area = value * (newX-x);
		sum += area;
		x = newX;
	}

	return sum;

}<commit_msg>Summarised two lines into one.<commit_after>/**
* @file TeamMessageStatistics.cpp
*/

#include "TeamMessageStatistics.h"

TeamMessageStatistics::TeamMessageStatistics()
{
  getDebugParameterList().add(&parameters);
}

TeamMessageStatistics::~TeamMessageStatistics()
{
  getDebugParameterList().remove(&parameters);
}

void TeamMessageStatistics::execute() {
  //Check, from which robots we have received a message, and update the corresponding statistics
  for (std::map<unsigned int, TeamMessage::Data>::const_iterator i = getTeamMessage().data.begin(); i != getTeamMessage().data.end(); ++i) {
    unsigned int robotNumber = i->first;
    unsigned int receiveTime = getFrameInfo().getTime();
    unsigned int receiveTime_sender = i->second.frameInfo.getTime();
    std::map<unsigned int, RobotMessageStatistics*>::const_iterator r = robotMap.find(robotNumber);
    if (r != robotMap.end()) {
      if ((*r->second).lastMessageReceived_sender < receiveTime_sender) {
        double currentMessageInterval = receiveTime - (*r->second).lastMessageReceived;

        //Update statistics for the corresponding robot
        (*r->second).messageReceived(receiveTime);
        (*r->second).lastMessageReceived_sender = receiveTime_sender;
        getTeamMessageStatisticsModel().amountsOfMessages[robotNumber] = (*r->second).amountOfMessages;
        getTeamMessageStatisticsModel().averages[robotNumber] = (*r->second).avgMsgInterval;
        getTeamMessageStatisticsModel().variances[robotNumber] = (*r->second).varianceMsgInterval;
        PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(robotNumber)+std::string("):MessageInterval"), currentMessageInterval);

        //Update statistics for the whole team
        if (robotNumber == getPlayerInfo().gameData.playerNumber) {
          continue; //Don't consider our own messages
        }
        double old_amountOfMessages = getTeamMessageStatisticsModel().amountOfMessages++;
        if (parameters.interpolation == 0.0 || old_amountOfMessages == 0 || 1.0/getTeamMessageStatisticsModel().amountOfMessages > parameters.interpolation) {
          //No interpolation, compute unweighted average
          getTeamMessageStatisticsModel().avgMsgInterval = (getTeamMessageStatisticsModel().avgMsgInterval * old_amountOfMessages + currentMessageInterval)
            /getTeamMessageStatisticsModel().amountOfMessages;
          getTeamMessageStatisticsModel().expectation_xSquared = (getTeamMessageStatisticsModel().expectation_xSquared * old_amountOfMessages +
            std::pow(currentMessageInterval, 2))/getTeamMessageStatisticsModel().amountOfMessages;
        }
        else {
          //Interpolation of message intervals
          getTeamMessageStatisticsModel().avgMsgInterval = parameters.interpolation * currentMessageInterval +
            (1.0 - parameters.interpolation) * getTeamMessageStatisticsModel().avgMsgInterval;
          getTeamMessageStatisticsModel().expectation_xSquared = parameters.interpolation * std::pow(currentMessageInterval, 2) +
            (1.0 - parameters.interpolation) * getTeamMessageStatisticsModel().expectation_xSquared;
        }
        getTeamMessageStatisticsModel().varianceMsgInterval = getTeamMessageStatisticsModel().expectation_xSquared -
          std::pow(getTeamMessageStatisticsModel().avgMsgInterval, 2);
        PLOT("MessageStatistics:Team:MessageInterval", currentMessageInterval);
      }
    }
    //If we haven't received a message from this robot before; add it to the map
    else {
      RobotMessageStatistics* rms = new RobotMessageStatistics(robotNumber);
      rms->messageReceived(receiveTime);
      rms->lastMessageReceived_sender = receiveTime_sender;
      robotMap.insert(std::make_pair(robotNumber, rms));
    }
  }
  PLOT("MessageStatistics:Team:stddevMessageInterval", std::sqrt(getTeamMessageStatisticsModel().varianceMsgInterval));
  PLOT("MessageStatistics:Team:averageMessageInterval", getTeamMessageStatisticsModel().avgMsgInterval);

  //Run the update procedure (incremental computation of probability of failure) for each robot
  unsigned int currentTime = getFrameInfo().getTime();
  for (std::map<unsigned int, RobotMessageStatistics*>::const_iterator rms = robotMap.begin(); rms != robotMap.end(); rms++) {
    (*rms->second).update(currentTime);
    getTeamMessageStatisticsModel().failureProbabilities.insert(std::make_pair(rms->first, (*rms->second).probability_messageReceived_upToNow));
    PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(rms->first)+std::string("):averageMessageInterval"), (*rms->second).avgMsgInterval);
    PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(rms->first)+std::string("):stddevMesssageInterval"), std::sqrt((*rms->second).varianceMsgInterval));
    PLOT(std::string("MessageStatistics:Robot(")+DataConversion::toStr(rms->first)+std::string("):probability"), 1.0-(*rms->second).probability_messageReceived_upToNow);
  }
}

void TeamMessageStatistics::reset() {
  getTeamMessageStatisticsModel().amountOfMessages = 0;
  getTeamMessageStatisticsModel().avgMsgInterval = 0.0;
  getTeamMessageStatisticsModel().varianceMsgInterval = 0.0;
  getTeamMessageStatisticsModel().expectation_xSquared = 0.0;

  robotMap.clear();
}

double TeamMessageStatistics::probability(double lower, double upper) {
  if (upper <= 0.0) {
    return 0.0;
  }
  double probability = riemann_integral(&TeamMessageStatistics::normalDensity, lower, upper, 1);

  return probability;
}

double TeamMessageStatistics::exponentialDistribution(double x) {
  return 1.0 - std::exp(-getTeamMessageStatisticsModel().avgMsgInterval * x);
}

/**
** Computes the Riemann Integral of some function for the given interval [a, b] and an amount of rectangles.
**/
double TeamMessageStatistics::riemann_integral(double (TeamMessageStatistics::*func)(double), double a, double b, int amountOfRectangles) {

	double *arguments = new double[amountOfRectangles];
	for (int i = 1; i <= amountOfRectangles; i++) {
		arguments[i-1] = a + i * (b - a)/amountOfRectangles;
	}

  double sum = 0.0;
	double x = a;
	for (int index = 0; index < amountOfRectangles; index++) {
		double newX = arguments[index];
		double value = (this->*func)((x+newX)/2.0);
		double area = value * (newX-x);
		sum += area;
		x = newX;
	}

	return sum;

}<|endoftext|>


<commit_before>// $Id$

AliAnalysisTaskScale* AddTaskScale(
  const char *nTracks        = "Tracks",
  const char *nClusters      = "CaloClustersCorr",
  Double_t    trackptcut     = 0.150,
  Double_t    clusptcut      = 0.150,
  const char *taskname       = "Scale",
  const char *outfilename    = "AnalysisResults.root"
)
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
  {
    ::Error("AddTaskScale", "No analysis manager to connect to.");
    return NULL;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
  {
    ::Error("AddTaskScale", "This task requires an input event handler");
    return NULL;
  }

  //-------------------------------------------------------
  // Init the task and do settings
  //-------------------------------------------------------

  TString name(Form("%s_%s_%s_%d_%d", taskname, nTracks, nClusters, TMath::FloorNint(trackptcut*1000), TMath::FloorNint(clusptcut*1000)));
  AliAnalysisTaskScale *scaletask = new AliAnalysisTaskScale(name);
  AliParticleContainer *pcont = scaletask->AddParticleContainer(nTracks);
  if(pcont) {
    pcont->SetParticlePtCut(trackptcut);
    pcont->SetParticleEtaLimits(-0.7,0.7); // only accept tracks in the EMCal eta range
  }
  AliClusterContainer  *ccont = scaletask->AddClusterContainer(nClusters);
  if(ccont) ccont->SetClusterPtCut(clusptcut);

  //-------------------------------------------------------
  // Final settings, pass to manager and set the containers
  //-------------------------------------------------------

  mgr->AddTask(scaletask);

  // Create containers for input/output
  TString contname(name);
  contname += "_Histos";
  mgr->ConnectInput (scaletask, 0, mgr->GetCommonInputContainer() );
  AliAnalysisDataContainer *coscale = mgr->CreateContainer(contname,
                                                           TList::Class(),
                                                           AliAnalysisManager::kOutputContainer,
                                                           outfilename);
  mgr->ConnectOutput(scaletask,1,coscale);

  return scaletask;
}
<commit_msg>Fix typo<commit_after>// $Id$

AliAnalysisTaskScale* AddTaskScale(
  const char *nTracks        = "Tracks",
  const char *nClusters      = "CaloClustersCorr",
  Double_t    trackptcut     = 0.150,
  Double_t    clusptcut      = 0.150,
  const char *taskname       = "Scale",
  const char *outfilename    = "AnalysisResults.root"
)
{
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr)
  {
    ::Error("AddTaskScale", "No analysis manager to connect to.");
    return NULL;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  //==============================================================================
  if (!mgr->GetInputEventHandler())
  {
    ::Error("AddTaskScale", "This task requires an input event handler");
    return NULL;
  }

  //-------------------------------------------------------
  // Init the task and do settings
  //-------------------------------------------------------

  TString name(Form("%s_%s_%s_%d_%d", taskname, nTracks, nClusters, TMath::FloorNint(trackptcut*1000), TMath::FloorNint(clusptcut*1000)));
  AliAnalysisTaskScale *scaletask = new AliAnalysisTaskScale(name);
  AliParticleContainer *pcont = scaletask->AddParticleContainer(nTracks);
  if(pcont) {
    pcont->SetParticlePtCut(trackptcut);
    pcont->SetParticleEtaLimits(-0.7,0.7); // only accept tracks in the EMCal eta range
  }
  AliClusterContainer  *ccont = scaletask->AddClusterContainer(nClusters);
  if(ccont) ccont->SetClusPtCut(clusptcut);

  //-------------------------------------------------------
  // Final settings, pass to manager and set the containers
  //-------------------------------------------------------

  mgr->AddTask(scaletask);

  // Create containers for input/output
  TString contname(name);
  contname += "_Histos";
  mgr->ConnectInput (scaletask, 0, mgr->GetCommonInputContainer() );
  AliAnalysisDataContainer *coscale = mgr->CreateContainer(contname,
                                                           TList::Class(),
                                                           AliAnalysisManager::kOutputContainer,
                                                           outfilename);
  mgr->ConnectOutput(scaletask,1,coscale);

  return scaletask;
}
<|endoftext|>


<commit_before>/**
 * \ file InPointerFilter.cpp
 */

#include <cmath>

#include <boost/math/constants/constants.hpp>

#include <ATK/Core/InPointerFilter.h>
#include <ATK/Core/OutPointerFilter.h>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

#include <boost/scoped_array.hpp>

#define PROCESSSIZE (10)

BOOST_AUTO_TEST_CASE( OutPointerFloat_sin1k_test )
{
  boost::scoped_array<float> data(new float[PROCESSSIZE]);
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<float> generator(data.get(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<float> outdata(new float[PROCESSSIZE]);

  ATK::OutPointerFilter<float> output(outdata.get(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}

BOOST_AUTO_TEST_CASE( OutPointerDouble_sin1k_test )
{
  boost::scoped_array<double> data(new double[PROCESSSIZE]);
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<double> generator(data.get(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<double> outdata(new double[PROCESSSIZE]);

  ATK::OutPointerFilter<double> output(outdata.get(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}

BOOST_AUTO_TEST_CASE( OutPointerFloat_sin1k2k_interleaved_test )
{
  boost::scoped_array<float> data(new float[2*PROCESSSIZE]);
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[2*i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
    data[2*i+1] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 2000);
  }

  ATK::InPointerFilter<float> generator(data.get(), PROCESSSIZE, 2, true);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<double> outdata(new double[2*PROCESSSIZE]);

  ATK::OutPointerFilter<double> output(outdata.get(), PROCESSSIZE, 2, true);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);
  output.set_input_port(1, &generator, 1);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < 2*PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}

BOOST_AUTO_TEST_CASE( OutPointerFloat_sin1k2k_noninterleaved_test )
{
  boost::scoped_array<float> data(new float[2*PROCESSSIZE]);
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i+PROCESSSIZE] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 2000);
  }

  ATK::InPointerFilter<float> generator(data.get(), 2, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  boost::scoped_array<double> outdata(new double[2*PROCESSSIZE]);

  ATK::OutPointerFilter<double> output(outdata.get(), 2, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);
  output.set_input_port(1, &generator, 1);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < 2*PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}
<commit_msg>Adding out of bounds checks<commit_after>/**
 * \ file InPointerFilter.cpp
 */

#include <cmath>

#include <boost/math/constants/constants.hpp>

#include <ATK/Core/InPointerFilter.h>
#include <ATK/Core/OutPointerFilter.h>

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

#include <boost/scoped_array.hpp>

#define PROCESSSIZE (10)

BOOST_AUTO_TEST_CASE( OutPointerFloat_sin1k_test )
{
  std::array<float, PROCESSSIZE> data;
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<float> generator(data.data(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  std::array<float, PROCESSSIZE> outdata;

  ATK::OutPointerFilter<float> output(outdata.data(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}

BOOST_AUTO_TEST_CASE( OutPointerDouble_sin1k_test )
{
  std::array<double, PROCESSSIZE> data;
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }

  ATK::InPointerFilter<double> generator(data.data(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  std::array<double, PROCESSSIZE> outdata;

  ATK::OutPointerFilter<double> output(outdata.data(), 1, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}

BOOST_AUTO_TEST_CASE(OutPointerDouble_check_bound_test)
{
  std::array<double, PROCESSSIZE> data;
  for (ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i + 1.) / 48000 * 1000);
  }

  ATK::InPointerFilter<double> generator(data.data(), 1, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  std::array<double, 2*PROCESSSIZE> outdata;
  std::fill(outdata.begin(), outdata.end(), -1);

  ATK::OutPointerFilter<double> output(outdata.data(), 1, 3*PROCESSSIZE/2, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);

  output.process(2*PROCESSSIZE);

  for (ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
  for (ptrdiff_t i = 0; i < PROCESSSIZE / 2; ++i)
  {
    BOOST_REQUIRE_EQUAL(0, outdata[PROCESSSIZE + i]); // check that input is now 0
  }
  for (ptrdiff_t i = 0; i < PROCESSSIZE / 2; ++i)
  {
    BOOST_REQUIRE_EQUAL(-1, outdata[3 * PROCESSSIZE /2 + i]); // check that we don't write after what we declare was allocated
  }
}

BOOST_AUTO_TEST_CASE( OutPointerFloat_sin1k2k_interleaved_test )
{
  std::array<float, 2*PROCESSSIZE> data;
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[2*i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
    data[2*i+1] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 2000);
  }

  ATK::InPointerFilter<float> generator(data.data(), PROCESSSIZE, 2, true);
  generator.set_output_sampling_rate(48000);

  std::array<double, 2*PROCESSSIZE> outdata;

  ATK::OutPointerFilter<double> output(outdata.data(), PROCESSSIZE, 2, true);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);
  output.set_input_port(1, &generator, 1);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < 2*PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}

BOOST_AUTO_TEST_CASE( OutPointerFloat_sin1k2k_noninterleaved_test )
{
  std::array<float, 2*PROCESSSIZE> data;
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 1000);
  }
  for(ptrdiff_t i = 0; i < PROCESSSIZE; ++i)
  {
    data[i+PROCESSSIZE] = std::sin(2 * boost::math::constants::pi<float>() * (i+1.)/48000 * 2000);
  }

  ATK::InPointerFilter<float> generator(data.data(), 2, PROCESSSIZE, false);
  generator.set_output_sampling_rate(48000);

  std::array<double, 2*PROCESSSIZE> outdata;

  ATK::OutPointerFilter<double> output(outdata.data(), 2, PROCESSSIZE, false);
  output.set_input_sampling_rate(48000);
  output.set_input_port(0, &generator, 0);
  output.set_input_port(1, &generator, 1);

  output.process(2);
  output.process(PROCESSSIZE - 2);

  for(ptrdiff_t i = 0; i < 2*PROCESSSIZE; ++i)
  {
    BOOST_REQUIRE_EQUAL(data[i], outdata[i]);
  }
}
<|endoftext|>


<commit_before>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

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

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

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "departure_boards.h"
#include "request_handle.h"
#include "routing/get_stop_times.h"
#include "type/pb_converter.h"
#include "routing/dataraptor.h"
#include "utils/paginate.h"
#include "routing/dataraptor.h"

#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/container/flat_set.hpp>

namespace pt = boost::posix_time;

namespace navitia { namespace timetables {

static void
render(PbCreator& pb_creator,
          const std::map<stop_point_route, pbnavitia::ResponseStatus>& response_status,
          const std::map<stop_point_route, vector_dt_st>& map_route_stop_point,
          DateTime datetime,
          DateTime max_datetime,
          boost::optional<const std::string> calendar_id,
          uint32_t depth) {
    pb_creator.action_period = pt::time_period(to_posix_time(datetime, pb_creator.data),
                                               to_posix_time(max_datetime, pb_creator.data));

    for(auto id_vec : map_route_stop_point) {
        auto schedule = pb_creator.add_stop_schedules();
        //Each schedule has a stop_point and a route
        pb_creator.fill(pb_creator.data.pt_data->stop_points[id_vec.first.first.val],
                schedule->mutable_stop_point(), depth);

        auto m_route = schedule->mutable_route();
        pb_creator.fill(pb_creator.data.pt_data->routes[id_vec.first.second.val], m_route, depth);
        if (pb_creator.data.pt_data->routes[id_vec.first.second.val]->line != nullptr){
            auto m_line = m_route->mutable_line();
            pb_creator.fill(pb_creator.data.pt_data->routes[id_vec.first.second.val]->line, m_line, 0);
        }
        auto pt_display_information = schedule->mutable_pt_display_informations();

        pb_creator.fill(pb_creator.data.pt_data->routes[id_vec.first.second.val], pt_display_information, 0);

        //Now we fill the date_times
        for(auto dt_st : id_vec.second) {
            auto date_time = schedule->add_date_times();
            const auto& st_calendar = navitia::StopTimeCalandar(dt_st.second, dt_st.first, calendar_id);
            pb_creator.fill(&st_calendar, date_time, 0);
            if (dt_st.second != nullptr) {
                auto vj = dt_st.second->vehicle_journey;
                if(vj != nullptr) {
                    for (const auto& comment: pb_creator.data.pt_data->comments.get(*vj)) {
                        pb_creator.fill(&comment, date_time->mutable_properties()->add_notes(), 0);
                    }
                }
            }
        }
        const auto& it = response_status.find(id_vec.first);
        if(it != response_status.end()){
            schedule->set_response_status(it->second);
        }
    }
}

static time_duration to_navitia(const boost::posix_time::time_duration& dur) {
    return navitia::seconds(dur.total_seconds());
}

time_duration length_of_time(const time_duration& duration_1,
                       const time_duration& duration_2) {
    if (duration_1 <= duration_2) {
        return duration_2 - duration_1;
    } else {
        return duration_2 + (hours(24) - duration_1);
    }
}

bool between_opening_and_closing(const time_duration& me,
                                 const time_duration& opening,
                                 const time_duration& closing) {
    if (opening < closing) {
        return (opening <= me && me <= closing);
    } else {
        return (opening <= me || me <= closing);
    }
}

bool line_closed (const time_duration& duration,
             const time_duration& opening,
             const time_duration& closing,
             const pt::ptime& date) {
    const auto begin = to_navitia(date.time_of_day());
    return !between_opening_and_closing(begin, opening, closing)
            && !between_opening_and_closing((begin + duration), opening, closing)
            && duration < (length_of_time(opening, closing) + length_of_time(begin, opening));
}

static bool line_closed (const time_duration& duration,
                  const type::Route* route,
                  const pt::ptime& date) {
    if (route->line->opening_time && route->line->closing_time) {
        const auto opening = to_navitia(*route->line->opening_time);
        const auto closing = to_navitia(*route->line->closing_time);
        return line_closed(duration, opening, closing, date);
    }
    return false;
}

void departure_board(PbCreator& pb_creator, const std::string& request,
                boost::optional<const std::string> calendar_id,
                const std::vector<std::string>& forbidden_uris,
                const pt::ptime date,
                uint32_t duration, uint32_t depth,
                int count, int start_page, const type::RTLevel rt_level, const size_t items_per_route_point) {

    RequestHandle handler(pb_creator, request, forbidden_uris, date, duration, calendar_id);

    if (pb_creator.has_error() || (handler.journey_pattern_points.size() == 0)) {
        return;
    }

    if (calendar_id) {
        //check whether that calendar exists, to raise an early error
        if (pb_creator.data.pt_data->calendars_map.find(*calendar_id) == pb_creator.data.pt_data->calendars_map.end()) {
            pb_creator.fill_pb_error(pbnavitia::Error::bad_filter, "stop_schedules : calendar does not exist");
            return;
        }
    }
    //  <stop_point_route, status>
    std::map<stop_point_route, pbnavitia::ResponseStatus> response_status;

    std::map<stop_point_route, vector_dt_st> map_route_stop_point;

    //Mapping route/stop_point
    boost::container::flat_set<stop_point_route> sps_routes;
    for(auto jpp_idx : handler.journey_pattern_points) {
        const auto& jpp = pb_creator.data.dataRaptor->jp_container.get(jpp_idx);
        const auto& jp = pb_creator.data.dataRaptor->jp_container.get(jpp.jp_idx);
        stop_point_route key = {jpp.sp_idx, jp.route_idx};
        sps_routes.insert(key);
    }
    size_t total_result = sps_routes.size();
    sps_routes = paginate(sps_routes, count, start_page);
    //Trie des vecteurs de date_times stop_times
    auto sort_predicate = [](routing::datetime_stop_time dt1, routing::datetime_stop_time dt2) {
                    return dt1.first < dt2.first;
                };
    // On regroupe entre eux les stop_times appartenant
    // au meme couple (stop_point, route)
    // On veut en effet afficher les départs regroupés par route
    // (une route étant une vague direction commerciale
    for (const auto& sp_route: sps_routes) {
        std::vector<routing::datetime_stop_time> stop_times;
        const type::StopPoint* stop_point = pb_creator.data.pt_data->stop_points[sp_route.first.val];
        const type::Route* route = pb_creator.data.pt_data->routes[sp_route.second.val];
        const auto& jpps = pb_creator.data.dataRaptor->jpps_from_sp[sp_route.first];
        std::vector<routing::JppIdx> routepoint_jpps;
        for (const auto& jpp_from_sp: jpps) {
            const routing::JppIdx& jpp_idx = jpp_from_sp.idx;
            const auto& jpp = pb_creator.data.dataRaptor->jp_container.get(jpp_idx);
            const auto& jp = pb_creator.data.dataRaptor->jp_container.get(jpp.jp_idx);
            if (jp.route_idx != sp_route.second) { continue; }

            routepoint_jpps.push_back(jpp_idx);
        }

        std::vector<routing::datetime_stop_time> tmp;
        if (! calendar_id) {
            stop_times = routing::get_stop_times(routing::StopEvent::pick_up, routepoint_jpps, handler.date_time,
                    handler.max_datetime, items_per_route_point, pb_creator.data, rt_level);
        } else {
            stop_times = routing::get_calendar_stop_times(routepoint_jpps, DateTimeUtils::hour(handler.date_time),
                    DateTimeUtils::hour(handler.max_datetime), pb_creator.data, *calendar_id);
        }
        if ( ! calendar_id) {
            std::sort(stop_times.begin(), stop_times.end(), sort_predicate);
        } else {
            // for calendar we want the first stop time to start from handler.date_time
            std::sort(stop_times.begin(), stop_times.end(), routing::CalendarScheduleSort(handler.date_time));
            if (stop_times.size() > items_per_route_point) {
                stop_times.resize(items_per_route_point);
            }
        }

        //we compute the route status
        for (const auto& jpp_from_sp: jpps) {
            const routing::JppIdx& jpp_idx = jpp_from_sp.idx;
            const auto& jpp = pb_creator.data.dataRaptor->jp_container.get(jpp_idx);
            const auto& jp = pb_creator.data.dataRaptor->jp_container.get(jpp.jp_idx);
            const auto& last_jpp = pb_creator.data.dataRaptor->jp_container.get(jp.jpps.back());
            if (sp_route.first == last_jpp.sp_idx) {
                if (stop_point->stop_area == route->destination) {
                    response_status[sp_route] = pbnavitia::ResponseStatus::terminus;
                } else {
                    response_status[sp_route] = pbnavitia::ResponseStatus::partial_terminus;
                }
            }
        }

        //If there is no departure for a request with "RealTime", Test existance of any departure with "base_schedule"
        //If departure with base_schedule is not empty, additional_information = active_disruption
        //Else additional_information = no_departure_this_day
        if (stop_times.empty() && (response_status.find(sp_route) == response_status.end())) {
            auto resp_status = pbnavitia::ResponseStatus::no_departure_this_day;
            if (line_closed(navitia::seconds(duration), route, date)) {
                  resp_status = pbnavitia::ResponseStatus::no_active_circulation_this_day;
            }
            if (rt_level != navitia::type::RTLevel::Base) {
                auto tmp_stop_times = routing::get_stop_times(routing::StopEvent::pick_up, routepoint_jpps, handler.date_time,
                                                              handler.max_datetime, 1, pb_creator.data,
                                                              navitia::type::RTLevel::Base);
                if (!tmp_stop_times.empty()) { resp_status = pbnavitia::ResponseStatus::active_disruption; }
            }
            response_status[sp_route] = resp_status;
        }

        map_route_stop_point[sp_route] = stop_times;
    }

    render(pb_creator, response_status, map_route_stop_point, handler.date_time, handler.max_datetime,
              calendar_id, depth);

    pb_creator.make_paginate(total_result, start_page, count, std::max(pb_creator.departure_boards_size(),
                                                                       pb_creator.stop_schedules_size()));
}
}
}
<commit_msg>traduction<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

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

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

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "departure_boards.h"
#include "request_handle.h"
#include "routing/get_stop_times.h"
#include "type/pb_converter.h"
#include "routing/dataraptor.h"
#include "utils/paginate.h"
#include "routing/dataraptor.h"

#include <boost/lexical_cast.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/container/flat_set.hpp>

namespace pt = boost::posix_time;

namespace navitia { namespace timetables {

static void
render(PbCreator& pb_creator,
          const std::map<stop_point_route, pbnavitia::ResponseStatus>& response_status,
          const std::map<stop_point_route, vector_dt_st>& map_route_stop_point,
          DateTime datetime,
          DateTime max_datetime,
          boost::optional<const std::string> calendar_id,
          uint32_t depth) {
    pb_creator.action_period = pt::time_period(to_posix_time(datetime, pb_creator.data),
                                               to_posix_time(max_datetime, pb_creator.data));

    for(auto id_vec : map_route_stop_point) {
        auto schedule = pb_creator.add_stop_schedules();
        //Each schedule has a stop_point and a route
        pb_creator.fill(pb_creator.data.pt_data->stop_points[id_vec.first.first.val],
                schedule->mutable_stop_point(), depth);

        auto m_route = schedule->mutable_route();
        pb_creator.fill(pb_creator.data.pt_data->routes[id_vec.first.second.val], m_route, depth);
        if (pb_creator.data.pt_data->routes[id_vec.first.second.val]->line != nullptr){
            auto m_line = m_route->mutable_line();
            pb_creator.fill(pb_creator.data.pt_data->routes[id_vec.first.second.val]->line, m_line, 0);
        }
        auto pt_display_information = schedule->mutable_pt_display_informations();

        pb_creator.fill(pb_creator.data.pt_data->routes[id_vec.first.second.val], pt_display_information, 0);

        //Now we fill the date_times
        for(auto dt_st : id_vec.second) {
            auto date_time = schedule->add_date_times();
            const auto& st_calendar = navitia::StopTimeCalandar(dt_st.second, dt_st.first, calendar_id);
            pb_creator.fill(&st_calendar, date_time, 0);
            if (dt_st.second != nullptr) {
                auto vj = dt_st.second->vehicle_journey;
                if(vj != nullptr) {
                    for (const auto& comment: pb_creator.data.pt_data->comments.get(*vj)) {
                        pb_creator.fill(&comment, date_time->mutable_properties()->add_notes(), 0);
                    }
                }
            }
        }
        const auto& it = response_status.find(id_vec.first);
        if(it != response_status.end()){
            schedule->set_response_status(it->second);
        }
    }
}

static time_duration to_navitia(const boost::posix_time::time_duration& dur) {
    return navitia::seconds(dur.total_seconds());
}

time_duration length_of_time(const time_duration& duration_1,
                       const time_duration& duration_2) {
    if (duration_1 <= duration_2) {
        return duration_2 - duration_1;
    } else {
        return duration_2 + (hours(24) - duration_1);
    }
}

bool between_opening_and_closing(const time_duration& me,
                                 const time_duration& opening,
                                 const time_duration& closing) {
    if (opening < closing) {
        return (opening <= me && me <= closing);
    } else {
        return (opening <= me || me <= closing);
    }
}

bool line_closed (const time_duration& duration,
             const time_duration& opening,
             const time_duration& closing,
             const pt::ptime& date) {
    const auto begin = to_navitia(date.time_of_day());
    return !between_opening_and_closing(begin, opening, closing)
            && !between_opening_and_closing((begin + duration), opening, closing)
            && duration < (length_of_time(opening, closing) + length_of_time(begin, opening));
}

static bool line_closed (const time_duration& duration,
                  const type::Route* route,
                  const pt::ptime& date) {
    if (route->line->opening_time && route->line->closing_time) {
        const auto opening = to_navitia(*route->line->opening_time);
        const auto closing = to_navitia(*route->line->closing_time);
        return line_closed(duration, opening, closing, date);
    }
    return false;
}

void departure_board(PbCreator& pb_creator, const std::string& request,
                boost::optional<const std::string> calendar_id,
                const std::vector<std::string>& forbidden_uris,
                const pt::ptime date,
                uint32_t duration, uint32_t depth,
                int count, int start_page, const type::RTLevel rt_level, const size_t items_per_route_point) {

    RequestHandle handler(pb_creator, request, forbidden_uris, date, duration, calendar_id);

    if (pb_creator.has_error() || (handler.journey_pattern_points.size() == 0)) {
        return;
    }

    if (calendar_id) {
        //check whether that calendar exists, to raise an early error
        if (pb_creator.data.pt_data->calendars_map.find(*calendar_id) == pb_creator.data.pt_data->calendars_map.end()) {
            pb_creator.fill_pb_error(pbnavitia::Error::bad_filter, "stop_schedules : calendar does not exist");
            return;
        }
    }
    //  <stop_point_route, status>
    std::map<stop_point_route, pbnavitia::ResponseStatus> response_status;

    std::map<stop_point_route, vector_dt_st> map_route_stop_point;

    //Mapping route/stop_point
    boost::container::flat_set<stop_point_route> sps_routes;
    for(auto jpp_idx : handler.journey_pattern_points) {
        const auto& jpp = pb_creator.data.dataRaptor->jp_container.get(jpp_idx);
        const auto& jp = pb_creator.data.dataRaptor->jp_container.get(jpp.jp_idx);
        stop_point_route key = {jpp.sp_idx, jp.route_idx};
        sps_routes.insert(key);
    }
    size_t total_result = sps_routes.size();
    sps_routes = paginate(sps_routes, count, start_page);
    auto sort_predicate = [](routing::datetime_stop_time dt1, routing::datetime_stop_time dt2) {
                    return dt1.first < dt2.first;
                };
    // we group the stoptime belonging to the same pair (stop_point, route)
    // since we want to display the departures grouped by route
    // the route being a loose commercial direction
    for (const auto& sp_route: sps_routes) {
        std::vector<routing::datetime_stop_time> stop_times;
        const type::StopPoint* stop_point = pb_creator.data.pt_data->stop_points[sp_route.first.val];
        const type::Route* route = pb_creator.data.pt_data->routes[sp_route.second.val];
        const auto& jpps = pb_creator.data.dataRaptor->jpps_from_sp[sp_route.first];
        std::vector<routing::JppIdx> routepoint_jpps;
        for (const auto& jpp_from_sp: jpps) {
            const routing::JppIdx& jpp_idx = jpp_from_sp.idx;
            const auto& jpp = pb_creator.data.dataRaptor->jp_container.get(jpp_idx);
            const auto& jp = pb_creator.data.dataRaptor->jp_container.get(jpp.jp_idx);
            if (jp.route_idx != sp_route.second) { continue; }

            routepoint_jpps.push_back(jpp_idx);
        }

        std::vector<routing::datetime_stop_time> tmp;
        if (! calendar_id) {
            stop_times = routing::get_stop_times(routing::StopEvent::pick_up, routepoint_jpps, handler.date_time,
                    handler.max_datetime, items_per_route_point, pb_creator.data, rt_level);
        } else {
            stop_times = routing::get_calendar_stop_times(routepoint_jpps, DateTimeUtils::hour(handler.date_time),
                    DateTimeUtils::hour(handler.max_datetime), pb_creator.data, *calendar_id);
        }
        if ( ! calendar_id) {
            std::sort(stop_times.begin(), stop_times.end(), sort_predicate);
        } else {
            // for calendar we want the first stop time to start from handler.date_time
            std::sort(stop_times.begin(), stop_times.end(), routing::CalendarScheduleSort(handler.date_time));
            if (stop_times.size() > items_per_route_point) {
                stop_times.resize(items_per_route_point);
            }
        }

        //we compute the route status
        for (const auto& jpp_from_sp: jpps) {
            const routing::JppIdx& jpp_idx = jpp_from_sp.idx;
            const auto& jpp = pb_creator.data.dataRaptor->jp_container.get(jpp_idx);
            const auto& jp = pb_creator.data.dataRaptor->jp_container.get(jpp.jp_idx);
            const auto& last_jpp = pb_creator.data.dataRaptor->jp_container.get(jp.jpps.back());
            if (sp_route.first == last_jpp.sp_idx) {
                if (stop_point->stop_area == route->destination) {
                    response_status[sp_route] = pbnavitia::ResponseStatus::terminus;
                } else {
                    response_status[sp_route] = pbnavitia::ResponseStatus::partial_terminus;
                }
            }
        }

        //If there is no departure for a request with "RealTime", Test existance of any departure with "base_schedule"
        //If departure with base_schedule is not empty, additional_information = active_disruption
        //Else additional_information = no_departure_this_day
        if (stop_times.empty() && (response_status.find(sp_route) == response_status.end())) {
            auto resp_status = pbnavitia::ResponseStatus::no_departure_this_day;
            if (line_closed(navitia::seconds(duration), route, date)) {
                  resp_status = pbnavitia::ResponseStatus::no_active_circulation_this_day;
            }
            if (rt_level != navitia::type::RTLevel::Base) {
                auto tmp_stop_times = routing::get_stop_times(routing::StopEvent::pick_up, routepoint_jpps, handler.date_time,
                                                              handler.max_datetime, 1, pb_creator.data,
                                                              navitia::type::RTLevel::Base);
                if (!tmp_stop_times.empty()) { resp_status = pbnavitia::ResponseStatus::active_disruption; }
            }
            response_status[sp_route] = resp_status;
        }

        map_route_stop_point[sp_route] = stop_times;
    }

    render(pb_creator, response_status, map_route_stop_point, handler.date_time, handler.max_datetime,
              calendar_id, depth);

    pb_creator.make_paginate(total_result, start_page, count, std::max(pb_creator.departure_boards_size(),
                                                                       pb_creator.stop_schedules_size()));
}
}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2018 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix3 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.
 *
 * For more details, see http://www.mrtrix.org/
 */

#include "command.h"

#include "header.h"
#include "image.h"
#include "image_helpers.h"

#include "surface/mesh.h"
#include "surface/algo/mesh2image.h"

using namespace MR;
using namespace App;

void usage ()
{

  AUTHOR = "Robert E. Smith (robert.smith@florey.edu.au)";

  SYNOPSIS = "Convert a mesh surface to a partial volume estimation image";

  REFERENCES
    + "Smith, R. E.; Tournier, J.-D.; Calamante, F. & Connelly, A. " // Internal
    "Anatomically-constrained tractography: Improved diffusion MRI streamlines tractography through effective use of anatomical information. "
    "NeuroImage, 2012, 62, 1924-1938";

  ARGUMENTS
  + Argument ("source",   "the mesh file; note vertices must be defined in realspace coordinates").type_file_in()
  + Argument ("template", "the template image").type_image_in()
  + Argument ("output",   "the output image").type_image_out();

}

void run ()
{

  // Read in the mesh data
  Surface::Mesh mesh (argument[0]);

  // Get the template image
  Header template_header = Header::open (argument[1]);
  check_3D_nonunity (template_header);

  // Create the output image
  template_header.datatype() = DataType::Float32;
  template_header.datatype().set_byte_order_native();
  Image<float> output = Image<float>::create (argument[2], template_header);

  // Perform the partial volume estimation
  Surface::Algo::mesh2image (mesh, output);

}
<commit_msg>mesh2voxel: Ensure output image is floating-point<commit_after>/*
 * Copyright (c) 2008-2018 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/
 *
 * MRtrix3 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.
 *
 * For more details, see http://www.mrtrix.org/
 */

#include "command.h"

#include "header.h"
#include "image.h"
#include "image_helpers.h"

#include "surface/mesh.h"
#include "surface/algo/mesh2image.h"

using namespace MR;
using namespace App;

void usage ()
{

  AUTHOR = "Robert E. Smith (robert.smith@florey.edu.au)";

  SYNOPSIS = "Convert a mesh surface to a partial volume estimation image";

  REFERENCES
    + "Smith, R. E.; Tournier, J.-D.; Calamante, F. & Connelly, A. " // Internal
    "Anatomically-constrained tractography: Improved diffusion MRI streamlines tractography through effective use of anatomical information. "
    "NeuroImage, 2012, 62, 1924-1938";

  ARGUMENTS
  + Argument ("source",   "the mesh file; note vertices must be defined in realspace coordinates").type_file_in()
  + Argument ("template", "the template image").type_image_in()
  + Argument ("output",   "the output image").type_image_out();

}

void run ()
{

  // Read in the mesh data
  Surface::Mesh mesh (argument[0]);

  // Get the template image
  Header template_header = Header::open (argument[1]);
  check_3D_nonunity (template_header);

  // Ensure that a floating-point representation is used for the output image,
  //   as is required for representing partial volumes
  template_header.datatype() = DataType::Float32;
  template_header.datatype().set_byte_order_native();

  // Create the output image
  template_header.datatype() = DataType::Float32;
  template_header.datatype().set_byte_order_native();
  Image<float> output = Image<float>::create (argument[2], template_header);

  // Perform the partial volume estimation
  Surface::Algo::mesh2image (mesh, output);

}
<|endoftext|>


<commit_before>#include <cstdlib>
#include <string>
#include <boost/asio.hpp>

#include "util.h"
#include "Log.h"

#ifdef WIN32
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sysinfoapi.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <shlobj.h>

#ifdef _MSC_VER
#pragma comment(lib, "IPHLPAPI.lib")
#endif // _MSC_VER

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

// inet_pton exists Windows since Vista, but XP doesn't have that function!
// This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found
int inet_pton_xp(int af, const char *src, void *dst)
{
	struct sockaddr_storage ss;
	int size = sizeof (ss);
	char src_copy[INET6_ADDRSTRLEN + 1];

	ZeroMemory (&ss, sizeof (ss));
	strncpy (src_copy, src, INET6_ADDRSTRLEN + 1);
	src_copy[INET6_ADDRSTRLEN] = 0;

	if (WSAStringToAddress (src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0)
	{
		switch (af)
		{
		case AF_INET:
			*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
			return 1;
		case AF_INET6:
			*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
			return 1;
		}
	}
	return 0;
}
#else /* !WIN32 => UNIX */
#include <sys/types.h>
#include <ifaddrs.h>
#endif

namespace i2p
{
namespace util
{

	void RunnableService::StartIOService ()
	{
		if (!m_IsRunning)
		{
			m_IsRunning = true;
			m_Thread.reset (new std::thread (std::bind (& RunnableService::Run, this)));
		}
	}

	void RunnableService::StopIOService ()
	{
		if (m_IsRunning)
		{
			m_IsRunning = false;
			m_Service.stop ();
			if (m_Thread)
			{
				m_Thread->join ();
				m_Thread = nullptr;
			}
		}
	}

	void RunnableService::Run ()
	{
		while (m_IsRunning)
		{
			try
			{
				m_Service.run ();
			}
			catch (std::exception& ex)
			{
				LogPrint (eLogError, m_Name, ": runtime exception: ", ex.what ());
			}
		}
	}

namespace net
{
#ifdef WIN32
	bool IsWindowsXPorLater()
	{
	    static bool isRequested = false;
	    static bool isXP = false;
	    if (!isRequested)
	    {
	        // request
            OSVERSIONINFO osvi;

            ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
            osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
            GetVersionEx(&osvi);

            isXP = osvi.dwMajorVersion <= 5;
            isRequested = true;
        }
        return isXP;
	}

	int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;

			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv4 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr;
				if(localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					return result;
				}
				pUnicast = pUnicast->Next;
			}
			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv4 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindowsIpv6(sockaddr_in6 inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		bool found_address = false;
		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;
			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv6 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr;

				for (int j = 0; j != 8; ++j)
				{
					if (localInterfaceAddress->sin6_addr.u.Word[j] != inputAddress.sin6_addr.u.Word[j])
						break;
					else
						found_address = true;
				}

				if (found_address)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					pAddresses = nullptr;
					return result;
				}
				pUnicast = pUnicast->Next;
			}

			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv6 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindows(const boost::asio::ip::address& localAddress, int fallback)
	{
#ifdef UNICODE
		string localAddress_temporary = localAddress.to_string();
		wstring localAddressUniversal(localAddress_temporary.begin(), localAddress_temporary.end());
#else
		std::string localAddressUniversal = localAddress.to_string();
#endif

        typedef int (* IPN)(int af, const char *src, void *dst);
		IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
        if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found

		if(localAddress.is_v4())
		{
			sockaddr_in inputAddress;
            inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
			return GetMTUWindowsIpv4(inputAddress, fallback);
		}
		else if(localAddress.is_v6())
		{
			sockaddr_in6 inputAddress;
            inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
			return GetMTUWindowsIpv6(inputAddress, fallback);
		} else {
			LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
			return fallback;
		}
	}
#else // assume unix
	int GetMTUUnix(const boost::asio::ip::address& localAddress, int fallback)
	{
		ifaddrs* ifaddr, *ifa = nullptr;
		if(getifaddrs(&ifaddr) == -1)
		{
			LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno));
			return fallback;
		}

		int family = 0;
		// look for interface matching local address
		for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
		{
			if(!ifa->ifa_addr)
				continue;

			family = ifa->ifa_addr->sa_family;
			if(family == AF_INET && localAddress.is_v4())
			{
				sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr;
				if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4))
					break; // address matches
			}
			else if(family == AF_INET6 && localAddress.is_v6())
			{
				sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr;
				if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16))
					break; // address matches
			}
		}
		int mtu = fallback;
		if(ifa && family)
		{ // interface found?
			int fd = socket(family, SOCK_DGRAM, 0);
			if(fd > 0)
			{
				ifreq ifr;
				strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); // set interface for query
				if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0)
					mtu = ifr.ifr_mtu; // MTU
				else
					LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno));
				close(fd);
			}
			else
				LogPrint(eLogError, "NetIface: Failed to create datagram socket");
		}
		else
			LogPrint(eLogWarning, "NetIface: interface for local address", localAddress.to_string(), " not found");
		freeifaddrs(ifaddr);

		return mtu;
	}
#endif // WIN32

	int GetMTU(const boost::asio::ip::address& localAddress)
	{
		const int fallback = 576; // fallback MTU

#ifdef WIN32
		return GetMTUWindows(localAddress, fallback);
#else
		return GetMTUUnix(localAddress, fallback);
#endif
		return fallback;
	}

	const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6)
	{
#ifdef WIN32
		LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32");
		if(ipv6)
			return boost::asio::ip::address::from_string("::1");
		else
			return boost::asio::ip::address::from_string("127.0.0.1");
#else
		int af = (ipv6 ? AF_INET6 : AF_INET);
		ifaddrs * addrs = nullptr;
		if(getifaddrs(&addrs) == 0)
		{
			// got ifaddrs
			ifaddrs * cur = addrs;
			while(cur)
			{
				std::string cur_ifname(cur->ifa_name);
				if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
				{
					// match
					char  addr[INET6_ADDRSTRLEN];
					memset (addr, 0, INET6_ADDRSTRLEN);
					if(af == AF_INET)
						inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
					else
						inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN);
					freeifaddrs(addrs);
					std::string cur_ifaddr(addr);
					return boost::asio::ip::address::from_string(cur_ifaddr);
				}
				cur = cur->ifa_next;
			}
		}
		if(addrs) freeifaddrs(addrs);
		std::string fallback;
		if(ipv6)
		{
			fallback = "::1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv6 address for interface ", ifname);
		} else {
			fallback = "127.0.0.1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
		}
		return boost::asio::ip::address::from_string(fallback);

#endif
	}
}
} // util
} // i2p
<commit_msg>change minimal MTU size<commit_after>#include <cstdlib>
#include <string>
#include <boost/asio.hpp>

#include "util.h"
#include "Log.h"

#ifdef WIN32
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <sysinfoapi.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <shlobj.h>

#ifdef _MSC_VER
#pragma comment(lib, "IPHLPAPI.lib")
#endif // _MSC_VER

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

// inet_pton exists Windows since Vista, but XP doesn't have that function!
// This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found
int inet_pton_xp(int af, const char *src, void *dst)
{
	struct sockaddr_storage ss;
	int size = sizeof (ss);
	char src_copy[INET6_ADDRSTRLEN + 1];

	ZeroMemory (&ss, sizeof (ss));
	strncpy (src_copy, src, INET6_ADDRSTRLEN + 1);
	src_copy[INET6_ADDRSTRLEN] = 0;

	if (WSAStringToAddress (src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0)
	{
		switch (af)
		{
		case AF_INET:
			*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
			return 1;
		case AF_INET6:
			*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
			return 1;
		}
	}
	return 0;
}
#else /* !WIN32 => UNIX */
#include <sys/types.h>
#include <ifaddrs.h>
#endif

namespace i2p
{
namespace util
{

	void RunnableService::StartIOService ()
	{
		if (!m_IsRunning)
		{
			m_IsRunning = true;
			m_Thread.reset (new std::thread (std::bind (& RunnableService::Run, this)));
		}
	}

	void RunnableService::StopIOService ()
	{
		if (m_IsRunning)
		{
			m_IsRunning = false;
			m_Service.stop ();
			if (m_Thread)
			{
				m_Thread->join ();
				m_Thread = nullptr;
			}
		}
	}

	void RunnableService::Run ()
	{
		while (m_IsRunning)
		{
			try
			{
				m_Service.run ();
			}
			catch (std::exception& ex)
			{
				LogPrint (eLogError, m_Name, ": runtime exception: ", ex.what ());
			}
		}
	}

namespace net
{
#ifdef WIN32
	bool IsWindowsXPorLater()
	{
	    static bool isRequested = false;
	    static bool isXP = false;
	    if (!isRequested)
	    {
	        // request
            OSVERSIONINFO osvi;

            ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
            osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
            GetVersionEx(&osvi);

            isXP = osvi.dwMajorVersion <= 5;
            isRequested = true;
        }
        return isXP;
	}

	int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;

			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv4 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in* localInterfaceAddress = (sockaddr_in*) lpAddr;
				if(localInterfaceAddress->sin_addr.S_un.S_addr == inputAddress.sin_addr.S_un.S_addr)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					return result;
				}
				pUnicast = pUnicast->Next;
			}
			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv4 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindowsIpv6(sockaddr_in6 inputAddress, int fallback)
	{
		ULONG outBufLen = 0;
		PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
		PIP_ADAPTER_ADDRESSES pCurrAddresses = nullptr;
		PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr;

		if(GetAdaptersAddresses(AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen)
			== ERROR_BUFFER_OVERFLOW)
		{
			FREE(pAddresses);
			pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(outBufLen);
		}

		DWORD dwRetVal = GetAdaptersAddresses(
			AF_INET6, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen
		);

		if(dwRetVal != NO_ERROR)
		{
			LogPrint(eLogError, "NetIface: GetMTU(): enclosed GetAdaptersAddresses() call has failed");
			FREE(pAddresses);
			return fallback;
		}

		bool found_address = false;
		pCurrAddresses = pAddresses;
		while(pCurrAddresses)
		{
			PIP_ADAPTER_UNICAST_ADDRESS firstUnicastAddress = pCurrAddresses->FirstUnicastAddress;
			pUnicast = pCurrAddresses->FirstUnicastAddress;
			if(pUnicast == nullptr)
				LogPrint(eLogError, "NetIface: GetMTU(): not a unicast ipv6 address, this is not supported");

			for(int i = 0; pUnicast != nullptr; ++i)
			{
				LPSOCKADDR lpAddr = pUnicast->Address.lpSockaddr;
				sockaddr_in6 *localInterfaceAddress = (sockaddr_in6*) lpAddr;

				for (int j = 0; j != 8; ++j)
				{
					if (localInterfaceAddress->sin6_addr.u.Word[j] != inputAddress.sin6_addr.u.Word[j])
						break;
					else
						found_address = true;
				}

				if (found_address)
				{
					auto result = pAddresses->Mtu;
					FREE(pAddresses);
					pAddresses = nullptr;
					return result;
				}
				pUnicast = pUnicast->Next;
			}

			pCurrAddresses = pCurrAddresses->Next;
		}

		LogPrint(eLogError, "NetIface: GetMTU(): no usable unicast ipv6 addresses found");
		FREE(pAddresses);
		return fallback;
	}

	int GetMTUWindows(const boost::asio::ip::address& localAddress, int fallback)
	{
#ifdef UNICODE
		string localAddress_temporary = localAddress.to_string();
		wstring localAddressUniversal(localAddress_temporary.begin(), localAddress_temporary.end());
#else
		std::string localAddressUniversal = localAddress.to_string();
#endif

        typedef int (* IPN)(int af, const char *src, void *dst);
		IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
        if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found

		if(localAddress.is_v4())
		{
			sockaddr_in inputAddress;
            inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
			return GetMTUWindowsIpv4(inputAddress, fallback);
		}
		else if(localAddress.is_v6())
		{
			sockaddr_in6 inputAddress;
            inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
			return GetMTUWindowsIpv6(inputAddress, fallback);
		} else {
			LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
			return fallback;
		}
	}
#else // assume unix
	int GetMTUUnix(const boost::asio::ip::address& localAddress, int fallback)
	{
		ifaddrs* ifaddr, *ifa = nullptr;
		if(getifaddrs(&ifaddr) == -1)
		{
			LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno));
			return fallback;
		}

		int family = 0;
		// look for interface matching local address
		for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next)
		{
			if(!ifa->ifa_addr)
				continue;

			family = ifa->ifa_addr->sa_family;
			if(family == AF_INET && localAddress.is_v4())
			{
				sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr;
				if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4))
					break; // address matches
			}
			else if(family == AF_INET6 && localAddress.is_v6())
			{
				sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr;
				if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16))
					break; // address matches
			}
		}
		int mtu = fallback;
		if(ifa && family)
		{ // interface found?
			int fd = socket(family, SOCK_DGRAM, 0);
			if(fd > 0)
			{
				ifreq ifr;
				strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); // set interface for query
				if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0)
					mtu = ifr.ifr_mtu; // MTU
				else
					LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno));
				close(fd);
			}
			else
				LogPrint(eLogError, "NetIface: Failed to create datagram socket");
		}
		else
			LogPrint(eLogWarning, "NetIface: interface for local address", localAddress.to_string(), " not found");
		freeifaddrs(ifaddr);

		return mtu;
	}
#endif // WIN32

	int GetMTU(const boost::asio::ip::address& localAddress)
	{
		int fallback = localAddress.is_v6 () ? 1280 : 620; // fallback MTU

#ifdef WIN32
		return GetMTUWindows(localAddress, fallback);
#else
		return GetMTUUnix(localAddress, fallback);
#endif
		return fallback;
	}

	const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6)
	{
#ifdef WIN32
		LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32");
		if(ipv6)
			return boost::asio::ip::address::from_string("::1");
		else
			return boost::asio::ip::address::from_string("127.0.0.1");
#else
		int af = (ipv6 ? AF_INET6 : AF_INET);
		ifaddrs * addrs = nullptr;
		if(getifaddrs(&addrs) == 0)
		{
			// got ifaddrs
			ifaddrs * cur = addrs;
			while(cur)
			{
				std::string cur_ifname(cur->ifa_name);
				if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
				{
					// match
					char  addr[INET6_ADDRSTRLEN];
					memset (addr, 0, INET6_ADDRSTRLEN);
					if(af == AF_INET)
						inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
					else
						inet_ntop(af, &((sockaddr_in6 *)cur->ifa_addr)->sin6_addr, addr, INET6_ADDRSTRLEN);
					freeifaddrs(addrs);
					std::string cur_ifaddr(addr);
					return boost::asio::ip::address::from_string(cur_ifaddr);
				}
				cur = cur->ifa_next;
			}
		}
		if(addrs) freeifaddrs(addrs);
		std::string fallback;
		if(ipv6)
		{
			fallback = "::1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv6 address for interface ", ifname);
		} else {
			fallback = "127.0.0.1";
			LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
		}
		return boost::asio::ip::address::from_string(fallback);

#endif
	}
}
} // util
} // i2p
<|endoftext|>


<commit_before>/*
 * nt loader
 *
 * Copyright 2006-2008 Mike McCormack
 *
 * 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 St, Fifth Floor, Boston, MA 02110-1301, USA
 */

//
// fiber implementation
//
// Fibers allow multiple execution contexts in thread.
// They are cooperative, and must be switched explicitly.
//
// Lots of gcc specific code here.
// Tested on Linux.  Windows has a native fiber implementation.
//

#include "config.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>

#include "fiber.h"
#include "platform.h"

#define NORET __attribute__((noreturn))

// current_fiber needs visibility from asm code
fiber_t* current_fiber;
fiber_t* sleeping_fiber; // single linked list through prev

extern "C" void switch_fiber(void);
__asm__ (
"\n"
".globl " ASM_NAME_PREFIX "switch_fiber\n"
ASM_NAME_PREFIX "switch_fiber:\n"
	// ret addr
	"\tpushl %eax\n"
	"\tpushl %ebx\n"
	"\tpushl %ecx\n"
	"\tpushl %edx\n"
	"\tpushl %esi\n"
	"\tpushl %edi\n"
	"\tpushl %ebp\n"
	"\tmovl " ASM_NAME_PREFIX "current_fiber, %eax\n"
	"\tmovl %esp, 4(%eax)\n"
	"\tmovl 8(%eax), %eax\n"
	"\tmovl %eax, " ASM_NAME_PREFIX "current_fiber\n"
	"\tmovl 4(%eax), %esp\n"
	"\tpopl %ebp\n"
	"\tpopl %edi\n"
	"\tpopl %esi\n"
	"\tpopl %edx\n"
	"\tpopl %ecx\n"
	"\tpopl %ebx\n"
	"\tpopl %eax\n"
	"\tret\n"
);

extern "C" void fiber_init(void *arg);
__asm__ (
"\n"
".globl " ASM_NAME_PREFIX "fiber_init\n"
ASM_NAME_PREFIX "fiber_init:\n"
	"\tsub $12, %esp\n"
	"\tpushl %ebx\n"
	"\tcall *%eax\n"
	"\tpopl %ebx\n"
	"\tpushl %eax\n"
	"\tpushl %ebx\n"
	"\tcall " ASM_NAME_PREFIX "fiber_exit\n"
);

void fiber_t::yield(void)
{
	if (!current_fiber->next)
		return;
	if (current_fiber->next == current_fiber)
		return;
	switch_fiber();
}

extern "C" void NORET fiber_exit(fiber_t *t, int ret)
{
	t->stop();
	assert(0);
}

void fiber_t::remove_from_runlist()
{
	assert(current_fiber->next);
	assert(current_fiber->prev);
	assert(current_fiber->prev->next == current_fiber);
	assert(current_fiber->next->prev == current_fiber);
	current_fiber->next->prev = current_fiber->prev;
	current_fiber->prev->next = current_fiber->next;
	current_fiber->prev = 0;
}

void fiber_t::stop()
{
	remove_from_runlist();
	yield();
}

void fiber_t::start()
{
	assert(prev == 0);
	next = current_fiber->next;
	prev = current_fiber;
	next->prev = this;
	prev->next = this;
}

int fiber_t::run()
{
	return 0;
}

int fiber_t::run_fiber( fiber_t* fiber )
{
	return fiber->run();
}

fiber_t::fiber_t( unsigned sz ) :
	next(0),
	prev(0),
	stack_size( sz )
{
	assert(current_fiber);

	stack = ::mmap_anon(0, stack_size, PROT_READ|PROT_WRITE|PROT_EXEC);
	if (stack == (void*) -1)
	{
		fprintf(stderr,"failed to allocate stack\n");
		exit(1);
	}

	fiber_stack_t *frame = (fiber_stack_t*) ((char*)stack + stack_size - sizeof (fiber_stack_t));

	frame->ebp = 0;
	frame->esi = 0;
	frame->edi = 0;
	frame->edx = 0;
	frame->ecx = 0;
	frame->ebx = (long) this;
	frame->eax = (long) &fiber_t::run_fiber;
	frame->eip = (long) &fiber_init;

	// link it in to the circular list
	stack_pointer = frame;
}

fiber_t::fiber_t() :
	stack_pointer(0),
	next(0),
	prev(0),
	stack(0),
	stack_size(0)
{
}

void fiber_t::fibers_init(void)
{
	assert(!current_fiber);

	fiber_t *t = new fiber_t;

	t->next = t;
	t->prev = t;
	current_fiber = t;
}

void fiber_t::fibers_finish(void)
{
	assert(current_fiber);
	assert(last_fiber());
	current_fiber->prev = 0;
	delete current_fiber;
	current_fiber = 0;
}

fiber_t::~fiber_t()
{
	assert(prev == 0);
	if (stack)
		munmap(stack, stack_size);
}

bool fiber_t::last_fiber()
{
	return (current_fiber->next == current_fiber);
}
<commit_msg>Register stacks with Valgrind<commit_after>/*
 * nt loader
 *
 * Copyright 2006-2008 Mike McCormack
 *
 * 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 St, Fifth Floor, Boston, MA 02110-1301, USA
 */

//
// fiber implementation
//
// Fibers allow multiple execution contexts in thread.
// They are cooperative, and must be switched explicitly.
//
// Lots of gcc specific code here.
// Tested on Linux.  Windows has a native fiber implementation.
//

#include "config.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>

#include "fiber.h"
#include "platform.h"

#include <valgrind/valgrind.h>

#define NORET __attribute__((noreturn))

// current_fiber needs visibility from asm code
fiber_t* current_fiber;
fiber_t* sleeping_fiber; // single linked list through prev

extern "C" void switch_fiber(void);
__asm__ (
"\n"
".globl " ASM_NAME_PREFIX "switch_fiber\n"
ASM_NAME_PREFIX "switch_fiber:\n"
	// ret addr
	"\tpushl %eax\n"
	"\tpushl %ebx\n"
	"\tpushl %ecx\n"
	"\tpushl %edx\n"
	"\tpushl %esi\n"
	"\tpushl %edi\n"
	"\tpushl %ebp\n"
	"\tmovl " ASM_NAME_PREFIX "current_fiber, %eax\n"
	"\tmovl %esp, 4(%eax)\n"
	"\tmovl 8(%eax), %eax\n"
	"\tmovl %eax, " ASM_NAME_PREFIX "current_fiber\n"
	"\tmovl 4(%eax), %esp\n"
	"\tpopl %ebp\n"
	"\tpopl %edi\n"
	"\tpopl %esi\n"
	"\tpopl %edx\n"
	"\tpopl %ecx\n"
	"\tpopl %ebx\n"
	"\tpopl %eax\n"
	"\tret\n"
);

extern "C" void fiber_init(void *arg);
__asm__ (
"\n"
".globl " ASM_NAME_PREFIX "fiber_init\n"
ASM_NAME_PREFIX "fiber_init:\n"
	"\tsub $12, %esp\n"
	"\tpushl %ebx\n"
	"\tcall *%eax\n"
	"\tpopl %ebx\n"
	"\tpushl %eax\n"
	"\tpushl %ebx\n"
	"\tcall " ASM_NAME_PREFIX "fiber_exit\n"
);

void fiber_t::yield(void)
{
	if (!current_fiber->next)
		return;
	if (current_fiber->next == current_fiber)
		return;
	switch_fiber();
}

extern "C" void NORET fiber_exit(fiber_t *t, int ret)
{
	t->stop();
	assert(0);
}

void fiber_t::remove_from_runlist()
{
	assert(current_fiber->next);
	assert(current_fiber->prev);
	assert(current_fiber->prev->next == current_fiber);
	assert(current_fiber->next->prev == current_fiber);
	current_fiber->next->prev = current_fiber->prev;
	current_fiber->prev->next = current_fiber->next;
	current_fiber->prev = 0;
}

void fiber_t::stop()
{
	remove_from_runlist();
	yield();
}

void fiber_t::start()
{
	assert(prev == 0);
	next = current_fiber->next;
	prev = current_fiber;
	next->prev = this;
	prev->next = this;
}

int fiber_t::run()
{
	return 0;
}

int fiber_t::run_fiber( fiber_t* fiber )
{
	return fiber->run();
}

fiber_t::fiber_t( unsigned sz ) :
	next(0),
	prev(0),
	stack_size( sz )
{
	assert(current_fiber);

	stack = ::mmap_anon(0, stack_size, PROT_READ|PROT_WRITE|PROT_EXEC);
	if (stack == (void*) -1)
	{
		fprintf(stderr,"failed to allocate stack\n");
		exit(1);
	}

	char *stack_end = (char*) stack + stack_size;
	VALGRIND_STACK_REGISTER(stack, stack_end);

	fiber_stack_t *frame = (fiber_stack_t*) (stack_end - sizeof (fiber_stack_t));

	frame->ebp = 0;
	frame->esi = 0;
	frame->edi = 0;
	frame->edx = 0;
	frame->ecx = 0;
	frame->ebx = (long) this;
	frame->eax = (long) &fiber_t::run_fiber;
	frame->eip = (long) &fiber_init;

	// link it in to the circular list
	stack_pointer = frame;
}

fiber_t::fiber_t() :
	stack_pointer(0),
	next(0),
	prev(0),
	stack(0),
	stack_size(0)
{
}

void fiber_t::fibers_init(void)
{
	assert(!current_fiber);

	fiber_t *t = new fiber_t;

	t->next = t;
	t->prev = t;
	current_fiber = t;
}

void fiber_t::fibers_finish(void)
{
	assert(current_fiber);
	assert(last_fiber());
	current_fiber->prev = 0;
	delete current_fiber;
	current_fiber = 0;
}

fiber_t::~fiber_t()
{
	assert(prev == 0);
	if (stack)
		munmap(stack, stack_size);
}

bool fiber_t::last_fiber()
{
	return (current_fiber->next == current_fiber);
}
<|endoftext|>


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

#ifndef DUNE_GDT_BASEFUNCTIONSET_DEFAULT_FV_HH
#define DUNE_GDT_BASEFUNCTIONSET_DEFAULT_FV_HH

#include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh>

#include <dune/stuff/common/type_utils.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace BaseFunctionSet {

// forward, to be used in the traits and to allow for specialization
template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class FiniteVolume
{
  static_assert(Dune::AlwaysFalse< EntityImp >::value, "Untested for these dimensions!");
};

namespace internal {

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols >
class FiniteVolumeTraits
{
public:
  typedef FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  typedef RangeFieldImp BackendType;
  typedef EntityImp     EntityType;
};

} // namespace internal

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp >
class FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
  : public BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
                                   , DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
{
  typedef FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > ThisType;
  typedef BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
                                                      , DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > BaseType;
public:
  typedef FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > Traits;
  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::EntityType  EntityType;

  using typename BaseType::DomainType;
  using typename BaseType::RangeType;
  using typename BaseType::JacobianRangeType;

  FiniteVolume(const EntityType& en)
    : BaseType(en)
    , backend_(1)
  {}

  FiniteVolume(ThisType&& source) = default;

  FiniteVolume(const ThisType& /*other*/) = delete;

  ThisType& operator=(const ThisType& /*other*/) = delete;

  const BackendType& backend() const
  {
    return backend_;
  }

  virtual size_t size() const override final
  {
    return 1;
  }

  virtual size_t order() const override final
  {
    return 0;
  }

  virtual void evaluate(const DomainType& /*xx*/, std::vector< RangeType >& ret) const override final
  {
    assert(ret.size() >= 0);
    ret[0] = 1.0;
  }

  using BaseType::evaluate;

  virtual void jacobian(const DomainType& /*xx*/, std::vector< JacobianRangeType >& ret) const override final
  {
    assert(ret.size() >= 0);
    ret[0] *= 0.0;
  }

  using BaseType::jacobian;

private:
  const BackendType backend_;
}; // class FiniteVolume< ..., 1, 1 >

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
  : public BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
                                   , DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
{
  typedef FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > ThisType;
  typedef BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
                                                      , DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > BaseType;
public:
  typedef FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > Traits;
  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::EntityType  EntityType;

  using typename BaseType::DomainType;
  using BaseType::dimRange;
  using typename BaseType::RangeType;
  using typename BaseType::JacobianRangeType;

  FiniteVolume(const EntityType& en)
    : BaseType(en)
    , backend_(1)
  {}

  FiniteVolume(ThisType&& source) = default;

  FiniteVolume(const ThisType& /*other*/) = delete;

  ThisType& operator=(const ThisType& /*other*/) = delete;

  const BackendType& backend() const
  {
    return backend_;
  }

  virtual size_t size() const override final
  {
    return dimRange;
  }

  virtual size_t order() const override final
  {
    return 0;
  }

  virtual void evaluate(const DomainType& /*xx*/, std::vector< RangeType >& ret) const override final
  {
    assert(ret.size() >= dimRange);
    for (size_t ii = 0; ii < dimRange; ++ii) {
      ret[ii] *= 0.0;
      ret[ii][ii] = 1.0;
    }
  } // ... evaluate(...)

  using BaseType::evaluate;

  virtual void jacobian(const DomainType& /*xx*/, std::vector< JacobianRangeType >& ret) const override final
  {
    assert(ret.size() >= dimRange);
    for (size_t ii = 0; ii < dimRange; ++ii)
      ret[ii] *= 0.0;
  } // ... jacobian(...)

  using BaseType::jacobian;

private:
  const BackendType backend_;
}; // class FiniteVolume< ..., rangeDim, 1 >

} // namespace BaseFunctionSet
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_BASEFUNCTIONSET_DEFAULT_FV_HH
<commit_msg>[basefunctionset.default.fv] fix wrong type names<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_BASEFUNCTIONSET_DEFAULT_FV_HH
#define DUNE_GDT_BASEFUNCTIONSET_DEFAULT_FV_HH

#include <dune/common/fmatrix.hh>
#include <dune/common/fvector.hh>

#include <dune/stuff/common/type_utils.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace BaseFunctionSet {

// forward, to be used in the traits and to allow for specialization
template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1 >
class FiniteVolume
{
  static_assert(Dune::AlwaysFalse< EntityImp >::value, "Untested for these dimensions!");
};

namespace internal {

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols >
class FiniteVolumeTraits
{
public:
  typedef FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, rangeDimCols > derived_type;
  typedef RangeFieldImp BackendType;
  typedef EntityImp     EntityType;
};

} // namespace internal

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp >
class FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
  : public BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
                                   , DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
{
  typedef FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > ThisType;
  typedef BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 >
                                                      , DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > BaseType;
public:
  typedef internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, 1, 1 > Traits;
  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::EntityType  EntityType;

  using typename BaseType::DomainType;
  using typename BaseType::RangeType;
  using typename BaseType::JacobianRangeType;

  FiniteVolume(const EntityType& en)
    : BaseType(en)
    , backend_(1)
  {}

  FiniteVolume(ThisType&& source) = default;

  FiniteVolume(const ThisType& /*other*/) = delete;

  ThisType& operator=(const ThisType& /*other*/) = delete;

  const BackendType& backend() const
  {
    return backend_;
  }

  virtual size_t size() const override final
  {
    return 1;
  }

  virtual size_t order() const override final
  {
    return 0;
  }

  virtual void evaluate(const DomainType& /*xx*/, std::vector< RangeType >& ret) const override final
  {
    assert(ret.size() >= 0);
    ret[0] = 1.0;
  }

  using BaseType::evaluate;

  virtual void jacobian(const DomainType& /*xx*/, std::vector< JacobianRangeType >& ret) const override final
  {
    assert(ret.size() >= 0);
    ret[0] *= 0.0;
  }

  using BaseType::jacobian;

private:
  const BackendType backend_;
}; // class FiniteVolume< ..., 1, 1 >

template< class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim >
class FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
  : public BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
                                   , DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
{
  typedef FiniteVolume< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > ThisType;
  typedef BaseFunctionSetInterface< internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 >
                                                      , DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > BaseType;
public:
  typedef internal::FiniteVolumeTraits< EntityImp, DomainFieldImp, domainDim, RangeFieldImp, rangeDim, 1 > Traits;
  typedef typename Traits::BackendType BackendType;
  typedef typename Traits::EntityType  EntityType;

  using typename BaseType::DomainType;
  using BaseType::dimRange;
  using typename BaseType::RangeType;
  using typename BaseType::JacobianRangeType;

  FiniteVolume(const EntityType& en)
    : BaseType(en)
    , backend_(1)
  {}

  FiniteVolume(ThisType&& source) = default;

  FiniteVolume(const ThisType& /*other*/) = delete;

  ThisType& operator=(const ThisType& /*other*/) = delete;

  const BackendType& backend() const
  {
    return backend_;
  }

  virtual size_t size() const override final
  {
    return dimRange;
  }

  virtual size_t order() const override final
  {
    return 0;
  }

  virtual void evaluate(const DomainType& /*xx*/, std::vector< RangeType >& ret) const override final
  {
    assert(ret.size() >= dimRange);
    for (size_t ii = 0; ii < dimRange; ++ii) {
      ret[ii] *= 0.0;
      ret[ii][ii] = 1.0;
    }
  } // ... evaluate(...)

  using BaseType::evaluate;

  virtual void jacobian(const DomainType& /*xx*/, std::vector< JacobianRangeType >& ret) const override final
  {
    assert(ret.size() >= dimRange);
    for (size_t ii = 0; ii < dimRange; ++ii)
      ret[ii] *= 0.0;
  } // ... jacobian(...)

  using BaseType::jacobian;

private:
  const BackendType backend_;
}; // class FiniteVolume< ..., rangeDim, 1 >

} // namespace BaseFunctionSet
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_BASEFUNCTIONSET_DEFAULT_FV_HH
<|endoftext|>


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

#ifndef DUNE_GDT_DISCRETEFUNCTION_VISUALIZE_HH
#define DUNE_GDT_DISCRETEFUNCTION_VISUALIZE_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include "config.h"
#endif

#include <memory>
#include <type_traits>

#include <dune/common/fvector.hh>
#include <dune/common/dynvector.hh>

#include <dune/grid/io/file/vtk/function.hh>

namespace Dune {
namespace GDT {
namespace DiscreteFunction {

template< class SpaceImp >
class BasisVisualization
  : public Dune::VTKFunction< typename SpaceImp::GridPartType::GridViewType >
{
public:
  typedef SpaceImp SpaceType;
  typedef typename SpaceType::EntityType EntityType;
  typedef typename SpaceType::BaseFunctionSetType::DomainType DomainType;
private:
  typedef typename SpaceType::BaseFunctionSetType::RangeType RangeType;

public:
  BasisVisualization(const SpaceType& sp, const size_t ind, const std::string nm = "basis")
    : space_(sp)
    , index_(ind)
    , values_(space_.mapper().maxNumDofs(), RangeType(0))
    , name_(nm)
  {
    if (index_ >= space_.mapper().maxNumDofs())
      DUNE_THROW(Dune::RangeError,
                 "index has to be smaller than " << space_.mapper().maxNumDofs() << "(is " << index_ << ")!");
  }

  const SpaceType& space() const
  {
    return space_;
  }

  virtual std::string name() const
  {
    return name_;
  }

  /** \defgroup vtk ´´Methods to comply with the Dune::VTKFunction interface.'' */
  /* @{ */
  virtual int ncomps() const
  {
    return SpaceType::dimRange;
  }

  virtual double evaluate(int component, const EntityType& entity, const DomainType& x) const
  {
    const auto baseFunctionSet = space_.baseFunctionSet(entity);
    if (component < 0)
      DUNE_THROW(Dune::RangeError, "component must not be negative (is " << component << ")!");
    if (component < baseFunctionSet.size()) {
      baseFunctionSet.evaluate(x, values_);
      assert(component < values_.size() && "This should not happen!");
      return values_[index_][component];
    } else if (component < space_.mapper().maxNumDofs())
      return 0.0;
    else
      DUNE_THROW(Dune::RangeError,
                 "component has to be smaller than " << space_.mapper().maxNumDofs() << "(is " << component << ")!");
  }
  /* @} */

private:
  const SpaceType& space_;
  const size_t index_;
  mutable std::vector< RangeType > values_;
  const std::string name_;
}; // class BasisVisualization

template< class SpaceImp, class VectorImp >
class VisualizationAdapter
  : public Dune::VTKFunction< typename SpaceImp::GridPartType::GridViewType >
{
public:
  typedef SpaceImp SpaceType;
  typedef VectorImp VectorType;

  typedef typename SpaceType::EntityType EntityType;

  typedef typename SpaceType::BaseFunctionSetType::DomainType DomainType;
  typedef typename SpaceType::BaseFunctionSetType::RangeType RangeType;

  VisualizationAdapter(const SpaceType& sp, const VectorType& vec, const std::string nm = "discrete_function")
    : space_(sp)
    , name_(nm)
    , vector_(vec)
    , indices_(space_.mapper().maxNumDofs(), 0)
    , basis_values_(space_.mapper().maxNumDofs(), RangeType(0))
  {
    if (vector_.size() != space_.mapper().size())
      DUNE_THROW(Dune::RangeError,
                 "The sice of vec (" << vec.size() << ") does not match the size of the space ("
                 << space_.mapper().size() << ")!");
  }

  ~VisualizationAdapter() {}

  const SpaceType& space() const
  {
    return space_;
  }

  virtual std::string name() const
  {
    return name_;
  }

  /** \defgroup vtk ´´Methods to comply with the Dune::VTKFunction interface.'' */
  /* @{ */
  virtual int ncomps() const
  {
    return SpaceType::dimRange;
  }

  virtual double evaluate(int component, const EntityType& entity, const DomainType& xx) const
  {
    if (component < 0)
      DUNE_THROW(Dune::RangeError,
                 "component must not be negative (is " << component << ")!");
    RangeType value(0);
    if (component >= ncomps())
      DUNE_THROW(Dune::RangeError,
                 "component has to be smaller than ncomps() = " << ncomps() << " (is " << component << ")!");
    const auto baseFunctionSet = space_.baseFunctionSet(entity);
    space_.mapper().globalIndices(entity, indices_);
    baseFunctionSet.evaluate(xx, basis_values_);
    for (size_t ii = 0; ii < baseFunctionSet.size(); ++ii) {
      basis_values_[ii] *= vector_.get(indices_[ii]);
      value += basis_values_[ii];
    }
    return value[component];
  }
  /* @} */

private:
  const SpaceType& space_;
  const std::string name_;
  const VectorType& vector_;
  mutable Dune::DynamicVector< size_t > indices_;
  mutable std::vector< RangeType > basis_values_;
}; // class VisualizationAdapter

} // namespace DiscreteFunction
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_VISUALIZE_HH
<commit_msg>[discretefunction.visualize] not needed any more<commit_after><|endoftext|>