<commit_before>#include "OpenFlipper.hh"
#include <OpenMesh/src/Python/Bindings.hh>
#include <boost/python.hpp>
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
#include <ACG/Utils/SmartPointer.hh>

#include <OpenFlipper/BasePlugin/RPCWrappers.hh>

namespace py = boost::python;

py::dict create_dict_from_ids(const std::vector<int>& ids)
{
    py::dict d;
    for (int i : ids)
    {
        TriMeshObject* triobj;
        PolyMeshObject* polyobj;
        if (PluginFunctions::getObject(i, triobj))
        {
            typedef OpenMesh::Python::TriMesh PyMesh;
            PyMesh* m = reinterpret_cast<PyMesh*>(triobj->mesh());
            d[triobj->name().toStdString()] = m;//ptr::shared_ptr<PyMesh>(m, [](PyMesh*){});
        }
        else if (PluginFunctions::getObject(i, polyobj))
        {
            typedef OpenMesh::Python::PolyMesh PyMesh;
            PyMesh* m = reinterpret_cast<PyMesh*>(polyobj->mesh());
            d[polyobj->name().toStdString()] = m;//ptr::shared_ptr<PyMesh>(m, [](PyMesh*){});
        }

    }
    return d;
}

py::dict targets()
{
    std::vector<int> ids;
    PluginFunctions::getTargetIdentifiers(ids);
    return create_dict_from_ids(ids);
}

py::dict sources()
{
    std::vector<int> ids;
    PluginFunctions::getSourceIdentifiers(ids);
    return create_dict_from_ids(ids);
}

py::dict meshes()
{
    std::vector<int> ids;
    PluginFunctions::getAllMeshes(ids);
    return create_dict_from_ids(ids);
}

