<commit_before>#include "TROOT.h"
#include "TSystem.h"
// additional inclusions following: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/macros/AddTaskFemtoLoton.C
#include <vector>
#include "AliAnalysisTaskSE.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisTaskFemtoSMI.h"
#include "AliFemtoDreamEventCuts.h"
#include "AliFemtoDreamTrackCuts.h"
#include "AliFemtoDreamCascadeCuts.h"
#include "AliFemtoDreamCollConfig.h"

AliAnalysisTaskSE* AddTaskFemtoSMI(
    bool isMC = false, // for now ignore implementing MC options
    TString CentEst = "kInt7",
    bool ControlLambdaCuts = false, // this and following not in older version
    double InvMassCut = 0.004,
    double CPACut = 0.99,
    double KaonRejectionLowerCut = 0.48,
    double KaonRejectionUpperCut = 0.515,
    double DaugToPrimCut = 0.05,
    double DaugTov0Cut = 1.5
    )
{
  //Framework specific blabla
  // the manager is static, so get the existing manager via the static method
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();

  if (!mgr)
  {
    printf("No analysis manager to connect to!\n");
    return nullptr;
  }
  // just to see if all went well, check if the input event handler has been
  // connected
  if (!mgr->GetInputEventHandler()) {
    printf("This task requires an input event handler!\n");
    return nullptr;
  }

  //Now we need to setup the Event cuts, we use the Don't worry event cuts
  //from the ALICE DPG which is the offical thing to use.
  AliFemtoDreamEventCuts *evtCuts=
      AliFemtoDreamEventCuts::StandardCutsRun2();
  //This sets the method we want to use to clean up events with negative or too
  //low multiplicity. Usually you use the matching multiplicity estiamtor in your
  //event collection
  evtCuts->CleanUpMult(false,false,false,true);

  // covering the protons
  AliFemtoDreamTrackCuts *TrackCuts = AliFemtoDreamTrackCuts::PrimProtonCuts(isMC, true, false, false);
  TrackCuts->SetFilterBit(128);
  TrackCuts->SetCutCharge(1);
  // leaving out anti-particles for now

  //Lambda Cuts
  AliFemtoDreamv0Cuts *v0Cuts = AliFemtoDreamv0Cuts::LambdaCuts(isMC, true, false);
  AliFemtoDreamTrackCuts *Posv0Daug = AliFemtoDreamTrackCuts::DecayProtonCuts(isMC, true, false);
  AliFemtoDreamTrackCuts *Negv0Daug = AliFemtoDreamTrackCuts::DecayPionCuts(isMC, true, false);

  v0Cuts->SetPosDaugterTrackCuts(Posv0Daug);
  v0Cuts->SetNegDaugterTrackCuts(Negv0Daug);
  v0Cuts->SetPDGCodePosDaug(2212);  //Proton
  v0Cuts->SetPDGCodeNegDaug(211);  //Pion
  v0Cuts->SetPDGCodev0(3122);  //Lambda
  //leaving out anti-lambda def's for now

  if(ControlLambdaCuts) {
    //Adding additional settings to access from train setup
    v0Cuts->SetCutInvMass(InvMassCut);  // default argument: 0.004
    v0Cuts->SetCutCPA(CPACut);  // default: 0.99
    v0Cuts->SetKaonRejection(KaonRejectionLowerCut,KaonRejectionUpperCut);  // default: 0.48, 0.515
    v0Cuts->SetCutDCADaugToPrimVtx(DaugToPrimCut);  // default: 0.05
    v0Cuts->SetCutDCADaugTov0Vtx(DaugTov0Cut);  // default: 1.5
  }

  //Now we define stuff we want for our Particle collection
  //Thanks, CINT - will not compile due to an illegal constructor
  //std::vector<int> PDGParticles ={2212,2212,3122,3122,3312,3312};
  //First we need to tell him about the particles we mix, from the
  //PDG code the mass is obtained.
  std::vector<int> PDGParticles;
  PDGParticles.push_back(2212);
  PDGParticles.push_back(3122);

  //We need to set the ZVtx bins
  std::vector<float> ZVtxBins;
  ZVtxBins.push_back(-10);
  ZVtxBins.push_back(-8);
  ZVtxBins.push_back(-6);
  ZVtxBins.push_back(-4);
  ZVtxBins.push_back(-2);
  ZVtxBins.push_back(0);
  ZVtxBins.push_back(2);
  ZVtxBins.push_back(4);
  ZVtxBins.push_back(6);
  ZVtxBins.push_back(8);
  ZVtxBins.push_back(10);
  //The Multiplicity bins are set here
  std::vector<int> MultBins;
  MultBins.push_back(0);
  MultBins.push_back(4);
  MultBins.push_back(8);
  MultBins.push_back(12);
  MultBins.push_back(16);
  MultBins.push_back(20);
  MultBins.push_back(24);
  MultBins.push_back(28);
  MultBins.push_back(32);
  MultBins.push_back(36);
  MultBins.push_back(40);
  MultBins.push_back(44);
  MultBins.push_back(48);
  MultBins.push_back(52);
  MultBins.push_back(56);
  MultBins.push_back(60);
  MultBins.push_back(64);
  MultBins.push_back(68);
  MultBins.push_back(72);
  MultBins.push_back(76);
  MultBins.push_back(80);

  //The next part is for the result histograms. The order of hist. is the following:
  //                Particle1     Particle2
  //Particle 1       Hist 1         Hist2
  //
  //Particle 2                      Hist3
  //The same way the values for binning, minimum and maximum k* range have to be set!
  //Number of bins
  std::vector<int> NBins;
  NBins.push_back(750);
  NBins.push_back(750);
  NBins.push_back(750);
  std::vector<float> kMin;
  //minimum k* value
  kMin.push_back(0.);
  kMin.push_back(0.);
  kMin.push_back(0.);
  //maximum k* value
  std::vector<float> kMax;
  kMax.push_back(3.);
  kMax.push_back(3.);
  kMax.push_back(3.);

  //To put all this into the task we add it to our collection config object in
  //the following way:
  AliFemtoDreamCollConfig *config=new AliFemtoDreamCollConfig("Femto","Femto"); //IC: third option "false"
  config->SetZBins(ZVtxBins);
  config->SetMultBins(MultBins);
  //Do you want to have an explicit binning of the correlation function for each multiplicity
  //bin set above?
  config->SetMultBinning(true);
  config->SetPDGCodes(PDGParticles);
  config->SetNBinsHist(NBins);
  config->SetMinKRel(kMin);
  config->SetMaxKRel(kMax);
  //Here we set the mixing depth.
  config->SetMixingDepth(10);
  //Added config:

  //config->SetClosePairRejection(false); // needed??
  config->SetDeltaEtaMax(0.017); // ??
  config->SetDeltaPhiMax(0.017); // ??
  // config->SetExtendedQAPairs(pairQA);
  // config->SetmTBins(mTBins);
  // config->SetDomTMultBinning(true);
  // config->SetUseEventMixing(true);
  // config->SetMultiplicityEstimator(AliFemtoDreamEvent::kRef08);
  // need something from the "Systematic"-section in FemtoLoton.C??
  //End of added config

  /*
  //This is just to show off what would be possible in case you are interested, don't be confused by this at the beginning
  //you can just ignore it!
  if (false) {
    config->SetkTBinning(false);
    config->SetmTBinning(false);
    config->SetkTCentralityBinning(false);
    std::vector<float> centBins;
    centBins.push_back(20);
    centBins.push_back(40);
    centBins.push_back(90);
    config->SetCentBins(centBins);
    config->SetZBins(ZVtxBins); // already included above

    if (isMC) {
      config->SetMomentumResolution(true);
    } else {
      std::cout << "You are trying to request the Momentum Resolution without MC Info; fix it wont work! \n";
    }
    if (isMC) {
      config->SetPhiEtaBinnign(true);
    } else {
      std::cout << "You are trying to request the Eta Phi Plots without MC Info; fix it wont work! \n";
    }
  }
   */
  //now we create the task
  AliAnalysisTaskFemtoSMI *task=
      new AliAnalysisTaskFemtoSMI("FemtoDreamPLDefault",isMC);
  //THIS IS VERY IMPORTANT ELSE YOU DONT PROCESS ANY EVENTS
  //kINT7 == Minimum bias
  //kHighMultV0 high multiplicity triggered by the V0 detector
  if(CentEst == "kInt7"){
    task->SelectCollisionCandidates(AliVEvent::kINT7);
    task->SetTrigger(AliVEvent::kINT7);
    std::cout << "Added kINT7 Trigger \n";
  } else if (CentEst == "kHM") {
    task->SelectCollisionCandidates(AliVEvent::kHighMultV0);
    task->SetTrigger(AliVEvent::kHighMultV0);
    std::cout << "Added kHighMultV0 Trigger \n";
  }else{
    std::cout << "=====================================================================" << std::endl;
    std::cout << "=====================================================================" << std::endl;
    std::cout << "Centrality Estimator not set, fix it else your Results will be empty!" << std::endl;
    std::cout << "=====================================================================" << std::endl;
    std::cout << "=====================================================================" << std::endl;
  }

  //Throw all our settings to the task
  task->SetEventCuts(evtCuts);
  // task->SetTrackCutsPart1(TrackCuts1);
  // task->SetTrackCutsPart2(TrackCuts2);
  task->SetCollectionConfig(config);
  // new additions for task:
  task->SetProtonCuts(TrackCuts);
  task->Setv0Cuts(v0Cuts);
  // needed ?? : task->SetCorrelationConfig(config); // We'll see, I guess

  mgr->AddTask(task);

  TString file = AliAnalysisManager::GetCommonFileName();

  AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();

  mgr->ConnectInput(task, 0, cinput);

  AliAnalysisDataContainer *coutputQA;
  TString QAName = Form("MyTask");
  coutputQA = mgr->CreateContainer(
      QAName.Data(), TList::Class(),
      AliAnalysisManager::kOutputContainer,
      Form("%s:%s", file.Data(), QAName.Data()));
  mgr->ConnectOutput(task, 1, coutputQA);

  return task;
}

<commit_msg>Adding optional directory names for several wagons in one train<commit_after>#include "TROOT.h"
#include "TSystem.h"
// additional inclusions following: https://github.com/alisw/AliPhysics/blob/master/PWGCF/FEMTOSCOPY/macros/AddTaskFemtoLoton.C
#include <vector>
#include "AliAnalysisTaskSE.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisTaskFemtoSMI.h"
#include "AliFemtoDreamEventCuts.h"
#include "AliFemtoDreamTrackCuts.h"
#include "AliFemtoDreamCascadeCuts.h"
#include "AliFemtoDreamCollConfig.h"