PyObject* rpc_call(const char* plugin_name, const char* function_name, std::vector<QScriptValue> params)
{
    QScriptValue ret = RPC::callFunction(plugin_name, function_name, std::move(params));
    if (ret.isNumber())
        return PyLong_FromLong(ret.toInt32());

    // in case of no return type could be evaluated
    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* rpc_call(const char* plugin_name, const char* function_name, const boost::python::list& py_params/*{ QString:"value",... }*/)
{
    std::vector<QScriptValue> q_params;
    // convert parameters to scriptvalues

    QScriptEngine* engine = RPC::getScriptEngine();
    for (py::ssize_t i = 0; i < py::len(py_params); i+=2)
    {
        std::string type_name = py::extract<std::string>(py_params[i])();
        //todo: error checking

        QScriptValue script_value;
        if (type_name == "QString")
            script_value = engine->toScriptValue(QString(py::extract<std::string>(py_params[i + 1])().c_str()));
        else if (type_name == "int")
            script_value = engine->toScriptValue(py::extract<int>(py_params[i + 1])());
        else if (type_name == "uint")
            script_value = engine->toScriptValue(py::extract<unsigned int>(py_params[i + 1])());
        else if (type_name == "bool")
            script_value = engine->toScriptValue(py::extract<bool>(py_params[i + 1])());
        else if (type_name == "IdList")
            script_value = engine->toScriptValue(py::extract<IdList>(py_params[i + 1])());
        else if (type_name == "Vector")
            script_value = engine->toScriptValue(py::extract<Vector>(py_params[i + 1])());
        else if (type_name == "Vector4")
            script_value = engine->toScriptValue(py::extract<Vector4>(py_params[i + 1])());

        q_params.push_back(std::move(script_value));
    }
    return rpc_call(plugin_name, function_name, std::move(q_params));
}

PyObject* rpc_call(const char* plugin_name, const char* function_name)
{
    std::vector<QScriptValue> params;
    return rpc_call(plugin_name, function_name, std::move(params));
}

template<typename T>
struct NoDeleter
{
    void operator()(T*) {}
};

py::object getMesh(int id)
{
    using PythonMesh = OpenMesh::Python::PolyMesh;
    using Mesh = PolyMesh;
    Mesh* polymesh = nullptr;
    const bool ok = PluginFunctions::getMesh(id, polymesh);
    if (ok)
        return py::object(std::shared_ptr<PythonMesh>(reinterpret_cast<PythonMesh*>(polymesh), NoDeleter<PythonMesh>()));

    using PythonMesh = OpenMesh::Python::TriMesh;
    using Mesh = TriMesh;
    Mesh* trimesh = nullptr;
    const bool ok = PluginFunctions::getMesh(id, trimesh);
    if (ok)
        return py::object(std::shared_ptr<PythonMesh>(reinterpret_cast<PythonMesh*>(trimesh), NoDeleter<PythonMesh>()));

    // error case
    PyErr_SetString(PyExc_ValueError, "Passed Id is not a PolyMesh");
    return py::object(py::handle<>(py::borrowed(Py_None)));
}

BOOST_PYTHON_MODULE(openflipper)
{
    py::def("targets", &targets);
    py::def("sources", &sources);
    py::def("meshes", &meshes);

    py::def("get_mesh", &getMesh);

    PyObject* (*rpc_callArgs)(const char*, const char*, const boost::python::list&) = rpc_call;
    PyObject* (*rpc_callNoArgs)(const char* , const char* ) = rpc_call;
    py::def("rpc_call", rpc_callArgs);
    py::def("rpc_call", rpc_callNoArgs);

    py::register_ptr_to_python< ptr::shared_ptr<OpenMesh::Python::TriMesh> >();
    py::register_ptr_to_python< ptr::shared_ptr<OpenMesh::Python::PolyMesh> >();

}

namespace boost
{
    template <>
    OpenMesh::Python::PolyMesh const volatile * get_pointer<OpenMesh::Python::PolyMesh const volatile >(
        OpenMesh::Python::PolyMesh const volatile *c)
    {
        return c;
    }
    //template <>
    //OpenMesh::Python::TriMesh const volatile *  get_pointer<OpenMesh::Python::TriMesh const volatile >(
    //    OpenMesh::Python::TriMesh const volatile *c)
    //{
    //    return c;
    //}

}

#if (PY_MAJOR_VERSION == 2)
    PyObject* (*openflipper_pyinit_function)(void) = &initopenflipper;//untested
#elif (PY_MAJOR_VERSION == 3)
    PyObject* (*openflipper_pyinit_function)(void) = &PyInit_openflipper;
#endif<commit_msg>fix typedef<commit_after>#include "OpenFlipper.hh"
#include <OpenMesh/src/Python/Bindings.hh>
#include <boost/python.hpp>
#include <OpenFlipper/BasePlugin/PluginFunctions.hh>
#include <ObjectTypes/PolyMesh/PolyMesh.hh>
#include <ObjectTypes/TriangleMesh/TriangleMesh.hh>
#include <ACG/Utils/SmartPointer.hh>

#include <OpenFlipper/BasePlugin/RPCWrappers.hh>

namespace py = boost::python;

py::dict create_dict_from_ids(const std::vector<int>& ids)
{
    py::dict d;
    for (int i : ids)
    {
        TriMeshObject* triobj;
        PolyMeshObject* polyobj;
        if (PluginFunctions::getObject(i, triobj))
        {
            typedef OpenMesh::Python::TriMesh PyMesh;
            PyMesh* m = reinterpret_cast<PyMesh*>(triobj->mesh());
            d[triobj->name().toStdString()] = m;//ptr::shared_ptr<PyMesh>(m, [](PyMesh*){});
        }
        else if (PluginFunctions::getObject(i, polyobj))
        {
            typedef OpenMesh::Python::PolyMesh PyMesh;
            PyMesh* m = reinterpret_cast<PyMesh*>(polyobj->mesh());
            d[polyobj->name().toStdString()] = m;//ptr::shared_ptr<PyMesh>(m, [](PyMesh*){});
        }

    }
    return d;
}

py::dict targets()
{
    std::vector<int> ids;
    PluginFunctions::getTargetIdentifiers(ids);
    return create_dict_from_ids(ids);
}

py::dict sources()
{
    std::vector<int> ids;
    PluginFunctions::getSourceIdentifiers(ids);
    return create_dict_from_ids(ids);
}

py::dict meshes()
{
    std::vector<int> ids;
    PluginFunctions::getAllMeshes(ids);
    return create_dict_from_ids(ids);
}

PyObject* rpc_call(const char* plugin_name, const char* function_name, std::vector<QScriptValue> params)
{
    QScriptValue ret = RPC::callFunction(plugin_name, function_name, std::move(params));
    if (ret.isNumber())
        return PyLong_FromLong(ret.toInt32());

    // in case of no return type could be evaluated
    Py_INCREF(Py_None);
    return Py_None;
}

PyObject* rpc_call(const char* plugin_name, const char* function_name, const boost::python::list& py_params/*{ QString:"value",... }*/)
{
    std::vector<QScriptValue> q_params;
    // convert parameters to scriptvalues

    QScriptEngine* engine = RPC::getScriptEngine();
    for (py::ssize_t i = 0; i < py::len(py_params); i+=2)
    {
        std::string type_name = py::extract<std::string>(py_params[i])();
        //todo: error checking

        QScriptValue script_value;
        if (type_name == "QString")
            script_value = engine->toScriptValue(QString(py::extract<std::string>(py_params[i + 1])().c_str()));
        else if (type_name == "int")
            script_value = engine->toScriptValue(py::extract<int>(py_params[i + 1])());
        else if (type_name == "uint")
            script_value = engine->toScriptValue(py::extract<unsigned int>(py_params[i + 1])());
        else if (type_name == "bool")
            script_value = engine->toScriptValue(py::extract<bool>(py_params[i + 1])());
        else if (type_name == "IdList")
            script_value = engine->toScriptValue(py::extract<IdList>(py_params[i + 1])());
        else if (type_name == "Vector")
            script_value = engine->toScriptValue(py::extract<Vector>(py_params[i + 1])());
        else if (type_name == "Vector4")
            script_value = engine->toScriptValue(py::extract<Vector4>(py_params[i + 1])());

        q_params.push_back(std::move(script_value));
    }
    return rpc_call(plugin_name, function_name, std::move(q_params));
}

PyObject* rpc_call(const char* plugin_name, const char* function_name)
{
    std::vector<QScriptValue> params;
    return rpc_call(plugin_name, function_name, std::move(params));
}

template<typename T>
struct NoDeleter
{
    void operator()(T*) {}
};

py::object getMesh(int id)
{
    using PythonMesh = OpenMesh::Python::PolyMesh;
    using Mesh = PolyMesh;
    Mesh* polymesh = nullptr;
    const bool ok = PluginFunctions::getMesh(id, polymesh);
    if (ok)
        return py::object(std::shared_ptr<PythonMesh>(reinterpret_cast<PythonMesh*>(polymesh), NoDeleter<PythonMesh>()));

    using PythonTriMesh = OpenMesh::Python::TriMesh;
    using TriMesh = TriMesh;
    TriMesh* trimesh = nullptr;
    const bool ok = PluginFunctions::getMesh(id, trimesh);
    if (ok)
        return py::object(std::shared_ptr<PythonTriMesh>(reinterpret_cast<PythonTriMesh*>(trimesh), NoDeleter<PythonTriMesh>()));

    // error case
    PyErr_SetString(PyExc_ValueError, "Passed Id is not a PolyMesh");
    return py::object(py::handle<>(py::borrowed(Py_None)));
}

BOOST_PYTHON_MODULE(openflipper)
{
    py::def("targets", &targets);
    py::def("sources", &sources);
    py::def("meshes", &meshes);

    py::def("get_mesh", &getMesh);

    PyObject* (*rpc_callArgs)(const char*, const char*, const boost::python::list&) = rpc_call;
    PyObject* (*rpc_callNoArgs)(const char* , const char* ) = rpc_call;
    py::def("rpc_call", rpc_callArgs);
    py::def("rpc_call", rpc_callNoArgs);

    py::register_ptr_to_python< ptr::shared_ptr<OpenMesh::Python::TriMesh> >();
    py::register_ptr_to_python< ptr::shared_ptr<OpenMesh::Python::PolyMesh> >();

}

namespace boost
{
    template <>
    OpenMesh::Python::PolyMesh const volatile * get_pointer<OpenMesh::Python::PolyMesh const volatile >(
        OpenMesh::Python::PolyMesh const volatile *c)
    {
        return c;
    }
    //template <>
    //OpenMesh::Python::TriMesh const volatile *  get_pointer<OpenMesh::Python::TriMesh const volatile >(
    //    OpenMesh::Python::TriMesh const volatile *c)
    //{
    //    return c;
    //}

}

#if (PY_MAJOR_VERSION == 2)
    PyObject* (*openflipper_pyinit_function)(void) = &initopenflipper;//untested
#elif (PY_MAJOR_VERSION == 3)
    PyObject* (*openflipper_pyinit_function)(void) = &PyInit_openflipper;
#endif<|endoftext|>


<commit_before>//********************************************************************
//     Example (very naive for the moment) of using the ESD classes
//        It demonstrates the idea of the "combined PID".
//      Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
//********************************************************************

#if !defined( __CINT__) || defined(__MAKECINT__)
  #include <TMath.h>
  #include <TError.h>
  #include <Riostream.h>
  #include <TH1F.h>
  #include <TH2F.h>
  #include <TParticle.h>
  #include <TCanvas.h>
  #include <TBenchmark.h>
  #include <TFile.h>
  #include <TTree.h>
  #include <TROOT.h>

  #include <AliStack.h>
  #include <AliRunLoader.h>
  #include <AliRun.h>
  #include <AliESD.h>
#endif

extern AliRun *gAlice;
extern TBenchmark *gBenchmark;
extern TROOT *gROOT;

static Int_t allpisel=0;
static Int_t allkasel=0;
static Int_t allprsel=0;
static Int_t allnsel=0;

Int_t AliESDComparison(const Char_t *dir=".") {
   gBenchmark->Start("AliESDComparison");

   ::Info("AliESDComparison.C","Doing comparison...");

   Double_t pi=0.2,pa=3;

   TH2F *tpcHist=(TH2F*)gROOT->FindObject("tpcHist");
   if (!tpcHist)
     tpcHist=new TH2F("tpcHist","TPC dE/dX vs momentum",100,pi,pa,100,0.,300.);
   tpcHist->SetXTitle("p (GeV/c)"); tpcHist->SetYTitle("dE/dx (Arb. Units)");
   tpcHist->SetMarkerStyle(8);
   tpcHist->SetMarkerSize(0.3);

   const Char_t *hname[]={
    "piG","piR","piF","piGood","piFake",
    "kaG","kaR","kaF","kaGood","kaFake",
    "prG","prR","prF","prGood","prFake"
   };
   Int_t nh=sizeof(hname)/sizeof(const Char_t *);
   TH1F **hprt=new TH1F*[nh];

   for (Int_t i=0; i<nh; i++) {
     hprt[i]=(TH1F*)gROOT->FindObject(hname[i]);
     if (hprt[i]==0) {hprt[i]=new TH1F(hname[i],"",20,pi,pa);hprt[i]->Sumw2();}
   }
   TH1F *piG=hprt[0];
   TH1F *piR=hprt[1];
   TH1F *piF=hprt[2];
   TH1F *piGood=hprt[3];
        piGood->SetTitle("Combined PID for pions");
        piGood->SetLineColor(4); piGood->SetXTitle("p (GeV/c)");
   TH1F *piFake=hprt[4];
        piFake->SetLineColor(2);
   TH1F *kaG=hprt[5];
   TH1F *kaR=hprt[6];
   TH1F *kaF=hprt[7];
   TH1F *kaGood=hprt[8];
        kaGood->SetTitle("Combined PID for kaons");
        kaGood->SetLineColor(4); kaGood->SetXTitle("p (GeV/c)");
   TH1F *kaFake=hprt[9];
        kaFake->SetLineColor(2);
   TH1F *prG=hprt[10];
   TH1F *prR=hprt[11];
   TH1F *prF=hprt[12];
   TH1F *prGood=hprt[13];
        prGood->SetTitle("Combined PID for protons");
        prGood->SetLineColor(4); prGood->SetXTitle("p (GeV/c)");
   TH1F *prFake=hprt[14];
        prFake->SetLineColor(2);

   delete[] hprt;

   Char_t fname[100];

   if (gAlice) {
      delete gAlice->GetRunLoader();
      delete gAlice;
      gAlice=0;
   }
   sprintf(fname,"%s/galice.root",dir);
   AliRunLoader *rl = AliRunLoader::Open(fname);
   if (rl == 0x0) {
      ::Error("AliESDComparison.C","Can not open session !");
      return 1;
   }
   if (rl->LoadgAlice()) {
      ::Error("AliESDComparison.C","LoadgAlice returned error !");
      delete rl;
      return 1;
   }
   if (rl->LoadHeader()) {
      ::Error("AliESDComparison.C","LoadHeader returned error !");
      delete rl;
      return 1;
   }
   rl->LoadKinematics();

   sprintf(fname,"%s/AliESDs.root",dir);
   TFile *ef=TFile::Open(fname);
   if (!ef || !ef->IsOpen()) {
      ::Error("AliESDComparison.C","Can't AliESDs.root !");
      delete rl;
      return 1;
   }
   AliESD* event = new AliESD;
   TTree* tree = (TTree*) ef->Get("esdTree");
   if (!tree) {
      ::Error("AliESDComparison.C", "no ESD tree found");
      delete rl;
      return 1;
   }
   tree->SetBranchAddress("ESD", &event);

   //****** Tentative particle type "concentrations"
   Double_t c[5]={0.01, 0.01, 0.85, 0.10, 0.05};

   //******* The loop over events
   Int_t e=0;
   while (tree->GetEvent(e)) {
      cout<<endl<<endl<<"********* Processing event number: "<<e<<"*******\n";

      rl->GetEvent(e);

      e++;

      Int_t ntrk=event->GetNumberOfTracks();
      cerr<<"Number of ESD tracks : "<<ntrk<<endl;

      Int_t pisel=0,kasel=0,prsel=0,nsel=0;

      AliStack *stack = rl->Stack();

      while (ntrk--) {
         AliESDtrack *t=event->GetTrack(ntrk);

         UInt_t status=AliESDtrack::kESDpid;
         status|=AliESDtrack::kITSpid;
         status|=AliESDtrack::kTPCpid;
         status|=AliESDtrack::kTRDpid;
         status|=AliESDtrack::kTOFpid;

        if ((t->GetStatus()&status) == status) {
           nsel++;

           Double_t p=t->GetP();
	   Double_t dedx=t->GetTPCsignal();
           tpcHist->Fill(p,dedx,1);

           Int_t lab=TMath::Abs(t->GetLabel());
           TParticle *part=stack->Particle(lab);
           Int_t code=part->GetPdgCode();

           Double_t r[10]; t->GetESDpid(r);
           //t->GetTRDpid(r);

           Double_t rcc=0.;
           Int_t i;
           for (i=0; i<AliESDtrack::kSPECIES; i++) rcc+=(c[i]*r[i]);
           if (rcc==0.) continue;

	   //Here we apply Bayes' formula
           Double_t w[10];
           for (i=0; i<AliESDtrack::kSPECIES; i++) w[i]=c[i]*r[i]/rcc;

           if (TMath::Abs(code)==2212) prR->Fill(p);
           if (w[4]>w[3] && w[4]>w[2] && w[4]>w[1] && w[4]>w[0]) {//proton
	      prsel++;
	      prG->Fill(p);
              if (TMath::Abs(code)!=2212) prF->Fill(p);
           }

           if (TMath::Abs(code)==321) kaR->Fill(p);
           if (w[3]>w[4] && w[3]>w[2] && w[3]>w[1] && w[3]>w[0]) {//kaon
	      kasel++;
	      kaG->Fill(p);
              if (TMath::Abs(code)!=321) kaF->Fill(p);
           }

	   if (TMath::Abs(code)==211) piR->Fill(p);
	   if (w[2]>w[3] && w[2]>w[4] && w[2]>w[1] && w[2]>w[0]) {//pion
	      pisel++;
	      piG->Fill(p);
	      if (TMath::Abs(code)!=211) piF->Fill(p);
           }
	}
      }
      cout<<"Number of selected ESD tracks : "<<nsel<<endl;
      cout<<"Number of selected pion ESD tracks : "<<pisel<<endl;
      cout<<"Number of selected kaon ESD tracks : "<<kasel<<endl;
      cout<<"Number of selected proton ESD tracks : "<<prsel<<endl;

      allnsel+=nsel; allpisel+=pisel; allkasel+=kasel; allprsel+=prsel;

   } // ***** End of the loop over events

   delete event;
   ef->Close();

   TCanvas *c1=(TCanvas*)gROOT->FindObject("c1");
   if (!c1) {
      c1=new TCanvas("c1","",0,0,600,1200);
      c1->Divide(1,4);
   }

   c1->cd(1);
   tpcHist->Draw();

   c1->cd(2);
   //piG->Sumw2(); piF->Sumw2(); piR->Sumw2();
   piGood->Add(piG,piF,1,-1);
   piGood->Divide(piGood,piR,1,1,"b");
   piFake->Divide(piF,piG,1,1,"b");
   piGood->Draw("hist");
   piFake->Draw("same");

   c1->cd(3);
   //kaG->Sumw2(); kaF->Sumw2(); kaR->Sumw2();
   kaGood->Add(kaG,kaF,1,-1);
   kaGood->Divide(kaGood,kaR,1,1,"b");
   kaFake->Divide(kaF,kaG,1,1,"b");
   kaGood->Draw("hist");
   kaFake->Draw("same");

   c1->cd(4);
   //prG->Sumw2(); prF->Sumw2(); prR->Sumw2();
   prGood->Add(prG,prF,1,-1);
   prGood->Divide(prGood,prR,1,1,"b");
   prFake->Divide(prF,prG,1,1,"b");
   prGood->Draw("hist");
   prFake->Draw("same");

   c1->Update();

   cout<<endl;
   cout<<endl;
   e=(Int_t)piR->GetEntries();
   Int_t o=(Int_t)piG->GetEntries();
   if (e*o) cout<<"Efficiency (contamination) for pions : "<<
      piGood->GetEntries()/e<<'('<<piF->GetEntries()/o<<')'<<endl;
   e=(Int_t)kaR->GetEntries();
   o=(Int_t)kaG->GetEntries();
   if (e*o) cout<<"Efficiency (contamination) for kaons : "<<
      kaGood->GetEntries()/e<<'('<<kaF->GetEntries()/o<<')'<<endl;
   e=(Int_t)prR->GetEntries();
   o=(Int_t)prG->GetEntries();
   if (e*o) cout<<"Efficiency (contamination) for protons : "<<
      prGood->GetEntries()/e<<'('<<prF->GetEntries()/o<<')'<<endl;
   cout<<endl;

   cout<<"Total number of selected ESD tracks : "<<allnsel<<endl;
   cout<<"Total number of selected pion ESD tracks : "<<allpisel<<endl;
   cout<<"Total number of selected kaon ESD tracks : "<<allkasel<<endl;
   cout<<"Total number of selected proton ESD tracks : "<<allprsel<<endl;

   ef->Close();
   TFile fc("AliESDComparison.root","RECREATE");
   c1->Write();
   fc.Close();

   gBenchmark->Stop("AliESDComparison");
   gBenchmark->Show("AliESDComparison");

   delete rl;
   return 0;
}
<commit_msg>Using AliPID (Yu.Belikov)<commit_after>//********************************************************************
//     Example (very naive for the moment) of using the ESD classes
//        It demonstrates the idea of the "combined PID".
//      Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
//********************************************************************

#if !defined( __CINT__) || defined(__MAKECINT__)
  #include <TMath.h>
  #include <TError.h>
  #include <Riostream.h>
  #include <TH1F.h>
  #include <TH2F.h>
  #include <TParticle.h>
  #include <TCanvas.h>
  #include <TBenchmark.h>
  #include <TFile.h>
  #include <TTree.h>
  #include <TROOT.h>

  #include <AliStack.h>
  #include <AliRunLoader.h>
  #include <AliRun.h>
  #include <AliESD.h>
#endif

extern AliRun *gAlice;
extern TBenchmark *gBenchmark;
extern TROOT *gROOT;

static Int_t allpisel=0;
static Int_t allkasel=0;
static Int_t allprsel=0;
static Int_t allnsel=0;

Int_t AliESDComparison(const Char_t *dir=".") {
   gBenchmark->Start("AliESDComparison");

   ::Info("AliESDComparison.C","Doing comparison...");

   Double_t pi=0.2,pa=3;

   TH2F *tpcHist=(TH2F*)gROOT->FindObject("tpcHist");
   if (!tpcHist)
     tpcHist=new TH2F("tpcHist","TPC dE/dX vs momentum",100,pi,pa,100,0.,300.);
   tpcHist->SetXTitle("p (GeV/c)"); tpcHist->SetYTitle("dE/dx (Arb. Units)");
   tpcHist->SetMarkerStyle(8);
   tpcHist->SetMarkerSize(0.3);

   const Char_t *hname[]={
    "piG","piR","piF","piGood","piFake",
    "kaG","kaR","kaF","kaGood","kaFake",
    "prG","prR","prF","prGood","prFake"
   };
   Int_t nh=sizeof(hname)/sizeof(const Char_t *);
   TH1F **hprt=new TH1F*[nh];

   for (Int_t i=0; i<nh; i++) {
     hprt[i]=(TH1F*)gROOT->FindObject(hname[i]);
     if (hprt[i]==0) {hprt[i]=new TH1F(hname[i],"",20,pi,pa);hprt[i]->Sumw2();}
   }
   TH1F *piG=hprt[0];
   TH1F *piR=hprt[1];
   TH1F *piF=hprt[2];
   TH1F *piGood=hprt[3];
        piGood->SetTitle("Combined PID for pions");
        piGood->SetLineColor(4); piGood->SetXTitle("p (GeV/c)");
   TH1F *piFake=hprt[4];
        piFake->SetLineColor(2);
   TH1F *kaG=hprt[5];
   TH1F *kaR=hprt[6];
   TH1F *kaF=hprt[7];
   TH1F *kaGood=hprt[8];
        kaGood->SetTitle("Combined PID for kaons");
        kaGood->SetLineColor(4); kaGood->SetXTitle("p (GeV/c)");
   TH1F *kaFake=hprt[9];
        kaFake->SetLineColor(2);
   TH1F *prG=hprt[10];
   TH1F *prR=hprt[11];
   TH1F *prF=hprt[12];
   TH1F *prGood=hprt[13];
        prGood->SetTitle("Combined PID for protons");
        prGood->SetLineColor(4); prGood->SetXTitle("p (GeV/c)");
   TH1F *prFake=hprt[14];
        prFake->SetLineColor(2);

   delete[] hprt;

   Char_t fname[100];

   if (gAlice) {
      delete gAlice->GetRunLoader();
      delete gAlice;
      gAlice=0;
   }
   sprintf(fname,"%s/galice.root",dir);
   AliRunLoader *rl = AliRunLoader::Open(fname);
   if (rl == 0x0) {
      ::Error("AliESDComparison.C","Can not open session !");
      return 1;
   }
   if (rl->LoadgAlice()) {
      ::Error("AliESDComparison.C","LoadgAlice returned error !");
      delete rl;
      return 1;
   }
   if (rl->LoadHeader()) {
      ::Error("AliESDComparison.C","LoadHeader returned error !");
      delete rl;
      return 1;
   }
   rl->LoadKinematics();

   sprintf(fname,"%s/AliESDs.root",dir);
   TFile *ef=TFile::Open(fname);
   if (!ef || !ef->IsOpen()) {
      ::Error("AliESDComparison.C","Can't AliESDs.root !");
      delete rl;
      return 1;
   }
   AliESD* event = new AliESD;
   TTree* tree = (TTree*) ef->Get("esdTree");
   if (!tree) {
      ::Error("AliESDComparison.C", "no ESD tree found");
      delete rl;
      return 1;
   }
   tree->SetBranchAddress("ESD", &event);

   //****** Tentative particle type "concentrations"
   Double_t c[5]={0.01, 0.01, 0.85, 0.10, 0.05};
   //Double_t c[5]={0.2, 0.2, 0.2, 0.2, 0.2};
   AliPID::SetPriors(c);

   //******* The loop over events
   Int_t e=0;
   while (tree->GetEvent(e)) {
      cout<<endl<<endl<<"********* Processing event number: "<<e<<"*******\n";

      rl->GetEvent(e);

      e++;

      Int_t ntrk=event->GetNumberOfTracks();
      cerr<<"Number of ESD tracks : "<<ntrk<<endl;

      Int_t pisel=0,kasel=0,prsel=0,nsel=0;

      AliStack *stack = rl->Stack();

      while (ntrk--) {
         AliESDtrack *t=event->GetTrack(ntrk);

         UInt_t status=AliESDtrack::kESDpid;
         status|=AliESDtrack::kITSpid;
         status|=AliESDtrack::kTPCpid;
         //status|=AliESDtrack::kTRDpid;
         //status|=AliESDtrack::kTOFpid;

        if ((t->GetStatus()&status) == status) {
           nsel++;

           Double_t p=t->GetP();
	   Double_t dedx=t->GetTPCsignal();
           tpcHist->Fill(p,dedx,1);

           Int_t lab=TMath::Abs(t->GetLabel());
           TParticle *part=stack->Particle(lab);
           Int_t code=part->GetPdgCode();

           Double_t r[10]; t->GetESDpid(r);
           //t->GetTRDpid(r);
           //t->GetTPCpid(r);

           AliPID pid(r);

           Double_t w[10];
           w[0]=pid.GetProbability(AliPID::kElectron);
           w[1]=pid.GetProbability(AliPID::kMuon);
           w[2]=pid.GetProbability(AliPID::kPion);
           w[3]=pid.GetProbability(AliPID::kKaon);
           w[4]=pid.GetProbability(AliPID::kProton);

           if (TMath::Abs(code)==2212) prR->Fill(p);
           if (w[4]>w[3] && w[4]>w[2] && w[4]>w[1] && w[4]>w[0]) {//proton
	      prsel++;
	      prG->Fill(p);
              if (TMath::Abs(code)!=2212) prF->Fill(p);
           }

           if (TMath::Abs(code)==321) kaR->Fill(p);
           if (w[3]>w[4] && w[3]>w[2] && w[3]>w[1] && w[3]>w[0]) {//kaon
	      kasel++;
	      kaG->Fill(p);
              if (TMath::Abs(code)!=321) kaF->Fill(p);
           }

	   if (TMath::Abs(code)==211) piR->Fill(p);
	   if (w[2]>w[4] && w[2]>w[3] && w[2]>w[0] && w[2]>w[1]) {//pion
	      pisel++;
	      piG->Fill(p);
	      if (TMath::Abs(code)!=211) piF->Fill(p);
           }
	}
      }
      cout<<"Number of selected ESD tracks : "<<nsel<<endl;
      cout<<"Number of selected pion ESD tracks : "<<pisel<<endl;
      cout<<"Number of selected kaon ESD tracks : "<<kasel<<endl;
      cout<<"Number of selected proton ESD tracks : "<<prsel<<endl;

      allnsel+=nsel; allpisel+=pisel; allkasel+=kasel; allprsel+=prsel;

   } // ***** End of the loop over events

   delete event;
   ef->Close();

   TCanvas *c1=(TCanvas*)gROOT->FindObject("c1");
   if (!c1) {
      c1=new TCanvas("c1","",0,0,600,1200);
      c1->Divide(1,4);
   }

   c1->cd(1);
   tpcHist->Draw();

   c1->cd(2);
   //piG->Sumw2(); piF->Sumw2(); piR->Sumw2();
   piGood->Add(piG,piF,1,-1);
   piGood->Divide(piGood,piR,1,1,"b");
   piFake->Divide(piF,piG,1,1,"b");
   piGood->Draw("hist");
   piFake->Draw("same");

   c1->cd(3);
   //kaG->Sumw2(); kaF->Sumw2(); kaR->Sumw2();
   kaGood->Add(kaG,kaF,1,-1);
   kaGood->Divide(kaGood,kaR,1,1,"b");
   kaFake->Divide(kaF,kaG,1,1,"b");
   kaGood->Draw("hist");
   kaFake->Draw("same");

   c1->cd(4);
   //prG->Sumw2(); prF->Sumw2(); prR->Sumw2();
   prGood->Add(prG,prF,1,-1);
   prGood->Divide(prGood,prR,1,1,"b");
   prFake->Divide(prF,prG,1,1,"b");
   prGood->Draw("hist");
   prFake->Draw("same");

   c1->Update();

   cout<<endl;
   cout<<endl;
   e=(Int_t)piR->GetEntries();
   Int_t o=(Int_t)piG->GetEntries();
   if (e*o) cout<<"Efficiency (contamination) for pions : "<<
      piGood->GetEntries()/e<<'('<<piF->GetEntries()/o<<')'<<endl;
   e=(Int_t)kaR->GetEntries();
   o=(Int_t)kaG->GetEntries();
   if (e*o) cout<<"Efficiency (contamination) for kaons : "<<
      kaGood->GetEntries()/e<<'('<<kaF->GetEntries()/o<<')'<<endl;
   e=(Int_t)prR->GetEntries();
   o=(Int_t)prG->GetEntries();
   if (e*o) cout<<"Efficiency (contamination) for protons : "<<
      prGood->GetEntries()/e<<'('<<prF->GetEntries()/o<<')'<<endl;
   cout<<endl;

   cout<<"Total number of selected ESD tracks : "<<allnsel<<endl;
   cout<<"Total number of selected pion ESD tracks : "<<allpisel<<endl;
   cout<<"Total number of selected kaon ESD tracks : "<<allkasel<<endl;
   cout<<"Total number of selected proton ESD tracks : "<<allprsel<<endl;

   ef->Close();
   TFile fc("AliESDComparison.root","RECREATE");
   c1->Write();
   fc.Close();

   gBenchmark->Stop("AliESDComparison");
   gBenchmark->Show("AliESDComparison");

   delete rl;
   return 0;
}
<|endoftext|>


<commit_before>//********************************************************************
//     Example (very naive for the moment) of the data analysis
//                    using the ESD classes.
//       It demonstrates the idea of the "combined PID"
//            applied to the Lambda0 reconstruction.
//      Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
//********************************************************************

#if !defined( __CINT__) || defined(__MAKECINT__)
  #include <Riostream.h>
  #include <TTree.h>
  #include <TFile.h>
  #include <TH1F.h>
  #include <TCanvas.h>

  #include "AliESD.h"

#endif

Int_t AliESDv0Analysis(const Char_t *dir=".") {
   TH1F *hm=(TH1F*)gROOT->FindObject("hm");
   if (!hm) {
      hm=new TH1F("hm","Lambda+LambdaBar Effective Mass",60,1.065,1.165);
      hm->SetXTitle("Mass (GeV/c**2)");
   }
   Char_t fname[100];
   sprintf(fname,"%s/AliESDs.root",dir);
   TFile *ef=TFile::Open(fname);
   if (!ef||!ef->IsOpen()) {cerr<<"Can't AliESDs.root !\n"; return 1;}
   cerr<<"\n****** "<<fname<<" ******\n";

   AliESD* event = new AliESD;

   TTree* tree = (TTree*) ef->Get("esdTree");
   if (!tree) {cerr<<"no ESD tree found\n"; return 1;};
   tree->SetBranchAddress("ESD", &event);

   Int_t rc=0,n=0;

   //****** Tentative particle type "concentrations"
   Double_t c[5]={0.0, 0.0, 1, 0, 1};

   //******* The loop over events
    while (tree->GetEvent(n))
    {

     cerr<<"Processing event number : "<<n++<<endl;

     Int_t nv0=event->GetNumberOfV0s();
     cerr<<"Number of ESD v0s : "<<nv0<<endl;

     while (nv0--) {
       AliESDv0 *v0=event->GetV0(nv0);

       Int_t protonIdx=v0->GetPindex();
       Int_t pionIdx  =v0->GetNindex();

       v0->ChangeMassHypothesis(3122);
       Double_t mass=v0->GetEffMass();
       if (mass>1.17) {  //check also a LambdaBar hypothesis
          v0->ChangeMassHypothesis(-3122);
          mass=v0->GetEffMass();
          if (mass>1.17) continue;
          Int_t tmp=protonIdx; protonIdx=pionIdx; pionIdx=tmp;
       }

       AliESDtrack *protonTrk=event->GetTrack(protonIdx);
       AliESDtrack *pionTrk  =event->GetTrack(pionIdx);

       if (protonTrk->GetP()<0.5) continue;

       // Check if the "proton track" is a proton
       if ((protonTrk->GetStatus()&AliESDtrack::kESDpid)!=0) {
	 Double_t r[10]; protonTrk->GetESDpid(r);
         Double_t rcc=0.;
         Int_t i;
         for (i=0; i<AliESDtrack::kSPECIES; i++) rcc+=(c[i]*r[i]);
         if (rcc==0.) continue;
         //Here we apply Bayes' formula
         Double_t w[10];
         for (i=0; i<AliESDtrack::kSPECIES; i++) w[i]=c[i]*r[i]/rcc;

         if (w[4]<w[3]) continue;
         if (w[4]<w[2]) continue;
         if (w[4]<w[1]) continue;
	 if (w[4]<w[0]) continue;
       }

       //Check if the "pion track" is a pion
       if ((pionTrk->GetStatus()&AliESDtrack::kESDpid)!=0) {
	 Double_t r[10]; pionTrk->GetESDpid(r);
         Double_t rcc=0.;
         Int_t i;
         for (i=0; i<AliESDtrack::kSPECIES; i++) rcc+=(c[i]*r[i]);
         if (rcc==0.) continue;
         //Here we apply Bayes' formula
         Double_t w[10];
         for (i=0; i<AliESDtrack::kSPECIES; i++) w[i]=c[i]*r[i]/rcc;

         if (w[2]<w[4]) continue;
         if (w[2]<w[3]) continue;
         if (w[2]<w[1]) continue;
	 if (w[2]<w[0]) continue;
       }

       hm->Fill(mass);
     }

   }

   delete event;
   ef->Close();

   TCanvas *c1=(TCanvas*)gROOT->FindObject("c1");
   if (!c1) {
      c1=new TCanvas();
   }

   if (hm->GetEntries()>100) hm->Fit("gaus","","",1.11,1.12);
   else hm->Draw();

   c1->Update();

   return rc;
}
<commit_msg>Using AliPID class (Yu.Belikov)<commit_after>//********************************************************************
//     Example (very naive for the moment) of the data analysis
//                    using the ESD classes.
//       It demonstrates the idea of the "combined PID"
//            applied to the Lambda0 reconstruction.
//      Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
//********************************************************************

#if !defined( __CINT__) || defined(__MAKECINT__)
  #include <Riostream.h>
  #include <TTree.h>
  #include <TFile.h>
  #include <TH1F.h>
  #include <TCanvas.h>

  #include "AliESD.h"

#endif

Int_t AliESDv0Analysis(const Char_t *dir=".") {
   TH1F *hm=(TH1F*)gROOT->FindObject("hm");
   if (!hm) {
      hm=new TH1F("hm","Lambda+LambdaBar Effective Mass",60,1.065,1.165);
      hm->SetXTitle("Mass (GeV/c**2)");
   }
   Char_t fname[100];
   sprintf(fname,"%s/AliESDs.root",dir);
   TFile *ef=TFile::Open(fname);
   if (!ef||!ef->IsOpen()) {cerr<<"Can't AliESDs.root !\n"; return 1;}
   cerr<<"\n****** "<<fname<<" ******\n";

   AliESD* event = new AliESD;

   TTree* tree = (TTree*) ef->Get("esdTree");
   if (!tree) {cerr<<"no ESD tree found\n"; return 1;};
   tree->SetBranchAddress("ESD", &event);

   Int_t rc=0,n=0;

   //****** Tentative particle type "concentrations"
   Double_t c[5]={0.0, 0.0, 1, 0, 1};
   AliPID::SetPriors(c);

   //******* The loop over events
    while (tree->GetEvent(n)) {

     cerr<<"Processing event number : "<<n++<<endl;

     Int_t nv0=event->GetNumberOfV0s();
     cerr<<"Number of ESD v0s : "<<nv0<<endl;

     while (nv0--) {
       AliESDv0 *v0=event->GetV0(nv0);

       Int_t protonIdx=v0->GetPindex();
       Int_t pionIdx  =v0->GetNindex();

       v0->ChangeMassHypothesis(3122);
       Double_t mass=v0->GetEffMass();
       if (mass>1.17) {  //check also the LambdaBar hypothesis
          v0->ChangeMassHypothesis(-3122);
          mass=v0->GetEffMass();
          if (mass>1.17) continue;
          Int_t tmp=protonIdx; protonIdx=pionIdx; pionIdx=tmp;
       }

       AliESDtrack *protonTrk=event->GetTrack(protonIdx);
       AliESDtrack *pionTrk  =event->GetTrack(pionIdx);

       if (protonTrk->GetP()<0.5) continue;

       // Check if the "proton track" is a proton
       if ((protonTrk->GetStatus()&AliESDtrack::kESDpid)!=0) {
	 Double_t r[10]; protonTrk->GetESDpid(r);
         AliPID pid(r);
         Double_t pp=pid.GetProbability(AliPID::kProton);
         if (pp < pid.GetProbability(AliPID::kElectron)) continue;
         if (pp < pid.GetProbability(AliPID::kMuon)) continue;
         if (pp < pid.GetProbability(AliPID::kPion)) continue;
         if (pp < pid.GetProbability(AliPID::kKaon)) continue;
       }

       //Check if the "pion track" is a pion
       if ((pionTrk->GetStatus()&AliESDtrack::kESDpid)!=0) {
	 Double_t r[10]; pionTrk->GetESDpid(r);
         AliPID pid(r);
         Double_t ppi=pid.GetProbability(AliPID::kPion);
         if (ppi < pid.GetProbability(AliPID::kElectron)) continue;
         if (ppi < pid.GetProbability(AliPID::kMuon)) continue;
         if (ppi < pid.GetProbability(AliPID::kKaon)) continue;
         if (ppi < pid.GetProbability(AliPID::kProton)) continue;
        }

       hm->Fill(mass);
     }

   }

   delete event;
   ef->Close();

   TCanvas *c1=(TCanvas*)gROOT->FindObject("c1");
   if (!c1) {
      c1=new TCanvas();
   }

   if (hm->GetEntries()>100) hm->Fit("gaus","","",1.11,1.12);
   else hm->Draw();

   c1->Update();

   return rc;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2010 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 "net/disk_cache/file.h"

#include <fcntl.h>

#include "base/logging.h"
#include "base/threading/worker_pool.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/in_flight_io.h"

namespace {

// This class represents a single asynchronous IO operation while it is being
// bounced between threads.
class FileBackgroundIO : public disk_cache::BackgroundIO {
 public:
  // Other than the actual parameters for the IO operation (including the
  // |callback| that must be notified at the end), we need the controller that
  // is keeping track of all operations. When done, we notify the controller
  // (we do NOT invoke the callback), in the worker thead that completed the
  // operation.
  FileBackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len,
                   size_t offset, disk_cache::FileIOCallback* callback,
                   disk_cache::InFlightIO* controller)
      : disk_cache::BackgroundIO(controller), callback_(callback), file_(file),
        buf_(buf), buf_len_(buf_len), offset_(offset) {
  }

  disk_cache::FileIOCallback* callback() {
    return callback_;
  }

  disk_cache::File* file() {
    return file_;
  }

  // Read and Write are the operations that can be performed asynchronously.
  // The actual parameters for the operation are setup in the constructor of
  // the object. Both methods should be called from a worker thread, by posting
  // a task to the WorkerPool (they are RunnableMethods). When finished,
  // controller->OnIOComplete() is called.
  void Read();
  void Write();

 private:
  ~FileBackgroundIO() {}

  disk_cache::FileIOCallback* callback_;

  disk_cache::File* file_;
  const void* buf_;
  size_t buf_len_;
  size_t offset_;

  DISALLOW_COPY_AND_ASSIGN(FileBackgroundIO);
};

// The specialized controller that keeps track of current operations.
class FileInFlightIO : public disk_cache::InFlightIO {
 public:
  FileInFlightIO() {}
  ~FileInFlightIO() {}

  // These methods start an asynchronous operation. The arguments have the same
  // semantics of the File asynchronous operations, with the exception that the
  // operation never finishes synchronously.
  void PostRead(disk_cache::File* file, void* buf, size_t buf_len,
                size_t offset, disk_cache::FileIOCallback* callback);
  void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len,
                 size_t offset, disk_cache::FileIOCallback* callback);

 protected:
  // Invokes the users' completion callback at the end of the IO operation.
  // |cancel| is true if the actual task posted to the thread is still
  // queued (because we are inside WaitForPendingIO), and false if said task is
  // the one performing the call.
  virtual void OnOperationComplete(disk_cache::BackgroundIO* operation,
                                   bool cancel);

 private:
  DISALLOW_COPY_AND_ASSIGN(FileInFlightIO);
};

// ---------------------------------------------------------------------------

// Runs on a worker thread.
void FileBackgroundIO::Read() {
  if (file_->Read(const_cast<void*>(buf_), buf_len_, offset_)) {
    result_ = static_cast<int>(buf_len_);
  } else {
    result_ = -1;
  }
  controller_->OnIOComplete(this);
}

// Runs on a worker thread.
void FileBackgroundIO::Write() {
  bool rv = file_->Write(buf_, buf_len_, offset_);

  result_ = rv ? static_cast<int>(buf_len_) : -1;
  controller_->OnIOComplete(this);
}

// ---------------------------------------------------------------------------

void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len,
                          size_t offset, disk_cache::FileIOCallback *callback) {
  scoped_refptr<FileBackgroundIO> operation(
      new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
  file->AddRef();  // Balanced on OnOperationComplete()

  base::WorkerPool::PostTask(FROM_HERE,
      NewRunnableMethod(operation.get(), &FileBackgroundIO::Read), true);
  OnOperationPosted(operation);
}

void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf,
                           size_t buf_len, size_t offset,
                           disk_cache::FileIOCallback* callback) {
  scoped_refptr<FileBackgroundIO> operation(
      new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
  file->AddRef();  // Balanced on OnOperationComplete()

  base::WorkerPool::PostTask(FROM_HERE,
      NewRunnableMethod(operation.get(), &FileBackgroundIO::Write), true);
  OnOperationPosted(operation);
}

// Runs on the IO thread.
void FileInFlightIO::OnOperationComplete(disk_cache::BackgroundIO* operation,
                                         bool cancel) {
  FileBackgroundIO* op = static_cast<FileBackgroundIO*>(operation);

  disk_cache::FileIOCallback* callback = op->callback();
  int bytes = operation->result();

  // Release the references acquired in PostRead / PostWrite.
  op->file()->Release();
  callback->OnFileIOComplete(bytes);
}

// A static object tha will broker all async operations.
FileInFlightIO* s_file_operations = NULL;

// Returns the current FileInFlightIO.
FileInFlightIO* GetFileInFlightIO() {
  if (!s_file_operations) {
    s_file_operations = new FileInFlightIO;
  }
  return s_file_operations;
}

// Deletes the current FileInFlightIO.
void DeleteFileInFlightIO() {
  DCHECK(s_file_operations);
  delete s_file_operations;
  s_file_operations = NULL;
}

}  // namespace

namespace disk_cache {

File::File(base::PlatformFile file)
    : init_(true),
      mixed_(true),
      platform_file_(file),
      sync_platform_file_(base::kInvalidPlatformFileValue) {
}

bool File::Init(const FilePath& name) {
  if (init_)
    return false;

  int flags = base::PLATFORM_FILE_OPEN |
              base::PLATFORM_FILE_READ |
              base::PLATFORM_FILE_WRITE;
  platform_file_ = base::CreatePlatformFile(name, flags, NULL, NULL);
  if (platform_file_ < 0) {
    platform_file_ = 0;
    return false;
  }

  init_ = true;
  return true;
}

base::PlatformFile File::platform_file() const {
  return platform_file_;
}

bool File::IsValid() const {
  if (!init_)
    return false;
  return (base::kInvalidPlatformFileValue != platform_file_);
}

bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
  DCHECK(init_);
  if (buffer_len > ULONG_MAX || offset > LONG_MAX)
    return false;

  int ret = pread(platform_file_, buffer, buffer_len, offset);
  return (static_cast<size_t>(ret) == buffer_len);
}

bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
  DCHECK(init_);
  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
    return false;

  int ret = pwrite(platform_file_, buffer, buffer_len, offset);
  return (static_cast<size_t>(ret) == buffer_len);
}