AliAnalysisTaskSE* AddTaskFemtoSMI(
    bool isMC = false, // for now ignore implementing MC options
    TString CentEst = "kInt7",
    bool ControlLambdaCuts = false, // this and following not in older version
    int    taskCounter = 0,
    double InvMassCut = 0.004,
    double CPACut = 0.99,
    double KaonRejectionLowerCut = 0.48,
    double KaonRejectionUpperCut = 0.515,
    double DaugToPrimCut = 0.05,
    double DaugTov0Cut = 1.5
    )
{
  //Framework specific blabla
  // the manager is static, so get the existing manager via the static method
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();

  if (!mgr)
  {
    printf("No analysis manager to connect to!\n");
    return nullptr;
  }
  // just to see if all went well, check if the input event handler has been
  // connected
  if (!mgr->GetInputEventHandler()) {
    printf("This task requires an input event handler!\n");
    return nullptr;
  }

  //Now we need to setup the Event cuts, we use the Don't worry event cuts
  //from the ALICE DPG which is the offical thing to use.
  AliFemtoDreamEventCuts *evtCuts=
      AliFemtoDreamEventCuts::StandardCutsRun2();
  //This sets the method we want to use to clean up events with negative or too
  //low multiplicity. Usually you use the matching multiplicity estiamtor in your
  //event collection
  evtCuts->CleanUpMult(false,false,false,true);

  // covering the protons
  AliFemtoDreamTrackCuts *TrackCuts = AliFemtoDreamTrackCuts::PrimProtonCuts(isMC, true, false, false);
  TrackCuts->SetFilterBit(128);
  TrackCuts->SetCutCharge(1);
  // leaving out anti-particles for now

  //Lambda Cuts
  AliFemtoDreamv0Cuts *v0Cuts = AliFemtoDreamv0Cuts::LambdaCuts(isMC, true, false);
  AliFemtoDreamTrackCuts *Posv0Daug = AliFemtoDreamTrackCuts::DecayProtonCuts(isMC, true, false);
  AliFemtoDreamTrackCuts *Negv0Daug = AliFemtoDreamTrackCuts::DecayPionCuts(isMC, true, false);

  v0Cuts->SetPosDaugterTrackCuts(Posv0Daug);
  v0Cuts->SetNegDaugterTrackCuts(Negv0Daug);
  v0Cuts->SetPDGCodePosDaug(2212);  //Proton
  v0Cuts->SetPDGCodeNegDaug(211);  //Pion
  v0Cuts->SetPDGCodev0(3122);  //Lambda
  //leaving out anti-lambda def's for now

  if(ControlLambdaCuts) {
    //Adding additional settings to access from train setup
    v0Cuts->SetCutInvMass(InvMassCut);  // default argument: 0.004
    v0Cuts->SetCutCPA(CPACut);  // default: 0.99
    v0Cuts->SetKaonRejection(KaonRejectionLowerCut,KaonRejectionUpperCut);  // default: 0.48, 0.515
    v0Cuts->SetCutDCADaugToPrimVtx(DaugToPrimCut);  // default: 0.05
    v0Cuts->SetCutDCADaugTov0Vtx(DaugTov0Cut);  // default: 1.5
  }

  //Now we define stuff we want for our Particle collection
  //Thanks, CINT - will not compile due to an illegal constructor
  //std::vector<int> PDGParticles ={2212,2212,3122,3122,3312,3312};
  //First we need to tell him about the particles we mix, from the
  //PDG code the mass is obtained.
  std::vector<int> PDGParticles;
  PDGParticles.push_back(2212);
  PDGParticles.push_back(3122);

  //We need to set the ZVtx bins
  std::vector<float> ZVtxBins;
  ZVtxBins.push_back(-10);
  ZVtxBins.push_back(-8);
  ZVtxBins.push_back(-6);
  ZVtxBins.push_back(-4);
  ZVtxBins.push_back(-2);
  ZVtxBins.push_back(0);
  ZVtxBins.push_back(2);
  ZVtxBins.push_back(4);
  ZVtxBins.push_back(6);
  ZVtxBins.push_back(8);
  ZVtxBins.push_back(10);
  //The Multiplicity bins are set here
  std::vector<int> MultBins;
  MultBins.push_back(0);
  MultBins.push_back(4);
  MultBins.push_back(8);
  MultBins.push_back(12);
  MultBins.push_back(16);
  MultBins.push_back(20);
  MultBins.push_back(24);
  MultBins.push_back(28);
  MultBins.push_back(32);
  MultBins.push_back(36);
  MultBins.push_back(40);
  MultBins.push_back(44);
  MultBins.push_back(48);
  MultBins.push_back(52);
  MultBins.push_back(56);
  MultBins.push_back(60);
  MultBins.push_back(64);
  MultBins.push_back(68);
  MultBins.push_back(72);
  MultBins.push_back(76);
  MultBins.push_back(80);

  //The next part is for the result histograms. The order of hist. is the following:
  //                Particle1     Particle2
  //Particle 1       Hist 1         Hist2
  //
  //Particle 2                      Hist3
  //The same way the values for binning, minimum and maximum k* range have to be set!
  //Number of bins
  std::vector<int> NBins;
  NBins.push_back(750);
  NBins.push_back(750);
  NBins.push_back(750);
  std::vector<float> kMin;
  //minimum k* value
  kMin.push_back(0.);
  kMin.push_back(0.);
  kMin.push_back(0.);
  //maximum k* value
  std::vector<float> kMax;
  kMax.push_back(3.);
  kMax.push_back(3.);
  kMax.push_back(3.);

  //To put all this into the task we add it to our collection config object in
  //the following way:
  AliFemtoDreamCollConfig *config=new AliFemtoDreamCollConfig("Femto","Femto"); //IC: third option "false"
  config->SetZBins(ZVtxBins);
  config->SetMultBins(MultBins);
  //Do you want to have an explicit binning of the correlation function for each multiplicity
  //bin set above?
  config->SetMultBinning(true);
  config->SetPDGCodes(PDGParticles);
  config->SetNBinsHist(NBins);
  config->SetMinKRel(kMin);
  config->SetMaxKRel(kMax);
  //Here we set the mixing depth.
  config->SetMixingDepth(10);
  //Added config:

  //config->SetClosePairRejection(false); // needed??
  config->SetDeltaEtaMax(0.017); // ??
  config->SetDeltaPhiMax(0.017); // ??
  // config->SetExtendedQAPairs(pairQA);
  // config->SetmTBins(mTBins);
  // config->SetDomTMultBinning(true);
  // config->SetUseEventMixing(true);
  // config->SetMultiplicityEstimator(AliFemtoDreamEvent::kRef08);
  // need something from the "Systematic"-section in FemtoLoton.C??
  //End of added config

  /*
  //This is just to show off what would be possible in case you are interested, don't be confused by this at the beginning
  //you can just ignore it!
  if (false) {
    config->SetkTBinning(false);
    config->SetmTBinning(false);
    config->SetkTCentralityBinning(false);
    std::vector<float> centBins;
    centBins.push_back(20);
    centBins.push_back(40);
    centBins.push_back(90);
    config->SetCentBins(centBins);
    config->SetZBins(ZVtxBins); // already included above

    if (isMC) {
      config->SetMomentumResolution(true);
    } else {
      std::cout << "You are trying to request the Momentum Resolution without MC Info; fix it wont work! \n";
    }
    if (isMC) {
      config->SetPhiEtaBinnign(true);
    } else {
      std::cout << "You are trying to request the Eta Phi Plots without MC Info; fix it wont work! \n";
    }
  }
   */
  //now we create the task
  AliAnalysisTaskFemtoSMI *task=
      new AliAnalysisTaskFemtoSMI("FemtoDreamPLDefault",isMC);
  //THIS IS VERY IMPORTANT ELSE YOU DONT PROCESS ANY EVENTS
  //kINT7 == Minimum bias
  //kHighMultV0 high multiplicity triggered by the V0 detector
  if(CentEst == "kInt7"){
    task->SelectCollisionCandidates(AliVEvent::kINT7);
    task->SetTrigger(AliVEvent::kINT7);
    std::cout << "Added kINT7 Trigger \n";
  } else if (CentEst == "kHM") {
    task->SelectCollisionCandidates(AliVEvent::kHighMultV0);
    task->SetTrigger(AliVEvent::kHighMultV0);
    std::cout << "Added kHighMultV0 Trigger \n";
  }else{
    std::cout << "=====================================================================" << std::endl;
    std::cout << "=====================================================================" << std::endl;
    std::cout << "Centrality Estimator not set, fix it else your Results will be empty!" << std::endl;
    std::cout << "=====================================================================" << std::endl;
    std::cout << "=====================================================================" << std::endl;
  }

  //Throw all our settings to the task
  task->SetEventCuts(evtCuts);
  // task->SetTrackCutsPart1(TrackCuts1);
  // task->SetTrackCutsPart2(TrackCuts2);
  task->SetCollectionConfig(config);
  // new additions for task:
  task->SetProtonCuts(TrackCuts);
  task->Setv0Cuts(v0Cuts);
  // needed ?? : task->SetCorrelationConfig(config); // We'll see, I guess

  mgr->AddTask(task);

  TString file = AliAnalysisManager::GetCommonFileName();

  AliAnalysisDataContainer *cinput = mgr->GetCommonInputContainer();

  mgr->ConnectInput(task, 0, cinput);

  AliAnalysisDataContainer *coutputQA;
  TString QAName;
  if(taskCounter > 0)
	QAName = Form("MyTask%d",taskCounter);
  else
	QAName = Form("MyTask");

  coutputQA = mgr->CreateContainer(
      QAName.Data(), TList::Class(),
      AliAnalysisManager::kOutputContainer,
      Form("%s:%s", file.Data(), QAName.Data()));
  mgr->ConnectOutput(task, 1, coutputQA);

  return task;
}

<|endoftext|>


<commit_before>/*
 * Author: Dino Wernli
 */

#include "bounding_box.h"

#include <algorithm>
#include <glog/logging.h>

#include "util/ray.h"

BoundingBox::BoundingBox(const Point3& p) : xmin_(p.x()), xmax_(p.x()),
    ymin_(p.y()), ymax_(p.y()), zmin_(p.z()), zmax_(p.z()) {
}

BoundingBox::BoundingBox(const Point3& p1, const Point3& p2)
    : xmin_(std::min(p1.x(), p2.x())), xmax_(std::max(p1.x(), p2.x())),
      ymin_(std::min(p1.y(), p2.y())), ymax_(std::max(p1.y(), p2.y())),
      zmin_(std::min(p1.z(), p2.z())), zmax_(std::max(p1.z(), p2.z())) {
}

BoundingBox::~BoundingBox() {
}

BoundingBox& BoundingBox::Include(const Point3& point) {
  using std::min;
  using std::max;
  xmin_ = min(xmin_, point.x());
  xmax_ = max(xmax_, point.x());
  ymin_ = min(ymin_, point.y());
  ymax_ = max(ymax_, point.y());
  zmin_ = min(zmin_, point.z());
  zmax_ = max(zmax_, point.z());
  return *this;
}

BoundingBox& BoundingBox::Include(const BoundingBox& other) {
  Include(Point3(other.xmin_, other.ymin_, other.zmin_));
  Include(Point3(other.xmax_, other.ymax_, other.zmax_));
  return *this;
}