// We have to increase the ref counter of the file before performing the IO to
// prevent the completion to happen with an invalid handle (if the file is
// closed while the IO is in flight).
bool File::Read(void* buffer, size_t buffer_len, size_t offset,
                FileIOCallback* callback, bool* completed) {
  DCHECK(init_);
  if (!callback) {
    if (completed)
      *completed = true;
    return Read(buffer, buffer_len, offset);
  }

  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
    return false;

  GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback);

  *completed = false;
  return true;
}

bool File::Write(const void* buffer, size_t buffer_len, size_t offset,
                 FileIOCallback* callback, bool* completed) {
  DCHECK(init_);
  if (!callback) {
    if (completed)
      *completed = true;
    return Write(buffer, buffer_len, offset);
  }

  return AsyncWrite(buffer, buffer_len, offset, callback, completed);
}

bool File::SetLength(size_t length) {
  DCHECK(init_);
  if (length > ULONG_MAX)
    return false;

  return 0 == ftruncate(platform_file_, length);
}

size_t File::GetLength() {
  DCHECK(init_);
  size_t ret = lseek(platform_file_, 0, SEEK_END);
  return ret;
}

// Static.
void File::WaitForPendingIO(int* num_pending_io) {
  // We may be running unit tests so we should allow be able to reset the
  // message loop.
  GetFileInFlightIO()->WaitForPendingIO();
  DeleteFileInFlightIO();
}