bool BoundingBox::Intersect(const Ray& ray, Scalar* t_near,
                            Scalar* t_far) const {
  *t_near = -std::numeric_limits<Scalar>::infinity();
  *t_far = std::numeric_limits<Scalar>::infinity();

  bool intersected = AxisIntersect(Axis::x(), ray, t_near, t_far)
        && AxisIntersect(Axis::y(), ray, t_near, t_far)
        && AxisIntersect(Axis::z(), ray, t_near, t_far)
        && (!(*t_far < ray.min_t()))  && (!(*t_near > ray.max_t()));

  DVLOG(2) << "t_near: " << *t_near << ", t_far: " << *t_far
           << ", intersected: " << intersected;

  return intersected;
}

bool BoundingBox::AxisIntersect(Axis axis, const Ray& ray,
                                Scalar* t_near, Scalar* t_far) const {
  Scalar box_min = min()[axis];
  Scalar box_max = max()[axis];
  Scalar origin = ray.origin() [axis];
  Scalar direction = ray.direction() [axis];

  if (direction == 0) {
    if (origin < box_min || origin > box_max) {
      return false;
    }
  } else {
    Scalar t1 = (box_min - origin) / direction;
    Scalar t2 = (box_max - origin) / direction;

    using std::swap;
    if (t1 > t2) swap(t1, t2);

    if (t1 > *t_near) *t_near = t1;
    if (t2 < *t_far) *t_far = t2;

    if (t_near > t_far) {
      DVLOG(2) << "Missed box entirely";
      return false;
    }
  }
  return true;
}
<commit_msg>Add some more debug output.<commit_after>/*
 * Author: Dino Wernli
 */

#include "bounding_box.h"

#include <algorithm>
#include <glog/logging.h>

#include "util/ray.h"

BoundingBox::BoundingBox(const Point3& p) : xmin_(p.x()), xmax_(p.x()),
    ymin_(p.y()), ymax_(p.y()), zmin_(p.z()), zmax_(p.z()) {
}

BoundingBox::BoundingBox(const Point3& p1, const Point3& p2)
    : xmin_(std::min(p1.x(), p2.x())), xmax_(std::max(p1.x(), p2.x())),
      ymin_(std::min(p1.y(), p2.y())), ymax_(std::max(p1.y(), p2.y())),
      zmin_(std::min(p1.z(), p2.z())), zmax_(std::max(p1.z(), p2.z())) {
}

BoundingBox::~BoundingBox() {
}

BoundingBox& BoundingBox::Include(const Point3& point) {
  using std::min;
  using std::max;
  xmin_ = min(xmin_, point.x());
  xmax_ = max(xmax_, point.x());
  ymin_ = min(ymin_, point.y());
  ymax_ = max(ymax_, point.y());
  zmin_ = min(zmin_, point.z());
  zmax_ = max(zmax_, point.z());
  return *this;
}

BoundingBox& BoundingBox::Include(const BoundingBox& other) {
  DVLOG(2) << "Bounding box include: ";
  DVLOG(2) << "\tThis: " << *this;
  DVLOG(2) << "\tOther: " << other;
  Include(other.min());
  Include(other.max());
  DVLOG(2) << "\tFinal: " << *this;
  return *this;
}

bool BoundingBox::Intersect(const Ray& ray, Scalar* t_near,
                            Scalar* t_far) const {
  *t_near = -std::numeric_limits<Scalar>::infinity();
  *t_far = std::numeric_limits<Scalar>::infinity();

  bool intersected = AxisIntersect(Axis::x(), ray, t_near, t_far)
        && AxisIntersect(Axis::y(), ray, t_near, t_far)
        && AxisIntersect(Axis::z(), ray, t_near, t_far);
        && (!(*t_far < ray.min_t()))  && (!(*t_near > ray.max_t()));

  DVLOG(2) << "t_near: " << *t_near << ", t_far: " << *t_far
           << ", intersected: " << intersected;

  return intersected;
}

bool BoundingBox::AxisIntersect(Axis axis, const Ray& ray,
                                Scalar* t_near, Scalar* t_far) const {
  Scalar box_min = min()[axis];
  Scalar box_max = max()[axis];
  Scalar origin = ray.origin() [axis];
  Scalar direction = ray.direction() [axis];

  if (direction == 0) {
    if (origin < box_min || origin > box_max) {
      return false;
    }
  } else {
    Scalar t1 = (box_min - origin) / direction;
    Scalar t2 = (box_max - origin) / direction;

    using std::swap;
    if (t1 > t2) swap(t1, t2);

    if (t1 > *t_near) *t_near = t1;
    if (t2 < *t_far) *t_far = t2;

    if (t_near > t_far) {
      DVLOG(2) << "Missed box entirely";
      return false;
    }
  }
  return true;
}
<|endoftext|>


<commit_before>/*
* Copyright (c) 2017-2019 Pedro Falcato
* This file is part of Onyx, and is released under the terms of the MIT License
* check LICENSE at the root directory for more information
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <string>
#include <shadow.h>
#include <pwd.h>

#include <sys/syscall.h>

char *program_name = NULL;

/* Set the uid and gid */
void switch_users(gid_t gid, uid_t uid)
{
	syscall(SYS_setuid, uid);
	syscall(SYS_setgid, gid);
}

static struct termios old_termios;

int hide_stdin(void)
{
	struct termios attr;
	tcgetattr(STDIN_FILENO, &attr);
	memcpy(&old_termios, &attr, sizeof(struct termios));
	attr.c_lflag &= ~ECHO; /* Clear ECHO */
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr);

	return 0;
}

int reset_terminal(void)
{
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_termios);
	return 0;
}

#define TEMP_BUF_SIZE		1024
int get_output(std::string& str)
{
	char *buf = (char *) malloc(TEMP_BUF_SIZE);
	if(!buf)
		return -1;
	bzero(buf, TEMP_BUF_SIZE);
	bool should_stop = false;
	while(!should_stop && fgets(buf, TEMP_BUF_SIZE, stdin))
	{
		char *pos;
		if((pos = strchr(buf, '\n')))
    	{
			should_stop = true;
			*pos = '\0';
		}

		str += buf;
	}

	/* TODO: Replace bzero with explicit_bzero */
	bzero(buf, TEMP_BUF_SIZE);
	free(buf);

	return 0;
}

bool compare_passwords(struct spwd *spwd, std::string& password)
{
	/* Hash format: $algorithm$salt$hash */
	std::string password_hash(spwd->sp_pwdp);

	std::size_t algo_pos = password_hash.find('$');
	auto salt_pos = password_hash.find('$', algo_pos + 1);
	auto hash_pos = password_hash.find('$', salt_pos + 1);
	if(algo_pos == std::string::npos || salt_pos == std::string::npos || hash_pos == std::string::npos)
	{
		printf("Malformed shadow file.\n");
		return false;
	}

	std::string salt;
	salt.assign(password_hash, algo_pos, hash_pos - algo_pos);

	const char *resulting_hash = crypt(password.c_str(), salt.c_str());

	if(!strcmp(password_hash.c_str(), resulting_hash))
		return true;
	return false;
}

int main(int argc, char **argv, char **envp)
{
	(void) argc;
	(void) envp;
	program_name = argv[0];
	printf("%s: ", argv[0]);
	fflush(stdout);
	struct passwd *user;

	while(true)
	{
		std::string username;
		std::string password;

		printf("username:");
		fflush(stdout);

		if(get_output(username) < 0)
		{
			perror("get_output");
			return 1;
		}

		printf("password:");
		fflush(stdout);

		hide_stdin();

		if(get_output(password) < 0)
		{
			reset_terminal();
			perror("get_output");
			return 1;
		}

		user = getpwnam(username.c_str());
		if(!user)
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		if(!user->pw_name[0])
			break;

		if(user->pw_name[0] == '!' || user->pw_name[0] == '*')
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		auto pass_ent = getspnam(username.c_str());
		if(!pass_ent)
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		if(!compare_passwords(pass_ent, password))
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		break;
	}

	switch_users(user->pw_gid, user->pw_uid);
	/* Set $USER */
	setenv("USER", user->pw_name, 1);
	/* Set $LOGNAME */
	setenv("LOGNAME", user->pw_name, 1);
	/* Set $HOME */
	setenv("HOME", user->pw_dir, 1);
	/* Set $SHELL */
	setenv("SHELL", user->pw_shell, 1);

	if(chdir(user->pw_dir) < 0)
	{
		printf("\nFailed to switch home directories to %s.\n", user->pw_dir);
		perror("chdir");
		reset_terminal();
		return 1;
	}

	char *args[] = {NULL, NULL};
	/* The first character of argv[0] needs to be -, in order to be a login shell */
	args[0] = (char *) malloc(strlen(user->pw_shell) + 2);
	if(!args[0])
	{
		perror("login");
		reset_terminal();
		return 1;
	}
	memset(args[0], 0, strlen(user->pw_shell) + 2);
	strcat(args[0], "-");
	strcat(args[0], user->pw_shell);

	reset_terminal();

	printf("\n");

	if(execv(user->pw_shell, args) < 0)
	{
		perror("exec");
		return 1;
	}

	return 0;
}
<commit_msg>login: Rename terribly-named function.<commit_after>/*
* Copyright (c) 2017-2019 Pedro Falcato
* This file is part of Onyx, and is released under the terms of the MIT License
* check LICENSE at the root directory for more information
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <string>
#include <shadow.h>
#include <pwd.h>

#include <sys/syscall.h>

char *program_name = NULL;

/* Set the uid and gid */
void switch_users(gid_t gid, uid_t uid)
{
	syscall(SYS_setuid, uid);
	syscall(SYS_setgid, gid);
}

static struct termios old_termios;

int hide_stdin(void)
{
	struct termios attr;
	tcgetattr(STDIN_FILENO, &attr);
	memcpy(&old_termios, &attr, sizeof(struct termios));
	attr.c_lflag &= ~ECHO; /* Clear ECHO */
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr);

	return 0;
}

int reset_terminal(void)
{
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_termios);
	return 0;
}

#define TEMP_BUF_SIZE		1024
int get_input(std::string& str)
{
	char *buf = (char *) malloc(TEMP_BUF_SIZE);
	if(!buf)
		return -1;
	bzero(buf, TEMP_BUF_SIZE);
	bool should_stop = false;
	while(!should_stop && fgets(buf, TEMP_BUF_SIZE, stdin))
	{
		char *pos;
		if((pos = strchr(buf, '\n')))
    	{
			should_stop = true;
			*pos = '\0';
		}

		str += buf;
	}

	/* TODO: Replace bzero with explicit_bzero */
	bzero(buf, TEMP_BUF_SIZE);
	free(buf);

	return 0;
}