File::~File() {
  if (platform_file_)
    close(platform_file_);
}

bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
                      FileIOCallback* callback, bool* completed) {
  DCHECK(init_);
  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
    return false;

  GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback);

  if (completed)
    *completed = false;
  return true;
}

}  // namespace disk_cache
<commit_msg>Disk Cache: Make sure that file descriptors are valid before calling close().<commit_after>// Copyright (c) 2006-2010 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 "net/disk_cache/file.h"

#include <fcntl.h>

#include "base/logging.h"
#include "base/threading/worker_pool.h"
#include "net/disk_cache/disk_cache.h"
#include "net/disk_cache/in_flight_io.h"

namespace {

// This class represents a single asynchronous IO operation while it is being
// bounced between threads.
class FileBackgroundIO : public disk_cache::BackgroundIO {
 public:
  // Other than the actual parameters for the IO operation (including the
  // |callback| that must be notified at the end), we need the controller that
  // is keeping track of all operations. When done, we notify the controller
  // (we do NOT invoke the callback), in the worker thead that completed the
  // operation.
  FileBackgroundIO(disk_cache::File* file, const void* buf, size_t buf_len,
                   size_t offset, disk_cache::FileIOCallback* callback,
                   disk_cache::InFlightIO* controller)
      : disk_cache::BackgroundIO(controller), callback_(callback), file_(file),
        buf_(buf), buf_len_(buf_len), offset_(offset) {
  }

  disk_cache::FileIOCallback* callback() {
    return callback_;
  }

  disk_cache::File* file() {
    return file_;
  }

  // Read and Write are the operations that can be performed asynchronously.
  // The actual parameters for the operation are setup in the constructor of
  // the object. Both methods should be called from a worker thread, by posting
  // a task to the WorkerPool (they are RunnableMethods). When finished,
  // controller->OnIOComplete() is called.
  void Read();
  void Write();

 private:
  ~FileBackgroundIO() {}

  disk_cache::FileIOCallback* callback_;

  disk_cache::File* file_;
  const void* buf_;
  size_t buf_len_;
  size_t offset_;

  DISALLOW_COPY_AND_ASSIGN(FileBackgroundIO);
};

// The specialized controller that keeps track of current operations.
class FileInFlightIO : public disk_cache::InFlightIO {
 public:
  FileInFlightIO() {}
  ~FileInFlightIO() {}

  // These methods start an asynchronous operation. The arguments have the same
  // semantics of the File asynchronous operations, with the exception that the
  // operation never finishes synchronously.
  void PostRead(disk_cache::File* file, void* buf, size_t buf_len,
                size_t offset, disk_cache::FileIOCallback* callback);
  void PostWrite(disk_cache::File* file, const void* buf, size_t buf_len,
                 size_t offset, disk_cache::FileIOCallback* callback);

 protected:
  // Invokes the users' completion callback at the end of the IO operation.
  // |cancel| is true if the actual task posted to the thread is still
  // queued (because we are inside WaitForPendingIO), and false if said task is
  // the one performing the call.
  virtual void OnOperationComplete(disk_cache::BackgroundIO* operation,
                                   bool cancel);

 private:
  DISALLOW_COPY_AND_ASSIGN(FileInFlightIO);
};

// ---------------------------------------------------------------------------

// Runs on a worker thread.
void FileBackgroundIO::Read() {
  if (file_->Read(const_cast<void*>(buf_), buf_len_, offset_)) {
    result_ = static_cast<int>(buf_len_);
  } else {
    result_ = -1;
  }
  controller_->OnIOComplete(this);
}

// Runs on a worker thread.
void FileBackgroundIO::Write() {
  bool rv = file_->Write(buf_, buf_len_, offset_);

  result_ = rv ? static_cast<int>(buf_len_) : -1;
  controller_->OnIOComplete(this);
}

// ---------------------------------------------------------------------------

void FileInFlightIO::PostRead(disk_cache::File *file, void* buf, size_t buf_len,
                          size_t offset, disk_cache::FileIOCallback *callback) {
  scoped_refptr<FileBackgroundIO> operation(
      new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
  file->AddRef();  // Balanced on OnOperationComplete()

  base::WorkerPool::PostTask(FROM_HERE,
      NewRunnableMethod(operation.get(), &FileBackgroundIO::Read), true);
  OnOperationPosted(operation);
}

void FileInFlightIO::PostWrite(disk_cache::File* file, const void* buf,
                           size_t buf_len, size_t offset,
                           disk_cache::FileIOCallback* callback) {
  scoped_refptr<FileBackgroundIO> operation(
      new FileBackgroundIO(file, buf, buf_len, offset, callback, this));
  file->AddRef();  // Balanced on OnOperationComplete()

  base::WorkerPool::PostTask(FROM_HERE,
      NewRunnableMethod(operation.get(), &FileBackgroundIO::Write), true);
  OnOperationPosted(operation);
}

// Runs on the IO thread.
void FileInFlightIO::OnOperationComplete(disk_cache::BackgroundIO* operation,
                                         bool cancel) {
  FileBackgroundIO* op = static_cast<FileBackgroundIO*>(operation);

  disk_cache::FileIOCallback* callback = op->callback();
  int bytes = operation->result();

  // Release the references acquired in PostRead / PostWrite.
  op->file()->Release();
  callback->OnFileIOComplete(bytes);
}

// A static object tha will broker all async operations.
FileInFlightIO* s_file_operations = NULL;

// Returns the current FileInFlightIO.
FileInFlightIO* GetFileInFlightIO() {
  if (!s_file_operations) {
    s_file_operations = new FileInFlightIO;
  }
  return s_file_operations;
}

// Deletes the current FileInFlightIO.
void DeleteFileInFlightIO() {
  DCHECK(s_file_operations);
  delete s_file_operations;
  s_file_operations = NULL;
}

}  // namespace

namespace disk_cache {

File::File(base::PlatformFile file)
    : init_(true),
      mixed_(true),
      platform_file_(file),
      sync_platform_file_(base::kInvalidPlatformFileValue) {
}

bool File::Init(const FilePath& name) {
  if (init_)
    return false;

  int flags = base::PLATFORM_FILE_OPEN |
              base::PLATFORM_FILE_READ |
              base::PLATFORM_FILE_WRITE;
  platform_file_ = base::CreatePlatformFile(name, flags, NULL, NULL);
  if (platform_file_ < 0) {
    platform_file_ = 0;
    return false;
  }

  init_ = true;
  return true;
}

base::PlatformFile File::platform_file() const {
  return platform_file_;
}

bool File::IsValid() const {
  if (!init_)
    return false;
  return (base::kInvalidPlatformFileValue != platform_file_);
}

bool File::Read(void* buffer, size_t buffer_len, size_t offset) {
  DCHECK(init_);
  if (buffer_len > ULONG_MAX || offset > LONG_MAX)
    return false;

  int ret = pread(platform_file_, buffer, buffer_len, offset);
  return (static_cast<size_t>(ret) == buffer_len);
}

bool File::Write(const void* buffer, size_t buffer_len, size_t offset) {
  DCHECK(init_);
  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
    return false;

  int ret = pwrite(platform_file_, buffer, buffer_len, offset);
  return (static_cast<size_t>(ret) == buffer_len);
}

// We have to increase the ref counter of the file before performing the IO to
// prevent the completion to happen with an invalid handle (if the file is
// closed while the IO is in flight).
bool File::Read(void* buffer, size_t buffer_len, size_t offset,
                FileIOCallback* callback, bool* completed) {
  DCHECK(init_);
  if (!callback) {
    if (completed)
      *completed = true;
    return Read(buffer, buffer_len, offset);
  }

  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
    return false;

  GetFileInFlightIO()->PostRead(this, buffer, buffer_len, offset, callback);

  *completed = false;
  return true;
}

bool File::Write(const void* buffer, size_t buffer_len, size_t offset,
                 FileIOCallback* callback, bool* completed) {
  DCHECK(init_);
  if (!callback) {
    if (completed)
      *completed = true;
    return Write(buffer, buffer_len, offset);
  }

  return AsyncWrite(buffer, buffer_len, offset, callback, completed);
}

bool File::SetLength(size_t length) {
  DCHECK(init_);
  if (length > ULONG_MAX)
    return false;

  return 0 == ftruncate(platform_file_, length);
}

size_t File::GetLength() {
  DCHECK(init_);
  size_t ret = lseek(platform_file_, 0, SEEK_END);
  return ret;
}

// Static.
void File::WaitForPendingIO(int* num_pending_io) {
  // We may be running unit tests so we should allow be able to reset the
  // message loop.
  GetFileInFlightIO()->WaitForPendingIO();
  DeleteFileInFlightIO();
}

File::~File() {
  if (IsValid())
    close(platform_file_);
}

bool File::AsyncWrite(const void* buffer, size_t buffer_len, size_t offset,
                      FileIOCallback* callback, bool* completed) {
  DCHECK(init_);
  if (buffer_len > ULONG_MAX || offset > ULONG_MAX)
    return false;

  GetFileInFlightIO()->PostWrite(this, buffer, buffer_len, offset, callback);

  if (completed)
    *completed = false;
  return true;
}

}  // namespace disk_cache
<|endoftext|>


<commit_before>#ifndef SRC_CORE_CONNECTION_HPP_
#define SRC_CORE_CONNECTION_HPP_

#include <type_traits>

#include "core/function_traits.hpp"
#include "core/traits.hpp"

/**
 * \brief defines basic connection object, which is connectable.
 * \tparam source_t the source node of the connection, data flows from here to the sink.
 * \tparam sink_t is the sink node of the connection, data goes here.
 * \tparam param_void is true if the parameter of operator() of source_t is void
 * \result_void param_void is true if the result of operator() of sink_t is void
 * \payload_void param_void is true if the result of operator() of source_t is void
 * the return value of source_t needs to be convertible to the parameter of sink_t.
 */
template<
		class source_t,
		class sink_t,
		bool param_void,
		bool result_void,
		bool payload_void
		>
struct connection;

// metafunction which creates correct Connection type by checking
// if parameters or result types are void.
template<class source_t, class sink_t>
struct connection_trait
{

	typedef typename result_of<source_t>::type source_result;
	typedef typename result_of<sink_t>::type sink_result;

	static const bool param_is_void = utils::function_traits<source_t>::arity == 0;
	static const bool result_is_void = std::is_void<sink_result>::value;
	static const bool payload_is_void = std::is_void<source_result>::value;