bool compare_passwords(struct spwd *spwd, std::string& password)
{
	/* Hash format: $algorithm$salt$hash */
	std::string password_hash(spwd->sp_pwdp);

	std::size_t algo_pos = password_hash.find('$');
	auto salt_pos = password_hash.find('$', algo_pos + 1);
	auto hash_pos = password_hash.find('$', salt_pos + 1);
	if(algo_pos == std::string::npos || salt_pos == std::string::npos || hash_pos == std::string::npos)
	{
		printf("Malformed shadow file.\n");
		return false;
	}

	std::string salt;
	salt.assign(password_hash, algo_pos, hash_pos - algo_pos);

	const char *resulting_hash = crypt(password.c_str(), salt.c_str());

	if(!strcmp(password_hash.c_str(), resulting_hash))
		return true;
	return false;
}

int main(int argc, char **argv, char **envp)
{
	(void) argc;
	(void) envp;
	program_name = argv[0];
	printf("%s: ", argv[0]);
	fflush(stdout);
	struct passwd *user;

	while(true)
	{
		std::string username;
		std::string password;

		printf("username:");
		fflush(stdout);

		if(get_input(username) < 0)
		{
			perror("get_input");
			return 1;
		}

		printf("password:");
		fflush(stdout);

		hide_stdin();

		if(get_input(password) < 0)
		{
			reset_terminal();
			perror("get_input");
			return 1;
		}

		user = getpwnam(username.c_str());
		if(!user)
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		if(!user->pw_name[0])
			break;

		if(user->pw_name[0] == '!' || user->pw_name[0] == '*')
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		auto pass_ent = getspnam(username.c_str());
		if(!pass_ent)
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		if(!compare_passwords(pass_ent, password))
		{
			reset_terminal();
			printf("\nLogin invalid. Try again\n");
			continue;
		}

		break;
	}

	switch_users(user->pw_gid, user->pw_uid);
	/* Set $USER */
	setenv("USER", user->pw_name, 1);
	/* Set $LOGNAME */
	setenv("LOGNAME", user->pw_name, 1);
	/* Set $HOME */
	setenv("HOME", user->pw_dir, 1);
	/* Set $SHELL */
	setenv("SHELL", user->pw_shell, 1);

	if(chdir(user->pw_dir) < 0)
	{
		printf("\nFailed to switch home directories to %s.\n", user->pw_dir);
		perror("chdir");
		reset_terminal();
		return 1;
	}

	char *args[] = {NULL, NULL};
	/* The first character of argv[0] needs to be -, in order to be a login shell */
	args[0] = (char *) malloc(strlen(user->pw_shell) + 2);
	if(!args[0])
	{
		perror("login");
		reset_terminal();
		return 1;
	}
	memset(args[0], 0, strlen(user->pw_shell) + 2);
	strcat(args[0], "-");
	strcat(args[0], user->pw_shell);

	reset_terminal();

	printf("\n");

	if(execv(user->pw_shell, args) < 0)
	{
		perror("exec");
		return 1;
	}

	return 0;
}
<|endoftext|>


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

#include "riegeli/base/base.h"

#include <stddef.h>
#include <stdint.h>

#include <cstring>
#include <exception>
#include <iostream>
#include <new>
#include <sstream>
#include <string>

#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"

namespace riegeli {

namespace internal {

CheckFailed::CheckFailed(const char* file, int line, const char* function,
                         const char* message) {
  stream_ << "Check failed at " << file << ":" << line << " in " << function
          << ": " << message << " ";
}

CheckFailed::~CheckFailed() {
  std::cerr << stream_.str() << std::endl;
  std::terminate();
}

}  // namespace internal

void ResizeStringAmortized(std::string& dest, size_t new_size) {
  if (new_size > dest.capacity()) {
    dest.reserve(UnsignedMax(
        new_size,
        UnsignedMin(dest.capacity() + dest.capacity() / 2, dest.max_size())));
  }
  dest.resize(new_size);
}

void CopyCordToArray(const absl::Cord& src, char* dest) {
  char* dest = cursor();
  for (const absl::string_view fragment : src.Chunks()) {
    std::memcpy(dest, fragment.data(), fragment.size());
    dest += fragment.size();
  }
}

void AppendCordToString(const absl::Cord& src, std::string& dest) {
  const size_t old_size = dest.size();
  ResizeStringAmortized(dest, old_size + src.size());
  CopyCordToArray(src, &dest[old_size]);
}

absl::Cord MakeBlockyCord(absl::string_view src) {
  // `absl::cord_internal::kMaxFlatLength`.
  static constexpr size_t kMaxFlatLength =
      4096 - (sizeof(size_t) + sizeof(int32_t) + sizeof(uint8_t));
  if (src.size() <= kMaxFlatLength) {
    // `absl::Cord(absl::string_view)` allocates a single node of that length.
    return absl::Cord(src);
  }
  char* const ptr = static_cast<char*>(operator new(src.size()));
  std::memcpy(ptr, src.data(), src.size());
  return absl::MakeCordFromExternal(
      absl::string_view(ptr, src.size()), [](absl::string_view data) {
#if __cpp_sized_deallocation || __GXX_DELETE_WITH_SIZE__
        operator delete(const_cast<char*>(data.data()), data.size());
#else
        operator delete(const_cast<char*>(data.data()));
#endif
      });
}

void AppendToBlockyCord(absl::string_view src, absl::Cord& dest) {
  // `absl::cord_internal::kMaxFlatLength`.
  static constexpr size_t kMaxFlatLength =
      4096 - (sizeof(size_t) + sizeof(int32_t) + sizeof(uint8_t));
  if (src.size() <= kMaxFlatLength) {
    // `absl::Cord::Append(absl::string_view)` can allocate a single node of
    // that length.
    dest.Append(src);
    return;
  }
  dest.Append(MakeBlockyCord(src));
}

void PrependToBlockyCord(absl::string_view src, absl::Cord& dest) {
  // `absl::cord_internal::kMaxFlatLength`.
  static constexpr size_t kMaxFlatLength =
      4096 - (sizeof(size_t) + sizeof(int32_t) + sizeof(uint8_t));
  if (src.size() <= kMaxFlatLength) {
    // `absl::Cord::Prepend(absl::string_view)` can allocate a single node of
    // that length.
    dest.Prepend(src);
    return;
  }
  dest.Prepend(MakeBlockyCord(src));
}

}  // namespace riegeli
<commit_msg>Fix open source build.<commit_after>// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "riegeli/base/base.h"

#include <stddef.h>
#include <stdint.h>

#include <cstring>
#include <exception>
#include <iostream>
#include <new>
#include <sstream>
#include <string>

#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"

namespace riegeli {

namespace internal {

CheckFailed::CheckFailed(const char* file, int line, const char* function,
                         const char* message) {
  stream_ << "Check failed at " << file << ":" << line << " in " << function
          << ": " << message << " ";
}

CheckFailed::~CheckFailed() {
  std::cerr << stream_.str() << std::endl;
  std::terminate();
}

}  // namespace internal

void ResizeStringAmortized(std::string& dest, size_t new_size) {
  if (new_size > dest.capacity()) {
    dest.reserve(UnsignedMax(
        new_size,
        UnsignedMin(dest.capacity() + dest.capacity() / 2, dest.max_size())));
  }
  dest.resize(new_size);
}

void CopyCordToArray(const absl::Cord& src, char* dest) {
  for (const absl::string_view fragment : src.Chunks()) {
    std::memcpy(dest, fragment.data(), fragment.size());
    dest += fragment.size();
  }
}

void AppendCordToString(const absl::Cord& src, std::string& dest) {
  const size_t old_size = dest.size();
  ResizeStringAmortized(dest, old_size + src.size());
  CopyCordToArray(src, &dest[old_size]);
}

absl::Cord MakeBlockyCord(absl::string_view src) {
  // `absl::cord_internal::kMaxFlatLength`.
  static constexpr size_t kMaxFlatLength =
      4096 - (sizeof(size_t) + sizeof(int32_t) + sizeof(uint8_t));
  if (src.size() <= kMaxFlatLength) {
    // `absl::Cord(absl::string_view)` allocates a single node of that length.
    return absl::Cord(src);
  }
  char* const ptr = static_cast<char*>(operator new(src.size()));
  std::memcpy(ptr, src.data(), src.size());
  return absl::MakeCordFromExternal(
      absl::string_view(ptr, src.size()), [](absl::string_view data) {
#if __cpp_sized_deallocation || __GXX_DELETE_WITH_SIZE__
        operator delete(const_cast<char*>(data.data()), data.size());
#else
        operator delete(const_cast<char*>(data.data()));
#endif
      });
}

void AppendToBlockyCord(absl::string_view src, absl::Cord& dest) {
  // `absl::cord_internal::kMaxFlatLength`.
  static constexpr size_t kMaxFlatLength =
      4096 - (sizeof(size_t) + sizeof(int32_t) + sizeof(uint8_t));
  if (src.size() <= kMaxFlatLength) {
    // `absl::Cord::Append(absl::string_view)` can allocate a single node of
    // that length.
    dest.Append(src);
    return;
  }
  dest.Append(MakeBlockyCord(src));
}

void PrependToBlockyCord(absl::string_view src, absl::Cord& dest) {
  // `absl::cord_internal::kMaxFlatLength`.
  static constexpr size_t kMaxFlatLength =
      4096 - (sizeof(size_t) + sizeof(int32_t) + sizeof(uint8_t));
  if (src.size() <= kMaxFlatLength) {
    // `absl::Cord::Prepend(absl::string_view)` can allocate a single node of
    // that length.
    dest.Prepend(src);
    return;
  }
  dest.Prepend(MakeBlockyCord(src));
}

}  // namespace riegeli
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE ScopeReader
#define BOOST_TEST_LOG_LEVEL message
#include <cstddef>
#include <functional>
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include "../JPetManager/JPetManager.h"

#include "JPetScopeReaderFixtures.h"
#include "../JPetScopeReader/JPetScopeReader.h"

BOOST_AUTO_TEST_SUITE (JPetScopeReaderTestSuite)
BOOST_AUTO_TEST_CASE (generate_root_file) {

  int   _argc    = 5;
  char* _argv[6];
        _argv[0] = const_cast<char*>("JPetScopeReaderTest.exe");
        _argv[1] = const_cast<char*>("-t");
        _argv[2] = const_cast<char*>("scope");
        _argv[3] = const_cast<char*>("-f");
        _argv[4] = const_cast<char*>("unitTestData/JPetScopeReaderTest/test_file.json");
	_argv[5] = (char*)(NULL);

  JPetManager& manager = JPetManager::getManager();
  manager.parseCmdLine(_argc, _argv);
  manager.run();
  BOOST_REQUIRE_MESSAGE(boost::filesystem::exists(gTest_root_filename), "File " << gTest_root_filename << " does not exist.");
}
BOOST_FIXTURE_TEST_CASE (signal_generation_test, signal_generation_fixture) {

  check_header(
    [] (int osc_file_size, int reco_signal_size) -> void {
      BOOST_REQUIRE_EQUAL(osc_file_size, reco_signal_size);
    }
  );

  check_data(
    [] (float osc_file_time, float reco_signal_time, float osc_file_ampl, float reco_signal_ampl) -> void {
      BOOST_CHECK_CLOSE_FRACTION(osc_file_time, reco_signal_time, 1.f / 131072.f);
      BOOST_CHECK_CLOSE_FRACTION(osc_file_ampl, reco_signal_ampl, 1.f / 131072.f);
    }
  );
}
BOOST_FIXTURE_TEST_CASE (tref_correctness_test, tref_correctness_fixture) {

  check_tref_simple(
    [] (const void* tref_pointer) -> void {
      BOOST_CHECK_PREDICATE(std::not_equal_to <size_t> (), ((size_t) tref_pointer)((size_t) nullptr));
    }
  );
  //check_tref_simple(nullptr);
}

BOOST_AUTO_TEST_CASE (getFilePrefix)
{
  JPetScopeReader reader(0);
  BOOST_REQUIRE(reader.getFilePrefix("").empty());
  BOOST_REQUIRE(reader.getFilePrefix("abkabd").empty());
  BOOST_REQUIRE(reader.getFilePrefix("jfsd808").empty());
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("c1_0554.txt"), "c1");
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("c098_0554.txt"), "c098");
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("cq_"), "cq");
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("a_ss_q"), "a");
}

BOOST_AUTO_TEST_CASE (createInputScopeFileNames)
{
  JPetScopeReader reader(0);
  BOOST_REQUIRE(reader.createInputScopeFileNames("", {}).empty());
  BOOST_REQUIRE(reader.createInputScopeFileNames("non_existing", {}).empty());
  BOOST_REQUIRE(!reader.createInputScopeFileNames("unitTestData/JPetScopeReaderTest/scope_files/0", {{"c1",0}, {"c2",1}, {"c3", 2}, {"c4",3}}).empty());
  std::map<int, std::vector<string>>  expectedRes {
    {0, {"C1_00003.txt","C1_00004.txt"}}, {1, {"C2_00003.txt","C2_00004.txt"}},
    {2, {"C3_00003.txt","C3_00004.txt"}}, {3, {"C4_00003.txt","C4_00004.txt"}}
  };
  std::string pathToFiles = "unitTestData/JPetScopeReaderTest/scope_files/0";
  std::for_each(expectedRes.begin(), expectedRes.end(),
                [&](std::pair<const int, std::vector<std::string> >&  el) {
                      for_each(el.second.begin(), el.second.end(),
                      [&](std::string& name) {
                        name = pathToFiles + "/" + name;
                      });
                      std::sort(el.second.begin(), el.second.end());
                });
  std::map<int, std::vector<std::string> > obtainedRes = reader.createInputScopeFileNames(pathToFiles, {{"C1",0}, {"C2",1}, {"C3", 2}, {"C4",3}});
  /// to assure the same order of elements for comparison
  std::for_each(obtainedRes.begin(), obtainedRes.end(),
                [&](std::pair<const int, std::vector<std::string> >&  el) {
                      std::sort(el.second.begin(), el.second.end());
                });
  BOOST_REQUIRE(!obtainedRes.empty());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[0].begin(), obtainedRes[0].end(), expectedRes[0].begin(), expectedRes[0].end());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[1].begin(), obtainedRes[1].end(), expectedRes[1].begin(), expectedRes[1].end());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[2].begin(), obtainedRes[2].end(), expectedRes[2].begin(), expectedRes[2].end());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[3].begin(), obtainedRes[3].end(), expectedRes[3].begin(), expectedRes[3].end());
}

BOOST_AUTO_TEST_CASE (isCorrectScopeFileName)
{
  JPetScopeReader reader(0);
  BOOST_REQUIRE(!reader.isCorrectScopeFileName(""));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("C1_004.gif"));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("C1004.txt"));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("004.txt"));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("C5_abc.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("C1_023.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("C5_000.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("AA_004.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("AA_004.txt"));
}

BOOST_AUTO_TEST_CASE (FullTest)
{
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Modify the generation of command line arguments in JPetScopeReaderTest<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE ScopeReader
#define BOOST_TEST_LOG_LEVEL message
#include <cstddef>
#include <functional>
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
#include "../JPetManager/JPetManager.h"

#include "JPetScopeReaderFixtures.h"
#include "../JPetScopeReader/JPetScopeReader.h"

char* convertStringToCharP(const std::string& s)
{
  char* pc = new char[s.size() + 1];
  std::strcpy(pc, s.c_str());
  return pc;
}

std::vector<char*> createArgs(const std::string& commandLine)
{
  std::istringstream iss(commandLine);
  std::vector<std::string> args {std::istream_iterator<std::string>{iss},
                                 std::istream_iterator<std::string>{}
                                };
  std::vector<char*> args_char;
  std::transform(args.begin(), args.end(), std::back_inserter(args_char), convertStringToCharP);
  return args_char;
}

BOOST_AUTO_TEST_SUITE (JPetScopeReaderTestSuite)
BOOST_AUTO_TEST_CASE (generate_root_file) {

  auto commandLine = "main.exe  -t scope -f unitTestData/JPetScopeReaderTest/test_file.json";
  auto args_char = createArgs(commandLine);
  auto argc = args_char.size();
  auto argv = args_char.data();

  JPetManager& manager = JPetManager::getManager();
  manager.parseCmdLine(argc, argv);
  manager.run();
  BOOST_REQUIRE_MESSAGE(boost::filesystem::exists(gTest_root_filename), "File " << gTest_root_filename << " does not exist.");
}
BOOST_FIXTURE_TEST_CASE (signal_generation_test, signal_generation_fixture) {

  check_header(
    [] (int osc_file_size, int reco_signal_size) -> void {
      BOOST_REQUIRE_EQUAL(osc_file_size, reco_signal_size);
    }
  );

  check_data(
    [] (float osc_file_time, float reco_signal_time, float osc_file_ampl, float reco_signal_ampl) -> void {
      BOOST_CHECK_CLOSE_FRACTION(osc_file_time, reco_signal_time, 1.f / 131072.f);
      BOOST_CHECK_CLOSE_FRACTION(osc_file_ampl, reco_signal_ampl, 1.f / 131072.f);
    }
  );
}
BOOST_FIXTURE_TEST_CASE (tref_correctness_test, tref_correctness_fixture) {

  check_tref_simple(
    [] (const void* tref_pointer) -> void {
      BOOST_CHECK_PREDICATE(std::not_equal_to <size_t> (), ((size_t) tref_pointer)((size_t) nullptr));
    }
  );
  //check_tref_simple(nullptr);
}

BOOST_AUTO_TEST_CASE (getFilePrefix)
{
  JPetScopeReader reader(0);
  BOOST_REQUIRE(reader.getFilePrefix("").empty());
  BOOST_REQUIRE(reader.getFilePrefix("abkabd").empty());
  BOOST_REQUIRE(reader.getFilePrefix("jfsd808").empty());
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("c1_0554.txt"), "c1");
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("c098_0554.txt"), "c098");
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("cq_"), "cq");
  BOOST_REQUIRE_EQUAL(reader.getFilePrefix("a_ss_q"), "a");
}

BOOST_AUTO_TEST_CASE (createInputScopeFileNames)
{
  JPetScopeReader reader(0);
  BOOST_REQUIRE(reader.createInputScopeFileNames("", {}).empty());
  BOOST_REQUIRE(reader.createInputScopeFileNames("non_existing", {}).empty());
  BOOST_REQUIRE(!reader.createInputScopeFileNames("unitTestData/JPetScopeReaderTest/scope_files/0", {{"c1",0}, {"c2",1}, {"c3", 2}, {"c4",3}}).empty());
  std::map<int, std::vector<string>>  expectedRes {
    {0, {"C1_00003.txt","C1_00004.txt"}}, {1, {"C2_00003.txt","C2_00004.txt"}},
    {2, {"C3_00003.txt","C3_00004.txt"}}, {3, {"C4_00003.txt","C4_00004.txt"}}
  };
  std::string pathToFiles = "unitTestData/JPetScopeReaderTest/scope_files/0";
  std::for_each(expectedRes.begin(), expectedRes.end(),
                [&](std::pair<const int, std::vector<std::string> >&  el) {
                      for_each(el.second.begin(), el.second.end(),
                      [&](std::string& name) {
                        name = pathToFiles + "/" + name;
                      });
                      std::sort(el.second.begin(), el.second.end());
                });
  std::map<int, std::vector<std::string> > obtainedRes = reader.createInputScopeFileNames(pathToFiles, {{"C1",0}, {"C2",1}, {"C3", 2}, {"C4",3}});
  /// to assure the same order of elements for comparison
  std::for_each(obtainedRes.begin(), obtainedRes.end(),
                [&](std::pair<const int, std::vector<std::string> >&  el) {
                      std::sort(el.second.begin(), el.second.end());
                });
  BOOST_REQUIRE(!obtainedRes.empty());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[0].begin(), obtainedRes[0].end(), expectedRes[0].begin(), expectedRes[0].end());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[1].begin(), obtainedRes[1].end(), expectedRes[1].begin(), expectedRes[1].end());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[2].begin(), obtainedRes[2].end(), expectedRes[2].begin(), expectedRes[2].end());
  BOOST_REQUIRE_EQUAL_COLLECTIONS(obtainedRes[3].begin(), obtainedRes[3].end(), expectedRes[3].begin(), expectedRes[3].end());
}