	typedef connection
			<
			source_t,
			sink_t,
			param_is_void,
			result_is_void,
			payload_is_void
			> type;
};

namespace detail
{
//template<class source_t, class sink_t>
//typename connection_trait<source_t, sink_t>::type connect_impl
//		(
//		const source_t& source,
//		const sink_t& sink
//		)
//{
//	return typename connection_trait<source_t, sink_t>::type {source, sink};
//}

template<class sink_t, class source_t, class Enable = void>
struct connect_impl
{
	typename connection_trait<source_t, sink_t>::type
	operator()(const source_t& source, const sink_t& sink)
	{
		return typename connection_trait<source_t, sink_t>::type {source, sink};
	}
};

/**
 * sink port case
 */
template<class sink_t, class source_t>
struct connect_impl<sink_t, source_t, typename std::enable_if<fc::is_sink_port<sink_t>::value>::type >
{
	void operator()(source_t source, sink_t sink)
	{
		sink.connect(source);
	}
};

} // namespace detail

/**
 * \brief Connect takes two connectables and returns a connection.
 *
 * \param source is the source of the data flowing through the connection.
 * \param sink is the target of the data flowing through the connection.
 * \returns connection object which has its type determined by the source_t and sink_t.
 *
 * If source_t and sink_t fulfill connectable, the result is connectable.
 * If one of source_t and sink_t fulfills receive_connectable and the other fulfills send_connectable,
 * the result is not non_connectable.
 * If either source_t or sink_t fulfill send_connectable, the result is send_connectable.
 * If either source_t or sink_t fulfill receive_connectable, the result is receive_connectable.
 */
template<class source_t, class sink_t,
	class = typename std::enable_if<is_connectable<source_t>::value>::type,
	class = typename std::enable_if<is_connectable<sink_t>::value>::type>
auto connect(const source_t& source, const sink_t& sink)
{
	return detail::connect_impl<sink_t, source_t>()(source, sink);
}

/**
 * \brief Operator >> takes two connectables and returns a connection.
 *
 * This operator is syntactic sugar for Connect.
 */
template<class source_t, class sink_t>
auto operator >>(const source_t& source, const sink_t& sink)
{
	return connect(source, sink);
}

/***************** Implementation *********************************************
 *
 * Template specializations on param_is_void, result_is_void and payload_is_void.
 * These specializations are necessary since different parts of the function bodies
 * of operator() are ill formed if parameters, payload or results are void.
 *
 * std::enable_if on the operator() does not work in all cases, since the metafunctions
 * param_type and result_of can also be ill formed, when paramt_t and result_t are void.
 *
 */

/// Specialization in case no value is void
template<class source_t,class sink_t>
struct connection<source_t, sink_t, false, false, false>
{
	source_t source;
	sink_t sink;
	typedef typename param_type<source_t>::type param_type;
	typedef typename result_of<sink_t>::type sink_result;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()(const param_type&& p)
	{
		// execute source with parameter and execute sink with result from source.
		return sink(source(p));
	}
};

/// Partial specialization no parameter
template<class source_t,class sink_t>
struct connection<source_t, sink_t, true, false, false>
{
	source_t source;
	sink_t sink;
	typedef typename result_of<sink_t>::type sink_result;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()()
	{
		// execute source and execute sink with result from source.
		return sink(source());
	}
};

/// partial  specialization for no parameter and no return value
template<class source_t, class sink_t>
struct connection<source_t, sink_t, true, true, false>
{
	source_t source;
	sink_t sink;
	void operator()()
	{
		// execute source and execute sink with result from source.
		sink(source());
	}
};

/// partial specialization for no parameter and no payload
template<class source_t, class sink_t>
struct connection<source_t, sink_t, true, false, true>
{
	source_t source;
	sink_t sink;
	typedef typename result_of<sink_t>::type sink_result;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()()
	{
		// execute source and execute sink separately since source has no result.
		source();
		return sink();
	}
};

/// partial specialization for no parameter and no return value and no payload
template<class source_t,class sink_t>
struct connection<source_t, sink_t, true, true, true>
{
	source_t source;
	sink_t sink;
	void operator()()
	{
		// execute source and execute sink separately since source has no result.
		source();
		sink();
	}
};

// Special case of connection which has no return value
template<class source_t, class sink_t>
struct connection<source_t, sink_t,false, true, false>
{
	source_t source;
	sink_t sink;
	typedef typename param_type<source_t>::type param_type;
	void operator()(const param_type&& p)
	{
		// execute source with parameter and execute sink with result from source.
		sink(source(p));
	}
};

/// Special case, when there is no payload in the connnection
template<class source_t,class sink_t>
struct connection<source_t, sink_t, false, false, true>
{
	source_t source;
	sink_t sink;
	typedef typename result_of<sink_t>::type sink_result;
	typedef typename param_type<source_t>::type param_type;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()(const param_type&& p)
	{
		// execute source and execute sink separately.
		source(p);
		return sink();
	}
};

/// Special case, when there is no payload and no result in the connection
template<class source_t,class sink_t>
struct connection<source_t, sink_t, false, true, true>
{
	source_t source;
	sink_t sink;
	typedef typename param_type<source_t>::type param_type;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	void operator()(const param_type&& p)
	{
		source(p);
		sink();
	}
};

#endif /* SRC_CORE_CONNECTION_HPP_ */
<commit_msg>Remove old connection_impl implementation<commit_after>#ifndef SRC_CORE_CONNECTION_HPP_
#define SRC_CORE_CONNECTION_HPP_

#include <type_traits>

#include "core/function_traits.hpp"
#include "core/traits.hpp"

/**
 * \brief defines basic connection object, which is connectable.
 * \tparam source_t the source node of the connection, data flows from here to the sink.
 * \tparam sink_t is the sink node of the connection, data goes here.
 * \tparam param_void is true if the parameter of operator() of source_t is void
 * \result_void param_void is true if the result of operator() of sink_t is void
 * \payload_void param_void is true if the result of operator() of source_t is void
 * the return value of source_t needs to be convertible to the parameter of sink_t.
 */
template<
		class source_t,
		class sink_t,
		bool param_void,
		bool result_void,
		bool payload_void
		>
struct connection;

// metafunction which creates correct Connection type by checking
// if parameters or result types are void.
template<class source_t, class sink_t>
struct connection_trait
{

	typedef typename result_of<source_t>::type source_result;
	typedef typename result_of<sink_t>::type sink_result;

	static const bool param_is_void = utils::function_traits<source_t>::arity == 0;
	static const bool result_is_void = std::is_void<sink_result>::value;
	static const bool payload_is_void = std::is_void<source_result>::value;

	typedef connection
			<
			source_t,
			sink_t,
			param_is_void,
			result_is_void,
			payload_is_void
			> type;
};

namespace detail
{

template<class sink_t, class source_t, class Enable = void>
struct connect_impl
{
	typename connection_trait<source_t, sink_t>::type
	operator()(const source_t& source, const sink_t& sink)
	{
		return typename connection_trait<source_t, sink_t>::type {source, sink};
	}
};

/**
 * sink port case
 */
template<class sink_t, class source_t>
struct connect_impl<sink_t, source_t, typename std::enable_if<fc::is_sink_port<sink_t>::value>::type >
{
	void operator()(source_t source, sink_t sink)
	{
		sink.connect(source);
	}
};

} // namespace detail

/**
 * \brief Connect takes two connectables and returns a connection.
 *
 * \param source is the source of the data flowing through the connection.
 * \param sink is the target of the data flowing through the connection.
 * \returns connection object which has its type determined by the source_t and sink_t.
 *
 * If source_t and sink_t fulfill connectable, the result is connectable.
 * If one of source_t and sink_t fulfills receive_connectable and the other fulfills send_connectable,
 * the result is not non_connectable.
 * If either source_t or sink_t fulfill send_connectable, the result is send_connectable.
 * If either source_t or sink_t fulfill receive_connectable, the result is receive_connectable.
 */
template<class source_t, class sink_t,
	class = typename std::enable_if<is_connectable<source_t>::value>::type,
	class = typename std::enable_if<is_connectable<sink_t>::value>::type>
auto connect(const source_t& source, const sink_t& sink)
{
	return detail::connect_impl<sink_t, source_t>()(source, sink);
}

/**
 * \brief Operator >> takes two connectables and returns a connection.
 *
 * This operator is syntactic sugar for Connect.
 */
template<class source_t, class sink_t>
auto operator >>(const source_t& source, const sink_t& sink)
{
	return connect(source, sink);
}

/***************** Implementation *********************************************
 *
 * Template specializations on param_is_void, result_is_void and payload_is_void.
 * These specializations are necessary since different parts of the function bodies
 * of operator() are ill formed if parameters, payload or results are void.
 *
 * std::enable_if on the operator() does not work in all cases, since the metafunctions
 * param_type and result_of can also be ill formed, when paramt_t and result_t are void.
 *
 */

/// Specialization in case no value is void
template<class source_t,class sink_t>
struct connection<source_t, sink_t, false, false, false>
{
	source_t source;
	sink_t sink;
	typedef typename param_type<source_t>::type param_type;
	typedef typename result_of<sink_t>::type sink_result;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()(const param_type&& p)
	{
		// execute source with parameter and execute sink with result from source.
		return sink(source(p));
	}
};

/// Partial specialization no parameter
template<class source_t,class sink_t>
struct connection<source_t, sink_t, true, false, false>
{
	source_t source;
	sink_t sink;
	typedef typename result_of<sink_t>::type sink_result;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()()
	{
		// execute source and execute sink with result from source.
		return sink(source());
	}
};

/// partial  specialization for no parameter and no return value
template<class source_t, class sink_t>
struct connection<source_t, sink_t, true, true, false>
{
	source_t source;
	sink_t sink;
	void operator()()
	{
		// execute source and execute sink with result from source.
		sink(source());
	}
};

/// partial specialization for no parameter and no payload
template<class source_t, class sink_t>
struct connection<source_t, sink_t, true, false, true>
{
	source_t source;
	sink_t sink;
	typedef typename result_of<sink_t>::type sink_result;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()()
	{
		// execute source and execute sink separately since source has no result.
		source();
		return sink();
	}
};

/// partial specialization for no parameter and no return value and no payload
template<class source_t,class sink_t>
struct connection<source_t, sink_t, true, true, true>
{
	source_t source;
	sink_t sink;
	void operator()()
	{
		// execute source and execute sink separately since source has no result.
		source();
		sink();
	}
};

// Special case of connection which has no return value
template<class source_t, class sink_t>
struct connection<source_t, sink_t,false, true, false>
{
	source_t source;
	sink_t sink;
	typedef typename param_type<source_t>::type param_type;
	void operator()(const param_type&& p)
	{
		// execute source with parameter and execute sink with result from source.
		sink(source(p));
	}
};

/// Special case, when there is no payload in the connnection
template<class source_t,class sink_t>
struct connection<source_t, sink_t, false, false, true>
{
	source_t source;
	sink_t sink;
	typedef typename result_of<sink_t>::type sink_result;
	typedef typename param_type<source_t>::type param_type;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	sink_result operator()(const param_type&& p)
	{
		// execute source and execute sink separately.
		source(p);
		return sink();
	}
};

/// Special case, when there is no payload and no result in the connection
template<class source_t,class sink_t>
struct connection<source_t, sink_t, false, true, true>
{
	source_t source;
	sink_t sink;
	typedef typename param_type<source_t>::type param_type;
	// auto return type here crashes gcc see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53756
	void operator()(const param_type&& p)
	{
		source(p);
		sink();
	}
};

#endif /* SRC_CORE_CONNECTION_HPP_ */
<|endoftext|>


<commit_before>/***************************************************
 * Alex Palcuie
 * FMI No Stress 2015 - buget - 100 puncte O(N log N + N)
 * alex [dot] palcuie [at] gmail [dot] com
 * http://blog.palcu.ro/
****************************************************/
#include <algorithm>
#include <fstream>
#include <vector>

using namespace std;

#define int64 long long

vector<int> budgets;

int main() {
    ifstream fin("buget.in");
    ofstream fout("buget.out");

    int n; int64 b, sum=0;
    fin >> n >> b;
    for (int i=0; i<n; i++) {
        int x; fin >> x;
        sum += x;
        budgets.push_back(x);
    }

    // Am putea să avem plafonul 1 dacă sumele sunt prea mari
    budgets.push_back(1);
    sort(budgets.begin(), budgets.end(), greater<int>());

    for (int i=0; i<budgets.size(); i++) {
        int64 possible_budget = sum + budgets[i] * i;
        // cerr << possible_budget << endl;
        if (possible_budget <= b) {
            fout << budgets[i] << endl;
            break;
        }
        sum -= budgets[i];
    }

    return 0;
}
<commit_msg>Solve the new problem<commit_after>/***************************************************
 * Alex Palcuie
 * FMI No Stress 2015 - buget - 100 puncte O(N log N + N)
 * alex [dot] palcuie [at] gmail [dot] com
 * http://blog.palcu.ro/
****************************************************/
#include <algorithm>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

#define int64 long long

vector<int> budgets, partial_sums;

int main() {
    ifstream fin("buget.in");
    ofstream fout("buget.out");

    int n; int64 b, max_x=-1;
    fin >> n >> b;
    for (int i=0; i<n; i++) {
        int x; fin >> x;
        max_x = max_x > x ? max_x : x;
        budgets.push_back(x);
    }

    int left = 1, right = max_x, cap = -1;
    while (left <= right) {
        cap = right - (right-left) / 2;
        cerr << "cap = " << cap << endl;
        int64 sum = 0;
        for (auto x : budgets) {
            if (x <= cap) {
                sum += x;
            } else {
                sum += cap;
            }
        }
        cerr << "sum = " << sum << endl;

        if (sum == b) {
            right = cap;
            break;
        } else if (sum > b) {
            right = cap - 1;
        } else {
            left = cap + 1;
        }
    }
    fout << right << "\n";

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>coverity#984096 Uninitialized scalar field<commit_after><|endoftext|>


<commit_before>#include "downloader.h"

#include <QNetworkAccessManager>
#include <QFile>
#include <QPixmap>

namespace {
    QNetworkAccessManager mgr;
}

Downloader::Downloader() {
    m_isAll = false;
    m_currentDownloadingReply = NULL;
}

void Downloader::run()
{
    m_cancelRequested = false;
    QDir currentDir = QDir::current();
    if (!currentDir.cd("downloader")) {
        if (!currentDir.mkdir("downloader")) {
            emit error();
            return;
        }
        currentDir.cd("downloader");
    }

    QDir dir = currentDir;
    if (!m_savePath.isEmpty()) {
        if (!dir.cd(m_savePath)) {
            if (!dir.mkdir(m_savePath)) {
                emit error();
                return;
            }
            dir.cd(m_savePath);
        }
    }

    m_downloadDir = dir;

    downloadSingleFile();

    exec();
}

void Downloader::downloadSingleFile() {
    if (m_downloadSequence.isEmpty()) {
        emit all_completed();
        quit();
        return;
    } else if (m_cancelRequested) {
        emit canceled();
        quit();
        return;
    }

    m_currentDownloadingFile = m_downloadSequence.takeFirst();
    if (m_isAll) {
        QString filename = QUrl(m_currentDownloadingFile).fileName();
        if (filename.endsWith(".jpg")) { // important hack!!
            filename.chop(4);
            filename.append(".png");
        }

        if (m_downloadDir.exists(filename)) {
            emit one_completed(m_currentDownloadingFile);
            downloadSingleFile();
            return;
        }
    }
    m_currentDownloadingReply = mgr.get(QNetworkRequest(QUrl(m_currentDownloadingFile)));
    connect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
    connect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);
}

void Downloader::singleFileError(QNetworkReply::NetworkError /*e*/) {
    m_failedList << m_currentDownloadingFile;
    if (m_currentDownloadingReply != NULL)
        qDebug() << m_currentDownloadingReply->errorString();
}

void Downloader::singleFileFinished() {
    if (m_failedList.contains(m_currentDownloadingFile)) {
        emit one_failed(m_currentDownloadingFile);
        downloadSingleFile();
    } else {
        if (m_currentDownloadingReply->attribute(QNetworkRequest::RedirectionTargetAttribute).isNull()) {
            QString filename = QUrl(m_currentDownloadingFile).fileName();
            QFile file(m_downloadDir.absoluteFilePath(filename));
            file.open(QIODevice::Truncate | QIODevice::WriteOnly);
            file.write(m_currentDownloadingReply->readAll());
            file.close();

            if (filename.endsWith(".jpg")) { // important hack!!
                QString new_filename = filename;
                new_filename.chop(4);
                new_filename.append(".png");
                //m_downloadDir.rename(filename, new_filename);
                QPixmap pm;
                if (pm.load(m_downloadDir.absoluteFilePath(filename))) {
                    if (pm.save(m_downloadDir.absoluteFilePath(new_filename), "PNG")) {
                        m_downloadDir.remove(filename);
                    } else
                        qDebug() << "save png error " << new_filename;
                } else if (pm.load(m_downloadDir.absoluteFilePath(filename), "PNG")) {
                    if (pm.save(m_downloadDir.absoluteFilePath(new_filename), "PNG")) {
                        m_downloadDir.remove(filename);
                    } else
                        qDebug() << "save png error " << new_filename;
                } else
                    qDebug() << "load jpg error " << filename;
            }

            emit one_completed(m_currentDownloadingFile);
            downloadSingleFile();
        } else {
            if (m_cancelRequested) {
                emit canceled();
                quit();
                return;
            }
            QUrl u = m_currentDownloadingReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl().resolved(QUrl(m_currentDownloadingFile));
            qDebug() << "redirect!!";
            qDebug() << u;
            m_currentDownloadingFile = u.toString();
            m_currentDownloadingReply = mgr.get(QNetworkRequest(u));
            connect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
            connect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);
        }
    }
}

Downloader *operator <<(Downloader *downloader, const QString &filename) {
    (*downloader) << filename;
    return downloader;
}

void Downloader::cancel() {
    m_currentDownloadingReply->abort();

    disconnect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
    disconnect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);

    m_failedList << m_currentDownloadingFile;
    qDebug() << m_currentDownloadingFile << "abort";

    m_cancelRequested = true;

    singleFileFinished();
}

void Downloader::timeout() {
    m_currentDownloadingReply->abort();

    disconnect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
    disconnect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);

    m_failedList << m_currentDownloadingFile;
    qDebug() << m_currentDownloadingFile << "timeout";

    singleFileFinished();
}<commit_msg>try to fix infinite self-redirecting<commit_after>#include "downloader.h"

#include <QNetworkAccessManager>
#include <QFile>
#include <QPixmap>

namespace {
    QNetworkAccessManager mgr;
}

Downloader::Downloader() {
    m_isAll = false;
    m_currentDownloadingReply = NULL;
}

void Downloader::run()
{
    m_cancelRequested = false;
    QDir currentDir = QDir::current();
    if (!currentDir.cd("downloader")) {
        if (!currentDir.mkdir("downloader")) {
            emit error();
            return;
        }
        currentDir.cd("downloader");
    }

    QDir dir = currentDir;
    if (!m_savePath.isEmpty()) {
        if (!dir.cd(m_savePath)) {
            if (!dir.mkdir(m_savePath)) {
                emit error();
                return;
            }
            dir.cd(m_savePath);
        }
    }

    m_downloadDir = dir;

    downloadSingleFile();

    exec();
}

void Downloader::downloadSingleFile() {
    if (m_downloadSequence.isEmpty()) {
        emit all_completed();
        quit();
        return;
    } else if (m_cancelRequested) {
        emit canceled();
        quit();
        return;
    }

    m_currentDownloadingFile = m_downloadSequence.takeFirst();
    if (m_isAll) {
        QString filename = QUrl(m_currentDownloadingFile).fileName();
        if (filename.endsWith(".jpg")) { // important hack!!
            filename.chop(4);
            filename.append(".png");
        }

        if (m_downloadDir.exists(filename)) {
            emit one_completed(m_currentDownloadingFile);
            downloadSingleFile();
            return;
        }
    }
    m_currentDownloadingReply = mgr.get(QNetworkRequest(QUrl(m_currentDownloadingFile)));
    connect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
    connect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);
}

void Downloader::singleFileError(QNetworkReply::NetworkError /*e*/) {
    m_failedList << m_currentDownloadingFile;
    if (m_currentDownloadingReply != NULL)
        qDebug() << m_currentDownloadingReply->errorString();
}

void Downloader::singleFileFinished() {
    if (m_failedList.contains(m_currentDownloadingFile)) {
        emit one_failed(m_currentDownloadingFile);
        downloadSingleFile();
    } else {
        if (m_currentDownloadingReply->attribute(QNetworkRequest::RedirectionTargetAttribute).isNull()) {
            QString filename = QUrl(m_currentDownloadingFile).fileName();
            QFile file(m_downloadDir.absoluteFilePath(filename));
            file.open(QIODevice::Truncate | QIODevice::WriteOnly);
            file.write(m_currentDownloadingReply->readAll());
            file.close();

            if (filename.endsWith(".jpg")) { // important hack!!
                QString new_filename = filename;
                new_filename.chop(4);
                new_filename.append(".png");
                //m_downloadDir.rename(filename, new_filename);
                QPixmap pm;
                if (pm.load(m_downloadDir.absoluteFilePath(filename))) {
                    if (pm.save(m_downloadDir.absoluteFilePath(new_filename), "PNG")) {
                        m_downloadDir.remove(filename);
                    } else
                        qDebug() << "save png error " << new_filename;
                } else if (pm.load(m_downloadDir.absoluteFilePath(filename), "PNG")) {
                    if (pm.save(m_downloadDir.absoluteFilePath(new_filename), "PNG")) {
                        m_downloadDir.remove(filename);
                    } else
                        qDebug() << "save png error " << new_filename;
                } else
                    qDebug() << "load jpg error " << filename;
            }

            emit one_completed(m_currentDownloadingFile);
            downloadSingleFile();
        } else {
            if (m_cancelRequested) {
                emit canceled();
                quit();
                return;
            }
            QUrl u = m_currentDownloadingReply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
            if (u.isRelative())
                u = u.resolved(QUrl(m_currentDownloadingFile));
            qDebug() << "redirect!!";
            qDebug() << u;
            m_currentDownloadingFile = u.toString();
            m_currentDownloadingReply = mgr.get(QNetworkRequest(u));
            connect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
            connect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);
        }
    }
}

Downloader *operator <<(Downloader *downloader, const QString &filename) {
    (*downloader) << filename;
    return downloader;
}

void Downloader::cancel() {
    m_currentDownloadingReply->abort();

    disconnect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
    disconnect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);

    m_failedList << m_currentDownloadingFile;
    qDebug() << m_currentDownloadingFile << "abort";

    m_cancelRequested = true;

    singleFileFinished();
}

void Downloader::timeout() {
    m_currentDownloadingReply->abort();

    disconnect(m_currentDownloadingReply, ((void (QNetworkReply::*)(QNetworkReply::NetworkError))(&QNetworkReply::error)), this, &Downloader::singleFileError);
    disconnect(m_currentDownloadingReply, &QNetworkReply::finished, this, &Downloader::singleFileFinished);

    m_failedList << m_currentDownloadingFile;
    qDebug() << m_currentDownloadingFile << "timeout";

    singleFileFinished();
}<|endoftext|>


<commit_before>#ifndef DUNE_STUFF_LA_SOLVER_INTERFACE_HH
#define DUNE_STUFF_LA_SOLVER_INTERFACE_HH

#if HAVE_EIGEN
  #include <Eigen/Core>
  #include <Eigen/IterativeLinearSolvers>
#endif

#include <dune/common/exceptions.hh>
#include <dune/common/parametertree.hh>
#include <dune/stuff/la/container/interface.hh>

namespace Dune {
namespace Stuff {
namespace LA {

template< class MatrixImp, class VectorImp >
class SolverInterface
{
  static_assert(std::is_base_of< typename Dune::Stuff::LA::MatrixInterface< typename MatrixImp::Traits >,
                                 MatrixImp >::value,
                "MatrixImp has to be derived from Dune::Stuff::LA::MatrixInterface!");
  static_assert(std::is_base_of< typename Dune::Stuff::LA::VectorInterface< typename VectorImp::Traits >,
                                 VectorImp >::value,
                "MatrixImp has to be derived from Dune::Stuff::LA::MatrixInterface!");
  static_assert(std::is_same< typename MatrixImp::ScalarType,
                              typename VectorImp::ScalarType >::value, "Types do not match!");
public:
  typedef MatrixImp MatrixType;
  typedef VectorImp VectorType;
  typedef typename MatrixType::ScalarType ScalarType;