BOOST_AUTO_TEST_CASE (isCorrectScopeFileName)
{
  JPetScopeReader reader(0);
  BOOST_REQUIRE(!reader.isCorrectScopeFileName(""));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("C1_004.gif"));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("C1004.txt"));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("004.txt"));
  BOOST_REQUIRE(!reader.isCorrectScopeFileName("C5_abc.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("C1_023.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("C5_000.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("AA_004.txt"));
  BOOST_REQUIRE(reader.isCorrectScopeFileName("AA_004.txt"));
}

BOOST_AUTO_TEST_CASE (FullTest)
{
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "webkit/glue/resource_fetcher.h"

#include "base/compiler_specific.h"

MSVC_PUSH_WARNING_LEVEL(0);
#include "FrameLoader.h"
#include "ResourceHandle.h"
#include "ResourceRequest.h"
MSVC_POP_WARNING();

#undef LOG
#include "base/logging.h"
#include "webkit/glue/glue_util.h"
#include "net/url_request/url_request_status.h"

using WebCore::ResourceError;
using WebCore::ResourceHandle;
using WebCore::ResourceResponse;

ResourceFetcher::ResourceFetcher(const GURL& url, WebCore::Frame* frame,
                                 Delegate* d)
    : url_(url), delegate_(d), completed_(false) {
  // Can't do anything without a frame.  However, delegate can be NULL (so we
  // can do a http request and ignore the results).
  DCHECK(frame);
  Start(frame);
}

ResourceFetcher::~ResourceFetcher() {
  if (!completed_)
    loader_->cancel();
  loader_ = NULL;
}

void ResourceFetcher::Cancel() {
  if (!completed_) {
    loader_->cancel();
    completed_ = true;
  }
}

void ResourceFetcher::Start(WebCore::Frame* frame) {
  WebCore::FrameLoader* frame_loader = frame->loader();
  if (!frame_loader) {
    // We put this on a 0 timer so the callback happens async (consistent with
    // regular fetches).
    start_failed_timer_.reset(new StartFailedTimer(this,
          &ResourceFetcher::StartFailed));
    start_failed_timer_->startOneShot(0);
    return;
  }

  WebCore::ResourceRequest request(webkit_glue::GURLToKURL(url_));
  request.setFrame(frame);

  loader_ = ResourceHandle::create(request, this, NULL, false, false);
}

void ResourceFetcher::StartFailed(StartFailedTimer* timer) {
  didFail(NULL, ResourceError());
}

/////////////////////////////////////////////////////////////////////////////
// ResourceHandleClient methods
void ResourceFetcher::didReceiveResponse(ResourceHandle* resource_handle,
                                         const ResourceResponse& response) {
  ASSERT(!completed_);
  // It's safe to use the ResourceResponse copy constructor
  // (xmlhttprequest.cpp uses it).
  response_ = response;
}

void ResourceFetcher::didReceiveData(ResourceHandle* resource_handle,
                                     const char* data, int length,
                                     int total_length) {
  ASSERT(!completed_);
  if (length <= 0)
    return;

  data_.append(data, length);
}

void ResourceFetcher::didFinishLoading(ResourceHandle* resource_handle) {
  ASSERT(!completed_);
  completed_ = true;

  if (delegate_)
    delegate_->OnURLFetchComplete(response_, data_);
}

void ResourceFetcher::didFail(ResourceHandle* resource_handle,
                              const ResourceError& error) {
  ASSERT(!completed_);
  completed_ = true;

  // Go ahead and tell our delegate that we're done.  Send an empty
  // ResourceResponse and string.
  if (delegate_)
    delegate_->OnURLFetchComplete(ResourceResponse(), std::string());
}

/////////////////////////////////////////////////////////////////////////////
// A resource fetcher with a timeout

ResourceFetcherWithTimeout::ResourceFetcherWithTimeout(
    const GURL& url, WebCore::Frame* frame, double timeout_secs, Delegate* d)
    : ResourceFetcher(url, frame, d) {
  timeout_timer_.reset(new FetchTimer(this,
      &ResourceFetcherWithTimeout::TimeoutFired));
  timeout_timer_->startOneShot(timeout_secs);
}

void ResourceFetcherWithTimeout::TimeoutFired(FetchTimer* timer) {
  if (!completed_) {
    loader_->cancel();
    didFail(NULL, ResourceError());
  }
}

<commit_msg>As described in the bug comments, there is a small hole which makes it possible for this object to be destroyed before it has been fully initialized. So we must protect against that.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "webkit/glue/resource_fetcher.h"

#include "base/compiler_specific.h"

MSVC_PUSH_WARNING_LEVEL(0);
#include "FrameLoader.h"
#include "ResourceHandle.h"
#include "ResourceRequest.h"
MSVC_POP_WARNING();

#undef LOG
#include "base/logging.h"
#include "webkit/glue/glue_util.h"
#include "net/url_request/url_request_status.h"

using WebCore::ResourceError;
using WebCore::ResourceHandle;
using WebCore::ResourceResponse;

ResourceFetcher::ResourceFetcher(const GURL& url, WebCore::Frame* frame,
                                 Delegate* d)
    : url_(url), delegate_(d), completed_(false) {
  // Can't do anything without a frame.  However, delegate can be NULL (so we
  // can do a http request and ignore the results).
  DCHECK(frame);
  Start(frame);
}

ResourceFetcher::~ResourceFetcher() {
  if (!completed_ && loader_.get())
    loader_->cancel();
  loader_ = NULL;
}

void ResourceFetcher::Cancel() {
  if (!completed_) {
    loader_->cancel();
    completed_ = true;
  }
}

void ResourceFetcher::Start(WebCore::Frame* frame) {
  WebCore::FrameLoader* frame_loader = frame->loader();
  if (!frame_loader) {
    // We put this on a 0 timer so the callback happens async (consistent with
    // regular fetches).
    start_failed_timer_.reset(new StartFailedTimer(this,
          &ResourceFetcher::StartFailed));
    start_failed_timer_->startOneShot(0);
    return;
  }

  WebCore::ResourceRequest request(webkit_glue::GURLToKURL(url_));
  request.setFrame(frame);

  loader_ = ResourceHandle::create(request, this, NULL, false, false);
}

void ResourceFetcher::StartFailed(StartFailedTimer* timer) {
  didFail(NULL, ResourceError());
}

/////////////////////////////////////////////////////////////////////////////
// ResourceHandleClient methods
void ResourceFetcher::didReceiveResponse(ResourceHandle* resource_handle,
                                         const ResourceResponse& response) {
  ASSERT(!completed_);
  // It's safe to use the ResourceResponse copy constructor
  // (xmlhttprequest.cpp uses it).
  response_ = response;
}

void ResourceFetcher::didReceiveData(ResourceHandle* resource_handle,
                                     const char* data, int length,
                                     int total_length) {
  ASSERT(!completed_);
  if (length <= 0)
    return;

  data_.append(data, length);
}

void ResourceFetcher::didFinishLoading(ResourceHandle* resource_handle) {
  ASSERT(!completed_);
  completed_ = true;

  if (delegate_)
    delegate_->OnURLFetchComplete(response_, data_);
}

void ResourceFetcher::didFail(ResourceHandle* resource_handle,
                              const ResourceError& error) {
  ASSERT(!completed_);
  completed_ = true;

  // Go ahead and tell our delegate that we're done.  Send an empty
  // ResourceResponse and string.
  if (delegate_)
    delegate_->OnURLFetchComplete(ResourceResponse(), std::string());
}

/////////////////////////////////////////////////////////////////////////////
// A resource fetcher with a timeout

ResourceFetcherWithTimeout::ResourceFetcherWithTimeout(
    const GURL& url, WebCore::Frame* frame, double timeout_secs, Delegate* d)
    : ResourceFetcher(url, frame, d) {
  timeout_timer_.reset(new FetchTimer(this,
      &ResourceFetcherWithTimeout::TimeoutFired));
  timeout_timer_->startOneShot(timeout_secs);
}

void ResourceFetcherWithTimeout::TimeoutFired(FetchTimer* timer) {
  if (!completed_) {
    loader_->cancel();
    didFail(NULL, ResourceError());
  }
}

<|endoftext|>


<commit_before><commit_msg>multithread the conversion to RGB10_A2<commit_after><|endoftext|>


<commit_before>#include "CancelableThreadPool.h"
#include "utils/Log.h"
#include "utils/ThreadUtils.h"

#include "core/MapPos.h"

namespace carto {

    CancelableThreadPool::CancelableThreadPool() :
        _poolSize(0),
        _taskCount(0),
        _stop(false),
        _taskRecords(),
        _workers(),
        _threads(),
        _mutex()
    {
    }

    CancelableThreadPool::~CancelableThreadPool() {
    }

    void CancelableThreadPool::deinit() {
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _stop = true;
        }

        cancelAll();

        {
            std::lock_guard<std::mutex> lock(_mutex);
            _condition.notify_all();
        }

        for (const std::shared_ptr<std::thread>& thread : _threads) {
            thread->detach();
        }

        _workers.clear();
        _threads.clear();
    }

    int CancelableThreadPool::getPoolSize() const {
        std::lock_guard<std::mutex> lock(_mutex);
        return _poolSize;
    }

    void CancelableThreadPool::setPoolSize(int poolSize) {
        std::lock_guard<std::mutex> lock(_mutex);

        if (_stop) {
            return;
        }

        // Add threads
        for (int i = _poolSize; i < poolSize; i++) {
            _workers.push_back(std::make_shared<TaskWorker>(shared_from_this()));
            _threads.push_back(std::make_shared<std::thread>(&TaskWorker::operator(), _workers.back()));
        }

        _poolSize = poolSize;
    }

    void CancelableThreadPool::execute(std::shared_ptr<CancelableTask> task) {
        execute(task, DEFAULT_PRIORITY);
    }

    void CancelableThreadPool::execute(std::shared_ptr<CancelableTask> task, int priority) {
        if (!task->isCanceled()) {
            std::lock_guard<std::mutex> lock(_mutex);

            if (_stop) {
                return;
            }

            // Push task to queue, increase global task count
            _taskRecords.push(TaskRecord(task, priority, _taskCount));
            _taskCount++;

            // If there are any waiting threads, notify one of them
            _condition.notify_one();
        }
    }

    void CancelableThreadPool::cancelAll() {
        std::lock_guard<std::mutex> lock(_mutex);

        std::size_t taskRecordsSize = _taskRecords.size();
        for (std::size_t i = 0; i < taskRecordsSize; i++) {
            const std::shared_ptr<CancelableTask>& task = _taskRecords.top()._task;
            task->cancel();
            _taskRecords.pop();
        }
    }

    CancelableThreadPool::TaskRecord::TaskRecord(std::shared_ptr<CancelableTask> task, int priority, long long sequence) :
        _task(task),
        _priority(priority),
        _sequence(sequence)
    {
    }

    bool CancelableThreadPool::TaskRecord::operator <(const TaskRecord& taskRecord) const {
        // Tasks are sorted according to their priority and then their sequence
        if (_priority != taskRecord._priority) {
            return _priority < taskRecord._priority;
        }
        return _sequence > taskRecord._sequence;
    }

    CancelableThreadPool::TaskWorker::TaskWorker(const std::shared_ptr<CancelableThreadPool>& threadPool) :
        _threadPool(threadPool) {
    }

    void CancelableThreadPool::TaskWorker::operator ()() {
        ThreadUtils::SetThreadPriority(ThreadPriority::MINIMUM);
        while (true) {
            auto threadPool = _threadPool.lock();
            if (!threadPool) {
                return;
            }

            // If there are no tasks, wait until notified or exit thread if interrupted
            {
                std::unique_lock<std::mutex> lock(threadPool->_mutex);
                if (threadPool->_stop) {
                    return;
                }

                if (threadPool->_taskRecords.size() == 0) {
                    threadPool->_condition.wait(lock);
                }
            }

            // Request another task, execute it if it's not null
            while (true) {
                {
                    std::lock_guard<std::mutex> lock(threadPool->_mutex);
                    if (threadPool->_stop) {
                        return;
                    }
                }

                std::shared_ptr<CancelableTask> task = threadPool->getNextTask();
                if (task) {
                    task->operator ()();
                } else {
                    break;
                }

                if (threadPool->shouldTerminateWorker(*this)) {
                    return;
                }

                // Check for interruption
                std::this_thread::yield();
            }
        }
    }

    std::shared_ptr<CancelableTask> CancelableThreadPool::getNextTask() {
        std::lock_guard<std::mutex> lock(_mutex);

        // Return the next highest priority task from the task queue
        std::shared_ptr<CancelableTask> task;
        if (_taskRecords.size() > 0) {
            task = _taskRecords.top()._task;
            _taskRecords.pop();
        }
        return task;
    }

    bool CancelableThreadPool::shouldTerminateWorker(TaskWorker& worker) {
        std::lock_guard<std::mutex> lock(_mutex);

        if (_stop) {
            return true;
        }

        // If there are too many threads, remove this worker and it's thread
        if (static_cast<int>(_threads.size()) > _poolSize) {

            // Find the index of the finished worker, it's thread will have the same index in _threads vector
            int index = 0;
            WorkerList::iterator it;
            for (it = _workers.begin(); it != _workers.end(); ++it) {
                const std::shared_ptr<TaskWorker>& listWorker = *it;
                if (listWorker.get() == &worker) {
                    // Remove thread and worker
                    _workers.erase(it);
                    _threads.erase(_threads.begin() + index);
                    break;
                }
                index++;
            }

            return true;
        }

        return false;
    }

    const int CancelableThreadPool::DEFAULT_PRIORITY = 0;

}
<commit_msg>Fix potential native crash when thread pool is downsized<commit_after>#include "CancelableThreadPool.h"
#include "utils/Log.h"
#include "utils/ThreadUtils.h"

#include "core/MapPos.h"

namespace carto {

    CancelableThreadPool::CancelableThreadPool() :
        _poolSize(0),
        _taskCount(0),
        _stop(false),
        _taskRecords(),
        _workers(),
        _threads(),
        _mutex()
    {
    }

    CancelableThreadPool::~CancelableThreadPool() {
    }

    void CancelableThreadPool::deinit() {
        {
            std::lock_guard<std::mutex> lock(_mutex);
            _stop = true;
        }

        cancelAll();

        {
            std::lock_guard<std::mutex> lock(_mutex);
            _condition.notify_all();
        }

        for (const std::shared_ptr<std::thread>& thread : _threads) {
            thread->detach();
        }

        _workers.clear();
        _threads.clear();
    }

    int CancelableThreadPool::getPoolSize() const {
        std::lock_guard<std::mutex> lock(_mutex);
        return _poolSize;
    }

    void CancelableThreadPool::setPoolSize(int poolSize) {
        std::lock_guard<std::mutex> lock(_mutex);

        if (_stop) {
            return;
        }

        // Add threads
        for (int i = _poolSize; i < poolSize; i++) {
            _workers.push_back(std::make_shared<TaskWorker>(shared_from_this()));
            _threads.push_back(std::make_shared<std::thread>(&TaskWorker::operator(), _workers.back()));
        }

        _poolSize = poolSize;
    }

    void CancelableThreadPool::execute(std::shared_ptr<CancelableTask> task) {
        execute(task, DEFAULT_PRIORITY);
    }

    void CancelableThreadPool::execute(std::shared_ptr<CancelableTask> task, int priority) {
        if (!task->isCanceled()) {
            std::lock_guard<std::mutex> lock(_mutex);

            if (_stop) {
                return;
            }

            // Push task to queue, increase global task count
            _taskRecords.push(TaskRecord(task, priority, _taskCount));
            _taskCount++;

            // If there are any waiting threads, notify one of them
            _condition.notify_one();
        }
    }

    void CancelableThreadPool::cancelAll() {
        std::lock_guard<std::mutex> lock(_mutex);

        std::size_t taskRecordsSize = _taskRecords.size();
        for (std::size_t i = 0; i < taskRecordsSize; i++) {
            const std::shared_ptr<CancelableTask>& task = _taskRecords.top()._task;
            task->cancel();
            _taskRecords.pop();
        }
    }

    CancelableThreadPool::TaskRecord::TaskRecord(std::shared_ptr<CancelableTask> task, int priority, long long sequence) :
        _task(task),
        _priority(priority),
        _sequence(sequence)
    {
    }

    bool CancelableThreadPool::TaskRecord::operator <(const TaskRecord& taskRecord) const {
        // Tasks are sorted according to their priority and then their sequence
        if (_priority != taskRecord._priority) {
            return _priority < taskRecord._priority;
        }
        return _sequence > taskRecord._sequence;
    }

    CancelableThreadPool::TaskWorker::TaskWorker(const std::shared_ptr<CancelableThreadPool>& threadPool) :
        _threadPool(threadPool) {
    }

    void CancelableThreadPool::TaskWorker::operator ()() {
        ThreadUtils::SetThreadPriority(ThreadPriority::MINIMUM);
        while (true) {
            auto threadPool = _threadPool.lock();
            if (!threadPool) {
                return;
            }

            // If there are no tasks, wait until notified or exit thread if interrupted
            {
                std::unique_lock<std::mutex> lock(threadPool->_mutex);
                if (threadPool->_stop) {
                    return;
                }

                if (threadPool->_taskRecords.size() == 0) {
                    threadPool->_condition.wait(lock);
                }
            }

            // Request another task, execute it if it's not null
            while (true) {
                {
                    std::lock_guard<std::mutex> lock(threadPool->_mutex);
                    if (threadPool->_stop) {
                        return;
                    }
                }

                std::shared_ptr<CancelableTask> task = threadPool->getNextTask();
                if (task) {
                    task->operator ()();
                } else {
                    break;
                }

                if (threadPool->shouldTerminateWorker(*this)) {
                    return;
                }

                // Check for interruption
                std::this_thread::yield();
            }
        }
    }

    std::shared_ptr<CancelableTask> CancelableThreadPool::getNextTask() {
        std::lock_guard<std::mutex> lock(_mutex);

        // Return the next highest priority task from the task queue
        std::shared_ptr<CancelableTask> task;
        if (_taskRecords.size() > 0) {
            task = _taskRecords.top()._task;
            _taskRecords.pop();
        }
        return task;
    }

    bool CancelableThreadPool::shouldTerminateWorker(TaskWorker& worker) {
        std::lock_guard<std::mutex> lock(_mutex);

        if (_stop) {
            return true;
        }

        // If there are too many threads, remove this worker and it's thread
        if (static_cast<int>(_threads.size()) > _poolSize) {

            // Find the index of the finished worker, it's thread will have the same index in _threads vector
            int index = 0;
            WorkerList::iterator it;
            for (it = _workers.begin(); it != _workers.end(); ++it) {
                const std::shared_ptr<TaskWorker>& listWorker = *it;
                if (listWorker.get() == &worker) {
                    // Remove thread and worker
                    _workers.erase(it);
                    _threads.at(index)->detach();
                    _threads.erase(_threads.begin() + index);
                    break;
                }
                index++;
            }

            return true;
        }

        return false;
    }

    const int CancelableThreadPool::DEFAULT_PRIORITY = 0;

}
<|endoftext|>


<commit_before>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-09 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

/*
$begin optimize.cpp$$

$section ADFun Operation Sequence Optimization: Example and Test$$

$index optimize, operation sequence$$
$index operation, optimize sequence$$
$index sequence, optimize operation$$
$index test, optimize$$
$index example, optimize$$

$code
$verbatim%example/optimize.cpp%0%// BEGIN PROGRAM%// END PROGRAM%1%$$
$$

$end
*/
// BEGIN PROGRAM
# include <cppad/cppad.hpp>
namespace {
	template <class Float>
	Float fun(const Float& x)
	{	using CppAD::exp;

	 	// Create a variable that is optimized out because
	 	// it is only used in the comparision operation.
		Float a = 1. / x;

		// Create a variable that is used by the result
		Float b = x * 5.;

		Float c;
		if( a < x )
			c = b + 3.; // only one variable created by this choice
		else	c = b + 2.;

		// Create a variable that is optimized out because it
		// will always have the same value as b
		Float d = 5. * x;

		// Note that the operation sequence connects b, c, and d with y
		// (but a is not connected).
		Float y = c + d;

		return y;
	}
}

bool optimize(void)
{	bool ok = true;
	using CppAD::AD;

	// domain space vector
	size_t n  = 1;
	CPPAD_TEST_VECTOR< AD<double> > X(n);
	X[0]      = .5;

	// declare independent variables and start tape recording
	CppAD::Independent(X);

	// range space vector
	size_t m = 1;
	CPPAD_TEST_VECTOR< AD<double> > Y(m);
	Y[0] = fun(X[0]);

	// create f: X -> Y and stop tape recording
	CppAD::ADFun<double> F(X, Y);

	// Check the number of variables in original operation sequence:
	// BeginOp:  one phantom variable at beginning of operation sequence
	// X[0]:     the independent variable
	// a,b,c,d:  four temporary variables inside the function fun
	// y:        return value for the function fun and dependent variable
	ok &= (F.size_var() == 7);

	// Check zero order forward mode on the original operation sequence
	CPPAD_TEST_VECTOR<double> x(n), y(m), check(m);
	x[0] = Value(X[0]);
	y = F.Forward(0, x);
	ok &= y[0] == fun(x[0]);

	// Optimize the operation sequence
	F.optimize();

	// Check the number of variables in original operation sequence:
	// BeginOp: at the beginning of every operation sequence.
	// X[0]:    the independent variable.
	// b, c:    temporay variables in the function fun.
	// y:       return value for the function fun and dependent variable.
	ok &= (F.size_var() == 5);

	// Check result for a zero order calculation.
	// This has already been checked if NDEBUG is not defined.
	y = F.Forward(0, x);
	ok &= y[0] == fun(x[0]);
	return ok;
}

// END PROGRAM
<commit_msg>trunk: missing from previous commit<commit_after>/* $Id$ */
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-09 Bradley M. Bell

CppAD is distributed under multiple licenses. This distribution is under
the terms of the
                    Common Public License Version 1.0.

A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */

/*
$begin optimize.cpp$$

$section ADFun Operation Sequence Optimization: Example and Test$$

$index optimize, operation sequence$$
$index operation, optimize sequence$$
$index sequence, optimize operation$$
$index test, optimize$$
$index example, optimize$$

$code
$verbatim%example/optimize.cpp%0%// BEGIN PROGRAM%// END PROGRAM%1%$$
$$

$end
*/
// BEGIN PROGRAM
# include <cppad/cppad.hpp>
namespace {
	template <class Float>
	void fun(const Float& x, Float& y, size_t& n_var, size_t& n_opt)
	{	using CppAD::exp;

	 	// Create a variable that is optimized out because
	 	// it is only used in the comparision operation.
		Float a = 1. / x;
		n_var += 1;
		n_opt += 0;

		// Create a variable that is used by the result
		Float b = x * 5.;
		n_var += 1;
		n_opt += 1;

		Float c;
		if( a < x )
			c = b / 3.; // only one variable created by this choice
		else	c = b / 2.;
		n_var += 1;
		n_opt += 1;

		// Create a variable that is optimized out because it
		// will always have the same value as b
		Float d = 5. * x;
		n_var += 1;
		n_opt += 0;

		// Create three variables that will be converted to one
		// cumulative summation. Note that a is not connected to
		// the result y (in the operation sequence).
		y      = 1. + b + c + d;
		n_var += 3;
		n_opt += 1;
	}
}

bool optimize(void)
{	bool ok = true;
	using CppAD::AD;

	// domain space vector
	size_t n  = 1;
	CPPAD_TEST_VECTOR< AD<double> > X(n);
	X[0]      = .5;

	// declare independent variables and start tape recording
	CppAD::Independent(X);
	size_t n_var = 1 + n; // one phantom variable at the beginning
	size_t n_opt = 1 + n; // and one for each independent variable

	// range space vector
	size_t m = 1;
	CPPAD_TEST_VECTOR< AD<double> > Y(m);
	fun(X[0], Y[0], n_var, n_opt);

	// create f: X -> Y and stop tape recording
	CppAD::ADFun<double> F(X, Y);
	ok &= (F.size_var() == n_var);

	// Check zero order forward mode on the original operation sequence
	CPPAD_TEST_VECTOR<double> x(n), y(m);
	x[0] = Value(X[0]);
	size_t i = 0; // temporary variable (we do not use value)
	double check;
	fun(x[0], check, i, i);
	y   = F.Forward(0, x);
	ok &= (y[0] == check);

	// Optimize the operation sequence
	F.optimize();
	ok &= (F.size_var() == n_opt);

	// Check result for a zero order calculation.
	// This has already been checked if NDEBUG is not defined.
	fun(x[0], check, i, i);
	ok &= (y[0] == check);
	y   = F.Forward(0, x);
	return ok;
}

// END PROGRAM
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * 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) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "AcbfDocument.h"
#include "AcbfBody.h"
#include "AcbfMetadata.h"
#include "AcbfBookinfo.h"
#include "AcbfData.h"
#include "AcbfReferences.h"
#include "AcbfStyleSheet.h"

#include <QXmlStreamReader>

#include <acbf_debug.h>

using namespace AdvancedComicBookFormat;

class Document::Private {
public:
    Private()
        : metaData(nullptr)
        , body(nullptr)
        , data(nullptr)
    {}
    Metadata* metaData;
    Body* body;
    Data* data;
    References* references;
    StyleSheet* cssStyleSheet;
};

Document::Document(QObject* parent)
    : QObject(parent)
    , d(new Private)
{
    d->metaData = new Metadata(this);
    d->body = new Body(this);
    d->data = new Data(this);
    d->references = new References(this);
    d->cssStyleSheet = new StyleSheet(this);
}

Document::~Document() = default;

QString Document::toXml()
{
    QString output;
    QXmlStreamWriter writer(&output);
    writer.setAutoFormatting(true);
    writer.writeStartDocument();
    writer.writeStartElement(QStringLiteral("ACBF"));
    writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://www.acbf.info/xml/acbf/1.1"));
    d->metaData->toXml(&writer);
    d->body->toXml(&writer);
    writer.writeEndElement();
    writer.writeEndDocument();

    return output;
}

bool Document::fromXml(QString xmlDocument)
{
    QXmlStreamReader xmlReader(xmlDocument);
    if(xmlReader.readNextStartElement())
    {
        if(xmlReader.name() == QStringLiteral("ACBF")
            && (xmlReader.namespaceUri().startsWith(QStringLiteral("http://www.fictionbook-lib.org/xml/acbf/"))
                || xmlReader.namespaceUri().startsWith(QStringLiteral("http://www.acbf.info/xml/acbf/"))
            ))
        {
            while(xmlReader.readNextStartElement())
            {
                if(xmlReader.name() == QStringLiteral("meta-data"))
                {
                    if(!d->metaData->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("body"))
                {
                    if(!d->body->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("data"))
                {
                    if(!d->data->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("references"))
                {
                    if(!d->references->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("style"))
                {
                    if(!d->cssStyleSheet->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else
                {
                    qCWarning(ACBF_LOG) << Q_FUNC_INFO << "currently unsupported subsection:" << xmlReader.name();
                    xmlReader.skipCurrentElement();
                }
            }
            // Ensure that all the internal forward references are up to date, by running through all the paragraphs in all the places
            // That is, run through all objects, check if they're referenceable, and update their forward references if they are
            std::function<void(const QObject* parent)> updateAllForwardReferences;
            updateAllForwardReferences = [&updateAllForwardReferences](const QObject *parent) {
                for (QObject *child : parent->children()) {
                    InternalReferenceObject* refObj = qobject_cast<InternalReferenceObject*>(child);
                    if (refObj) {
                        refObj->updateForwardReferences();
                    }
                    updateAllForwardReferences(child);
                }
            };
            updateAllForwardReferences(this);
        }
        else {
            qCWarning(ACBF_LOG) << Q_FUNC_INFO << "not an ACBF XML document";
            return false;
        }
    }
    if (xmlReader.hasError()) {
        qCWarning(ACBF_LOG) << Q_FUNC_INFO << "Failed to read ACBF XML document at token" << xmlReader.name() << "(" << xmlReader.lineNumber() << ":" << xmlReader.columnNumber() << ") The reported error was:" << xmlReader.errorString();
    }
    qCDebug(ACBF_LOG) << Q_FUNC_INFO << "Completed ACBF document creation for" << d->metaData->bookInfo()->title();
    return !xmlReader.hasError();
}

Metadata * Document::metaData() const
{
    return d->metaData;
}

Body * Document::body() const
{
    return d->body;
}

Data * Document::data() const
{
    return d->data;
}

References * Document::references() const
{
    return d->references;
}

StyleSheet * Document::styleSheet() const
{
    return d->cssStyleSheet;
}

QObject * Document::objectByID(const QString& id) const
{
    QObject* obj{nullptr};
    // We could introspect for id here, but that would be much more expensive, so let's not
    for (QObject* child : d->references->references()) {
        Reference* ref = qobject_cast<Reference*>(child);
        if (ref->id() == id) {
            obj = child;
            break;
        }
    }
    if (!obj) {
        for (QObject* child : d->data->binaries()) {
            Binary* ref = qobject_cast<Binary*>(child);
            if (ref->id() == id) {
                obj = child;
                break;
            }
        }
    }
    return obj;
}
<commit_msg>Register QObjectList as a metatype<commit_after>/*
 * Copyright (C) 2016 Dan Leinir Turthra Jensen <admin@leinir.dk>
 *
 * 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) version 3, or any
 * later version accepted by the membership of KDE e.V. (or its
 * successor approved by the membership of KDE e.V.), which shall
 * act as a proxy defined in Section 6 of version 3 of the license.
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "AcbfDocument.h"
#include "AcbfBody.h"
#include "AcbfMetadata.h"
#include "AcbfBookinfo.h"
#include "AcbfData.h"
#include "AcbfReferences.h"
#include "AcbfStyleSheet.h"

#include <QXmlStreamReader>

#include <acbf_debug.h>

using namespace AdvancedComicBookFormat;

class Document::Private {
public:
    Private()
        : metaData(nullptr)
        , body(nullptr)
        , data(nullptr)
    {}
    Metadata* metaData;
    Body* body;
    Data* data;
    References* references;
    StyleSheet* cssStyleSheet;
};

Document::Document(QObject* parent)
    : QObject(parent)
    , d(new Private)
{
    static const int typeId = qRegisterMetaType<QObjectList>("QObjectList");
    Q_UNUSED(typeId);
    d->metaData = new Metadata(this);
    d->body = new Body(this);
    d->data = new Data(this);
    d->references = new References(this);
    d->cssStyleSheet = new StyleSheet(this);
}

Document::~Document() = default;

QString Document::toXml()
{
    QString output;
    QXmlStreamWriter writer(&output);
    writer.setAutoFormatting(true);
    writer.writeStartDocument();
    writer.writeStartElement(QStringLiteral("ACBF"));
    writer.writeAttribute(QStringLiteral("xmlns"), QStringLiteral("http://www.acbf.info/xml/acbf/1.1"));
    d->metaData->toXml(&writer);
    d->body->toXml(&writer);
    writer.writeEndElement();
    writer.writeEndDocument();

    return output;
}

bool Document::fromXml(QString xmlDocument)
{
    QXmlStreamReader xmlReader(xmlDocument);
    if(xmlReader.readNextStartElement())
    {
        if(xmlReader.name() == QStringLiteral("ACBF")
            && (xmlReader.namespaceUri().startsWith(QStringLiteral("http://www.fictionbook-lib.org/xml/acbf/"))
                || xmlReader.namespaceUri().startsWith(QStringLiteral("http://www.acbf.info/xml/acbf/"))
            ))
        {
            while(xmlReader.readNextStartElement())
            {
                if(xmlReader.name() == QStringLiteral("meta-data"))
                {
                    if(!d->metaData->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("body"))
                {
                    if(!d->body->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("data"))
                {
                    if(!d->data->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("references"))
                {
                    if(!d->references->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else if(xmlReader.name() == QStringLiteral("style"))
                {
                    if(!d->cssStyleSheet->fromXml(&xmlReader)) {
                        break;
                    }
                }
                else
                {
                    qCWarning(ACBF_LOG) << Q_FUNC_INFO << "currently unsupported subsection:" << xmlReader.name();
                    xmlReader.skipCurrentElement();
                }
            }
            // Ensure that all the internal forward references are up to date, by running through all the paragraphs in all the places
            // That is, run through all objects, check if they're referenceable, and update their forward references if they are
            std::function<void(const QObject* parent)> updateAllForwardReferences;
            updateAllForwardReferences = [&updateAllForwardReferences](const QObject *parent) {
                for (QObject *child : parent->children()) {
                    InternalReferenceObject* refObj = qobject_cast<InternalReferenceObject*>(child);
                    if (refObj) {
                        refObj->updateForwardReferences();
                    }
                    updateAllForwardReferences(child);
                }
            };
            updateAllForwardReferences(this);
        }
        else {
            qCWarning(ACBF_LOG) << Q_FUNC_INFO << "not an ACBF XML document";
            return false;
        }
    }
    if (xmlReader.hasError()) {
        qCWarning(ACBF_LOG) << Q_FUNC_INFO << "Failed to read ACBF XML document at token" << xmlReader.name() << "(" << xmlReader.lineNumber() << ":" << xmlReader.columnNumber() << ") The reported error was:" << xmlReader.errorString();
    }
    qCDebug(ACBF_LOG) << Q_FUNC_INFO << "Completed ACBF document creation for" << d->metaData->bookInfo()->title();
    return !xmlReader.hasError();
}

Metadata * Document::metaData() const
{
    return d->metaData;
}

Body * Document::body() const
{
    return d->body;
}

Data * Document::data() const
{
    return d->data;
}

References * Document::references() const
{
    return d->references;
}

StyleSheet * Document::styleSheet() const
{
    return d->cssStyleSheet;
}

QObject * Document::objectByID(const QString& id) const
{
    QObject* obj{nullptr};
    // We could introspect for id here, but that would be much more expensive, so let's not
    for (QObject* child : d->references->references()) {
        Reference* ref = qobject_cast<Reference*>(child);
        if (ref->id() == id) {
            obj = child;
            break;
        }
    }
    if (!obj) {
        for (QObject* child : d->data->binaries()) {
            Binary* ref = qobject_cast<Binary*>(child);
            if (ref->id() == id) {
                obj = child;
                break;
            }
        }
    }
    return obj;
}
<|endoftext|>