  // deprecated
  typedef ScalarType ElementType;

  virtual ~SolverInterface()
  {}

  virtual size_t apply(const MatrixType& /*_systemMatrix*/,
                       const VectorType& /*_rhsVector*/,
                       VectorType& /*_solutionVector*/,
                       const Dune::ParameterTree /*description*/) const = 0;
#if HAVE_EIGEN
  size_t translateInfo(const ::Eigen::ComputationInfo& info) const
  {
    switch (info) {
      case ::Eigen::Success: return 0;
      case ::Eigen::NoConvergence: return 1;
      case ::Eigen::NumericalIssue: return 2;
      default: return 3;
    }
  }
#endif

  static Dune::ParameterTree defaultIterativeSettings()
  {
    Dune::ParameterTree description;
    description["maxIter"] = "5000";
    description["precision"] = "1e-12";
    description["verbose"] = "0";
    return description;
  }
}; // class Interface

template< class MatrixImp, class VectorImp >
class SolverNotImplementedForThisMatrixVectorCombination
  : public SolverInterface< MatrixImp, VectorImp >
{
public:
  typedef typename SolverInterface< MatrixImp, VectorImp >::MatrixType   MatrixType;
  typedef typename SolverInterface< MatrixImp, VectorImp >::VectorType   VectorType;
  typedef typename SolverInterface< MatrixImp, VectorImp >::ScalarType  ScalarType;

  SolverNotImplementedForThisMatrixVectorCombination(const std::string msg = "\nERROR: this solver is not implemented for this matrix/vector combination")
  {
    DUNE_THROW(Dune::NotImplemented, msg);
  }

  virtual size_t apply(const MatrixType& /*_systemMatrix*/,
                       const VectorType& /*_rhsVector*/,
                       VectorType& /*_solutionVector*/,
                       const Dune::ParameterTree /*description*/ = Dune::ParameterTree()) const
  {
    return size_t(3);
  }
}; // class SolverNotImplementedForThisMatrixVectorCombination

template< class MatrixImp, class VectorImp, class Enable = void >
class CgSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class CgDiagonalSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class BicgstabSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class BicgstabDiagonalSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class BicgstabILUTSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class DirectSuperLuSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

#if HAVE_FASP
template< class MatrixImp, class VectorImp, class Enable = void >
class AmgSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};
#endif // HAVE_FASP

} // namespace LA
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_LA_SOLVER_INTERFACE_HH
<commit_msg>[la.solver.interface] update include path<commit_after>#ifndef DUNE_STUFF_LA_SOLVER_INTERFACE_HH
#define DUNE_STUFF_LA_SOLVER_INTERFACE_HH

#if HAVE_EIGEN
  #include <Eigen/Core>
  #include <Eigen/IterativeLinearSolvers>
#endif

#include <dune/common/exceptions.hh>
#include <dune/common/parametertree.hh>
#include <dune/stuff/la/container/interfaces.hh>

namespace Dune {
namespace Stuff {
namespace LA {

template< class MatrixImp, class VectorImp >
class SolverInterface
{
  static_assert(std::is_base_of< typename Dune::Stuff::LA::MatrixInterface< typename MatrixImp::Traits >,
                                 MatrixImp >::value,
                "MatrixImp has to be derived from Dune::Stuff::LA::MatrixInterface!");
  static_assert(std::is_base_of< typename Dune::Stuff::LA::VectorInterface< typename VectorImp::Traits >,
                                 VectorImp >::value,
                "MatrixImp has to be derived from Dune::Stuff::LA::MatrixInterface!");
  static_assert(std::is_same< typename MatrixImp::ScalarType,
                              typename VectorImp::ScalarType >::value, "Types do not match!");
public:
  typedef MatrixImp MatrixType;
  typedef VectorImp VectorType;
  typedef typename MatrixType::ScalarType ScalarType;

  // deprecated
  typedef ScalarType ElementType;

  virtual ~SolverInterface()
  {}

  virtual size_t apply(const MatrixType& /*_systemMatrix*/,
                       const VectorType& /*_rhsVector*/,
                       VectorType& /*_solutionVector*/,
                       const Dune::ParameterTree /*description*/) const = 0;
#if HAVE_EIGEN
  size_t translateInfo(const ::Eigen::ComputationInfo& info) const
  {
    switch (info) {
      case ::Eigen::Success: return 0;
      case ::Eigen::NoConvergence: return 1;
      case ::Eigen::NumericalIssue: return 2;
      default: return 3;
    }
  }
#endif

  static Dune::ParameterTree defaultIterativeSettings()
  {
    Dune::ParameterTree description;
    description["maxIter"] = "5000";
    description["precision"] = "1e-12";
    description["verbose"] = "0";
    return description;
  }
}; // class Interface

template< class MatrixImp, class VectorImp >
class SolverNotImplementedForThisMatrixVectorCombination
  : public SolverInterface< MatrixImp, VectorImp >
{
public:
  typedef typename SolverInterface< MatrixImp, VectorImp >::MatrixType   MatrixType;
  typedef typename SolverInterface< MatrixImp, VectorImp >::VectorType   VectorType;
  typedef typename SolverInterface< MatrixImp, VectorImp >::ScalarType  ScalarType;

  SolverNotImplementedForThisMatrixVectorCombination(const std::string msg = "\nERROR: this solver is not implemented for this matrix/vector combination")
  {
    DUNE_THROW(Dune::NotImplemented, msg);
  }

  virtual size_t apply(const MatrixType& /*_systemMatrix*/,
                       const VectorType& /*_rhsVector*/,
                       VectorType& /*_solutionVector*/,
                       const Dune::ParameterTree /*description*/ = Dune::ParameterTree()) const
  {
    return size_t(3);
  }
}; // class SolverNotImplementedForThisMatrixVectorCombination

template< class MatrixImp, class VectorImp, class Enable = void >
class CgSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class CgDiagonalSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class BicgstabSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class BicgstabDiagonalSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class BicgstabILUTSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

template< class MatrixImp, class VectorImp, class Enable = void >
class DirectSuperLuSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};

#if HAVE_FASP
template< class MatrixImp, class VectorImp, class Enable = void >
class AmgSolver
  : public SolverNotImplementedForThisMatrixVectorCombination< MatrixImp, VectorImp >
{};
#endif // HAVE_FASP

} // namespace LA
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_LA_SOLVER_INTERFACE_HH
<|endoftext|>


<commit_before>#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

#pragma warning(disable:4996)

typedef struct edge {
	int start, end, weight;
} Edge;

int up[500000];
int weight[500000];
int n, m, x, y, t;
vector<Edge> edge, selectEdge;

bool comp1(const Edge &x, const Edge &y) {
	return x.weight < y.weight;
}

bool comp2(const Edge &x, const Edge &y) {
	return x.weight > y.weight;
}

int SimpleFind(const int i) {
	int root = i;

	while (up[root] > 0)
		root = up[root];

	return root;
}

void Union(const int i, const int j) {
	int rooti = SimpleFind(i);
	int rootj = SimpleFind(j);

	if (weight[rooti] > weight[rootj]) {
		up[rootj] = rooti;
		weight[rooti] = weight[rooti] + weight[rootj];
		weight[rootj] = 0;
	}
	else if (weight[rooti] < weight[rootj]) {
		up[rooti] = rootj;
		weight[rootj] = weight[rooti] + weight[rootj];
		weight[rooti] = 0;
	}
	else if (weight[rooti] == weight[rootj]) {
		if (rooti > rootj) {
			up[rootj] = rooti;
			weight[rooti] = weight[rooti] + weight[rootj];
			weight[rootj] = 0;
		}
		else {
			up[rooti] = rootj;
			weight[rootj] = weight[rooti] + weight[rootj];
			weight[rooti] = 0;
		}
	}
}

void Kruskal() {
	int edgeCnt = 0;

	while (selectEdge.size() < n) {
		int x = edge[edgeCnt].start, y = edge[edgeCnt].end;
		int p = SimpleFind(x);
		int q = SimpleFind(y);

		if (q != p) {
			Union(q, p);
			selectEdge.push_back({ edge[edgeCnt].start, edge[edgeCnt].end, edge[edgeCnt].weight });
		}
		edgeCnt++;
	}
}

int main() {
	bool(*comp[2])(const Edge &, const Edge &) = { comp1, comp2 };
	int cost[2] = { 0 };

	scanf("%d %d", &n, &m);

	scanf("%d %d %d", &x, &y, &t);
	edge.push_back({ x, y, t });

	for (int i = 0; i < m; i++) {
		scanf("%d %d %d", &x, &y, &t);
		edge.push_back({ x, y, t });
	}

	for (int i = 0; i < 2; i++) {
		sort(edge.begin(), edge.end(), comp[i]);

		for (int j = 0; j < 500000; j++) {
			up[j] = 0;
			weight[j] = 1;
		}

		Kruskal();

		for (int j = 0; j < selectEdge.size(); j++) {
			cost[i] += selectEdge[j].weight;
		}

		selectEdge.clear();
	}

	printf("%d\n", (cost[1] * cost[1]) - (cost[0] * cost[0]));

	return 0;
}<commit_msg>challenge<commit_after>#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

#pragma warning(disable:4996)

typedef struct edge {
	int start, end, weight;
} Edge;

int up[500000];
int weight[500000];
int n, m, x, y, t;
vector<Edge> edge, selectEdge;

bool asc(const Edge &x, const Edge &y) {
	return x.weight < y.weight;
}

bool des(const Edge &x, const Edge &y) {
	return x.weight > y.weight;
}

int SimpleFind(const int i) {
	int root = i;

	while (up[root] > 0)
		root = up[root];

	return root;
}

void Union(const int i, const int j) {
	int rooti = SimpleFind(i);
	int rootj = SimpleFind(j);

	if (weight[rooti] > weight[rootj]) {
		up[rootj] = rooti;
		weight[rooti] = weight[rooti] + weight[rootj];
		weight[rootj] = 0;
	}
	else if (weight[rooti] < weight[rootj]) {
		up[rooti] = rootj;
		weight[rootj] = weight[rooti] + weight[rootj];
		weight[rooti] = 0;
	}
	else if (weight[rooti] == weight[rootj]) {
		if (rooti > rootj) {
			up[rootj] = rooti;
			weight[rooti] = weight[rooti] + weight[rootj];
			weight[rootj] = 0;
		}
		else {
			up[rooti] = rootj;
			weight[rootj] = weight[rooti] + weight[rootj];
			weight[rooti] = 0;
		}
	}
}

void Kruskal() {
	int edgeCnt = 0;

	while (selectEdge.size() < n) {
		int x = edge[edgeCnt].start, y = edge[edgeCnt].end;
		int p = SimpleFind(x);
		int q = SimpleFind(y);

		if (q != p) {
			Union(q, p);
			selectEdge.push_back({ edge[edgeCnt].start, edge[edgeCnt].end, edge[edgeCnt].weight });
		}
		edgeCnt++;
	}
}

int main() {
	bool(*comp[2])(const Edge &, const Edge &) = { asc, des };
	int cost[2] = { 0 };

	scanf("%d %d", &n, &m);

	scanf("%d %d %d", &x, &y, &t);
	edge.push_back({ x, y, t });

	for (int i = 0; i < m; i++) {
		scanf("%d %d %d", &x, &y, &t);
		edge.push_back({ x, y, t });
	}

	for (int i = 0; i < 2; i++) {
		sort(edge.begin(), edge.end(), comp[i]);

		for (int j = 0; j < 500000; j++) {
			up[j] = 0;
			weight[j] = 1;
		}

		Kruskal();

		for (int j = 0; j < selectEdge.size(); j++) {
			cost[i] += selectEdge[j].weight;
		}

		selectEdge.clear();
	}

	printf("%d\n", (cost[1] * cost[1]) - (cost[0] * cost[0]));

	return 0;
}<|endoftext|>