<commit_before>/// \file
/// \ingroup tutorial_tmva
/// \notebook -nodraw
/// This macro provides an example of how to use TMVA for k-folds cross
/// evaluation.
///
/// As input data is used a toy-MC sample consisting of two guassian
/// distributions.
///
/// The output file "TMVA.root" can be analysed with the use of dedicated
/// macros (simply say: root -l <macro.C>), which can be conveniently
/// invoked through a GUI that will appear at the end of the run of this macro.
/// Launch the GUI via the command:
///
/// ```
/// root -l -e 'TMVA::TMVAGui("TMVA.root")'
/// ```
///
/// ## Cross Evaluation
/// Cross evaluation is a special case of k-folds cross validation where the
/// splitting into k folds is computed deterministically. This ensures that the
/// a given event will always end up in the same fold.
///
/// In addition all resulting classifiers are saved and can be applied to new
/// data using `MethodCrossValidation`. One requirement for this to work is a
/// splitting function that is evaluated for each event to determine into what
/// fold it goes (for training/evaluation) or to what classifier (for
/// application).
///
/// ## Split Expression
/// Cross evaluation uses a deterministic split to partition the data into
/// folds called the split expression. The expression can be any valid
/// `TFormula` as long as all parts used are defined.
///
/// For each event the split expression is evaluated to a number and the event
/// is put in the fold corresponding to that number.
///
/// It is recommended to always use `%int([NumFolds])` at the end of the
/// expression.
///
/// The split expression has access to all spectators and variables defined in
/// the dataloader. Additionally, the number of folds in the split can be
/// accessed with `NumFolds` (or `numFolds`).
///
/// ### Example
///  ```
///  "int(fabs([eventID]))%int([NumFolds])"
///  ```
///
/// - Project   : TMVA - a ROOT-integrated toolkit for multivariate data analysis
/// - Package   : TMVA
/// - Root Macro: TMVACrossValidation
///
/// \macro_output
/// \macro_code
/// \author Kim Albertsson (adapted from code originally by Andreas Hoecker)

#include <cstdlib>
#include <iostream>
#include <map>
#include <string>

#include "TChain.h"
#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include "TObjString.h"
#include "TSystem.h"
#include "TROOT.h"

#include "TMVA/CrossValidation.h"
#include "TMVA/DataLoader.h"
#include "TMVA/Factory.h"
#include "TMVA/Tools.h"
#include "TMVA/TMVAGui.h"

// Helper function to load data into TTrees.
TTree *genTree(Int_t nPoints, Double_t offset, Double_t scale, UInt_t seed = 100)
{
   TRandom3 rng(seed);
   Float_t x = 0;
   Float_t y = 0;
   UInt_t eventID = 0;

   TTree *data = new TTree();
   data->Branch("x", &x, "x/F");
   data->Branch("y", &y, "y/F");
   data->Branch("eventID", &eventID, "eventID/I");

   for (Int_t n = 0; n < nPoints; ++n) {
      x = rng.Gaus(offset, scale);
      y = rng.Gaus(offset, scale);

      // For our simple example it is enough that the id's are uniformly
      // distributed and independent of the data.
      ++eventID;

      data->Fill();
   }

   // Important: Disconnects the tree from the memory locations of x and y.
   data->ResetBranchAddresses();
   return data;
}

int TMVACrossValidation()
{
   // This loads the library
   TMVA::Tools::Instance();

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

   // Load the data into TTrees. If you load data from file you can use a
   // variant of
   // ```
   // TString filename = "/path/to/file";
   // TFile * input = TFile::Open( filename );
   // TTree * signalTree = (TTree*)input->Get("TreeName");
   // ```
   TTree *sigTree = genTree(1000, 1.0, 1.0, 100);
   TTree *bkgTree = genTree(1000, -1.0, 1.0, 101);

   // Create a ROOT output file where TMVA will store ntuples, histograms, etc.
   TString outfileName("TMVA.root");
   TFile *outputFile = TFile::Open(outfileName, "RECREATE");

   // DataLoader definitions; We declare variables in the tree so that TMVA can
   // find them. For more information see TMVAClassification tutorial.
   TMVA::DataLoader *dataloader = new TMVA::DataLoader("dataset");

   // Data variables
   dataloader->AddVariable("x", 'F');
   dataloader->AddVariable("y", 'F');

   // Spectator used for split
   dataloader->AddSpectator("eventID", 'I');

   // Attaches the trees so they can be read from
   dataloader->AddSignalTree(sigTree, 1.0);
   dataloader->AddBackgroundTree(bkgTree, 1.0);

   // The CV mechanism of TMVA splits up the training set into several folds.
   // The test set is currently left unused. The `nTest_ClassName=1` assigns
   // one event to the the test set for each class and puts the rest in the
   // training set. A value of 0 is a special value and would split the
   // datasets 50 / 50.
   dataloader->PrepareTrainingAndTestTree("", "",
                                          "nTest_Signal=1"
                                          ":nTest_Background=1"
                                          ":SplitMode=Random"
                                          ":NormMode=NumEvents"
                                          ":!V");

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

   //
   // This sets up a CrossValidation class (which wraps a TMVA::Factory
   // internally) for 2-fold cross validation.
   //
   // The split type can be "Random", "RandomStratified" or "Deterministic".
   // For the last option, check the comment below. Random splitting randomises
   // the order of events and distributes events as evenly as possible.
   // RandomStratified applies the same logic but distributes events within a
   // class as evenly as possible over the folds.
   //
   UInt_t numFolds = 2;
   TString analysisType = "Classification";
   TString splitType = "Random";
   TString splitExpr = "";

   //
   // One can also use a custom splitting function for producing the folds.
   // The example uses a dataset spectator `eventID`.
   //
   // The idea here is that eventID should be an event number that is integral,
   // random and independent of the data, generated only once. This last
   // property ensures that if a calibration is changed the same event will
   // still be assigned the same fold.
   //
   // This can be used to use the cross validated classifiers in application,
   // a technique that can simplify statistical analysis.
   //
   // If you want to run TMVACrossValidationApplication, make sure you have
   // run this tutorial with the below line uncommented first.
   //

   // TString splitExpr = "int(fabs([eventID]))%int([NumFolds])";

   TString cvOptions = Form("!V"
                            ":!Silent"
                            ":ModelPersistence"
                            ":AnalysisType=%s"
                            ":SplitType=%s"
                            ":NumFolds=%i"
                            ":SplitExpr=%s",
                            analysisType.Data(), splitType.Data(), numFolds,
                            splitExpr.Data());

   TMVA::CrossValidation cv{"TMVACrossValidation", dataloader, outputFile, cvOptions};

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

   //
   // Books a method to use for evaluation
   //
   cv.BookMethod(TMVA::Types::kBDT, "BDTG",
                 "!H:!V:NTrees=100:MinNodeSize=2.5%:BoostType=Grad"
                 ":NegWeightTreatment=Pray:Shrinkage=0.10:nCuts=20"
                 ":MaxDepth=2");

   cv.BookMethod(TMVA::Types::kFisher, "Fisher",
                 "!H:!V:Fisher:VarTransform=None");

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

   //
   // Train, test and evaluate the booked methods.
   // Evaluates the booked methods once for each fold and aggregates the result
   // in the specified output file.
   //
   cv.Evaluate();

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

   //
   // Process some output programatically, printing the ROC score for each
   // booked method.
   //
   size_t iMethod = 0;
   for (auto && result : cv.GetResults()) {
      std::cout << "Summary for method " << cv.GetMethods()[iMethod++].GetValue<TString>("MethodName")
                << std::endl;
      for (UInt_t iFold = 0; iFold<cv.GetNumFolds(); ++iFold) {
         std::cout << "\tFold " << iFold << ": "
                   << "ROC int: " << result.GetROCValues()[iFold]
                   << ", "
                   << "BkgEff@SigEff=0.3: " << result.GetEff30Values()[iFold]
                   << std::endl;
      }
   }

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

   //
   // Save the output
   //
   outputFile->Close();

   std::cout << "==> Wrote root file: " << outputFile->GetName() << std::endl;
   std::cout << "==> TMVACrossValidation is done!" << std::endl;

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

   //
   // Launch the GUI for the root macros
   //
   if (!gROOT->IsBatch()) {
      // Draw cv-specific graphs
      cv.GetResults()[0].DrawAvgROCCurve(kTRUE, "Avg ROC for BDTG");
      cv.GetResults()[0].DrawAvgROCCurve(kTRUE, "Avg ROC for Fisher");

      // You can also use the classical gui
      TMVA::TMVAGui(outfileName);
   }

   return 0;
}

//
// This is used if the macro is compiled. If run through ROOT with
// `root -l -b -q MACRO.C` or similar it is unused.
//
int main(int argc, char **argv)
{
   TMVACrossValidation();
}
<commit_msg>[TMVA] CV - Add workaround for large event numbers (#2971)<commit_after>/// \file
/// \ingroup tutorial_tmva
/// \notebook -nodraw
/// This macro provides an example of how to use TMVA for k-folds cross
/// evaluation.
///
/// As input data is used a toy-MC sample consisting of two guassian
/// distributions.
///
/// The output file "TMVA.root" can be analysed with the use of dedicated
/// macros (simply say: root -l <macro.C>), which can be conveniently
/// invoked through a GUI that will appear at the end of the run of this macro.
/// Launch the GUI via the command:
///
/// ```
/// root -l -e 'TMVA::TMVAGui("TMVA.root")'
/// ```
///
/// ## Cross Evaluation
/// Cross evaluation is a special case of k-folds cross validation where the
/// splitting into k folds is computed deterministically. This ensures that the
/// a given event will always end up in the same fold.
///
/// In addition all resulting classifiers are saved and can be applied to new
/// data using `MethodCrossValidation`. One requirement for this to work is a
/// splitting function that is evaluated for each event to determine into what
/// fold it goes (for training/evaluation) or to what classifier (for
/// application).
///
/// ## Split Expression
/// Cross evaluation uses a deterministic split to partition the data into
/// folds called the split expression. The expression can be any valid
/// `TFormula` as long as all parts used are defined.
///
/// For each event the split expression is evaluated to a number and the event
/// is put in the fold corresponding to that number.
///
/// It is recommended to always use `%int([NumFolds])` at the end of the
/// expression.
///
/// The split expression has access to all spectators and variables defined in
/// the dataloader. Additionally, the number of folds in the split can be
/// accessed with `NumFolds` (or `numFolds`).
///
/// ### Example
///  ```
///  "int(fabs([eventID]))%int([NumFolds])"
///  ```
///
/// - Project   : TMVA - a ROOT-integrated toolkit for multivariate data analysis
/// - Package   : TMVA
/// - Root Macro: TMVACrossValidation
///
/// \macro_output
/// \macro_code
/// \author Kim Albertsson (adapted from code originally by Andreas Hoecker)

#include <cstdlib>
#include <iostream>
#include <map>
#include <string>

#include "TChain.h"
#include "TFile.h"
#include "TTree.h"
#include "TString.h"
#include "TObjString.h"
#include "TSystem.h"
#include "TROOT.h"

#include "TMVA/CrossValidation.h"
#include "TMVA/DataLoader.h"
#include "TMVA/Factory.h"
#include "TMVA/Tools.h"
#include "TMVA/TMVAGui.h"

// Helper function to load data into TTrees.
TTree *genTree(Int_t nPoints, Double_t offset, Double_t scale, UInt_t seed = 100)
{
   TRandom3 rng(seed);
   Float_t x = 0;
   Float_t y = 0;
   UInt_t eventID = 0;

   TTree *data = new TTree();
   data->Branch("x", &x, "x/F");
   data->Branch("y", &y, "y/F");
   data->Branch("eventID", &eventID, "eventID/I");

   for (Int_t n = 0; n < nPoints; ++n) {
      x = rng.Gaus(offset, scale);
      y = rng.Gaus(offset, scale);

      // For our simple example it is enough that the id's are uniformly
      // distributed and independent of the data.
      ++eventID;

      data->Fill();
   }

   // Important: Disconnects the tree from the memory locations of x and y.
   data->ResetBranchAddresses();
   return data;
}

int TMVACrossValidation()
{
   // This loads the library
   TMVA::Tools::Instance();

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

   // Load the data into TTrees. If you load data from file you can use a
   // variant of
   // ```
   // TString filename = "/path/to/file";
   // TFile * input = TFile::Open( filename );
   // TTree * signalTree = (TTree*)input->Get("TreeName");
   // ```
   TTree *sigTree = genTree(1000, 1.0, 1.0, 100);
   TTree *bkgTree = genTree(1000, -1.0, 1.0, 101);

   // Create a ROOT output file where TMVA will store ntuples, histograms, etc.
   TString outfileName("TMVA.root");
   TFile *outputFile = TFile::Open(outfileName, "RECREATE");

   // DataLoader definitions; We declare variables in the tree so that TMVA can
   // find them. For more information see TMVAClassification tutorial.
   TMVA::DataLoader *dataloader = new TMVA::DataLoader("dataset");

   // Data variables
   dataloader->AddVariable("x", 'F');
   dataloader->AddVariable("y", 'F');

   // Spectator used for split
   dataloader->AddSpectator("eventID", 'I');

   // NOTE: Currently TMVA treats all input variables, spectators etc as
   //       floats. Thus, if the absolute value of the input is too large
   //       there can be precision loss. This can especially be a problem for
   //       cross validation with large event numbers.
   //       A workaround is to define your splitting variable as:
   //           `dataloader->AddSpectator("eventID := eventID % 4096", 'I');`
   //       where 4096 should be a number much larger than the number of folds
   //       you intend to run with.

   // Attaches the trees so they can be read from
   dataloader->AddSignalTree(sigTree, 1.0);
   dataloader->AddBackgroundTree(bkgTree, 1.0);

   // The CV mechanism of TMVA splits up the training set into several folds.
   // The test set is currently left unused. The `nTest_ClassName=1` assigns
   // one event to the the test set for each class and puts the rest in the
   // training set. A value of 0 is a special value and would split the
   // datasets 50 / 50.
   dataloader->PrepareTrainingAndTestTree("", "",
                                          "nTest_Signal=1"
                                          ":nTest_Background=1"
                                          ":SplitMode=Random"
                                          ":NormMode=NumEvents"
                                          ":!V");

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

   //
   // This sets up a CrossValidation class (which wraps a TMVA::Factory
   // internally) for 2-fold cross validation.
   //
   // The split type can be "Random", "RandomStratified" or "Deterministic".
   // For the last option, check the comment below. Random splitting randomises
   // the order of events and distributes events as evenly as possible.
   // RandomStratified applies the same logic but distributes events within a
   // class as evenly as possible over the folds.
   //
   UInt_t numFolds = 2;
   TString analysisType = "Classification";
   TString splitType = "Random";
   TString splitExpr = "";

   //
   // One can also use a custom splitting function for producing the folds.
   // The example uses a dataset spectator `eventID`.
   //
   // The idea here is that eventID should be an event number that is integral,
   // random and independent of the data, generated only once. This last
   // property ensures that if a calibration is changed the same event will
   // still be assigned the same fold.
   //
   // This can be used to use the cross validated classifiers in application,
   // a technique that can simplify statistical analysis.
   //
   // If you want to run TMVACrossValidationApplication, make sure you have
   // run this tutorial with the below line uncommented first.
   //

   // TString splitExpr = "int(fabs([eventID]))%int([NumFolds])";

   TString cvOptions = Form("!V"
                            ":!Silent"
                            ":ModelPersistence"
                            ":AnalysisType=%s"
                            ":SplitType=%s"
                            ":NumFolds=%i"
                            ":SplitExpr=%s",
                            analysisType.Data(), splitType.Data(), numFolds,
                            splitExpr.Data());

   TMVA::CrossValidation cv{"TMVACrossValidation", dataloader, outputFile, cvOptions};

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

   //
   // Books a method to use for evaluation
   //
   cv.BookMethod(TMVA::Types::kBDT, "BDTG",
                 "!H:!V:NTrees=100:MinNodeSize=2.5%:BoostType=Grad"
                 ":NegWeightTreatment=Pray:Shrinkage=0.10:nCuts=20"
                 ":MaxDepth=2");

   cv.BookMethod(TMVA::Types::kFisher, "Fisher",
                 "!H:!V:Fisher:VarTransform=None");

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

   //
   // Train, test and evaluate the booked methods.
   // Evaluates the booked methods once for each fold and aggregates the result
   // in the specified output file.
   //
   cv.Evaluate();

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

   //
   // Process some output programatically, printing the ROC score for each
   // booked method.
   //
   size_t iMethod = 0;
   for (auto && result : cv.GetResults()) {
      std::cout << "Summary for method " << cv.GetMethods()[iMethod++].GetValue<TString>("MethodName")
                << std::endl;
      for (UInt_t iFold = 0; iFold<cv.GetNumFolds(); ++iFold) {
         std::cout << "\tFold " << iFold << ": "
                   << "ROC int: " << result.GetROCValues()[iFold]
                   << ", "
                   << "BkgEff@SigEff=0.3: " << result.GetEff30Values()[iFold]
                   << std::endl;
      }
   }

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

   //
   // Save the output
   //
   outputFile->Close();

   std::cout << "==> Wrote root file: " << outputFile->GetName() << std::endl;
   std::cout << "==> TMVACrossValidation is done!" << std::endl;

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

   //
   // Launch the GUI for the root macros
   //
   if (!gROOT->IsBatch()) {
      // Draw cv-specific graphs
      cv.GetResults()[0].DrawAvgROCCurve(kTRUE, "Avg ROC for BDTG");
      cv.GetResults()[0].DrawAvgROCCurve(kTRUE, "Avg ROC for Fisher");

      // You can also use the classical gui
      TMVA::TMVAGui(outfileName);
   }

   return 0;
}

//
// This is used if the macro is compiled. If run through ROOT with
// `root -l -b -q MACRO.C` or similar it is unused.
//
int main(int argc, char **argv)
{
   TMVACrossValidation();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ref.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 13:50:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <ref.hxx>

/****************** SvRefBaseMemberList **********************************/
SV_IMPL_REF_LIST( SvRefBase,SvRefBase* )

/**************************************************************************
#*  SvRefBase::~SvRefBase()
**************************************************************************/
SvRefBase::~SvRefBase()
{
}

/**************************************************************************
#*  SvRefBase::QueryDelete()
**************************************************************************/
void SvRefBase::QueryDelete()
{
    nRefCount = SV_NO_DELETE_REFCOUNT / 2;
    delete this;
}

SvCompatRefBase::~SvCompatRefBase()
{
    (*pFunc)( pObj );
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.3.44); FILE MERGED 2006/09/01 17:54:56 kaib 1.3.44.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ref.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 01:01:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#include <ref.hxx>

/****************** SvRefBaseMemberList **********************************/
SV_IMPL_REF_LIST( SvRefBase,SvRefBase* )

/**************************************************************************
#*  SvRefBase::~SvRefBase()
**************************************************************************/
SvRefBase::~SvRefBase()
{
}

/**************************************************************************
#*  SvRefBase::QueryDelete()
**************************************************************************/
void SvRefBase::QueryDelete()
{
    nRefCount = SV_NO_DELETE_REFCOUNT / 2;
    delete this;
}

SvCompatRefBase::~SvCompatRefBase()
{
    (*pFunc)( pObj );
}

<|endoftext|>


<commit_before>/**
 * Project
 * #    #     #     ######   ######
 * #   #     # #    #     #  #     #
 * #  #     #   #   #     #  #     #
 * ###     #     #  ######   ######
 * #  #    #######  #   #    #   #
 * #   #   #     #  #    #   #    #
 * #    #  #     #  #     #  #     #
 *
 * Copyright (c) 2014, Project KARR
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "AngularInstrument.h"

#include <string>

using namespace std;

AngularInstrument::AngularInstrument() : Instrument() {
}

AngularInstrument::~AngularInstrument() {
}

void AngularInstrument::draw() {
}

void AngularInstrument::update(float newVal) {
}

bool AngularInstrument::parseFromTree(boost::property_tree::ptree &instrumentTree) {

    for (auto &tags : instrumentTree) {
	if (tags.first == "id") {
	    mId = GetInstrumentIdForString(tags.second.get_value<string>());
	    if (mId == IID_UNKNOWN)
		return false;
	}
	else if (tags.first == "area") {
	}
	else if (tags.first == "background") {
	    mBackground.open(tags.second.get_value<string>());
	}
	else if (tags.first == "needle") {
	    mNeedle.open(tags.second.get_value<string>());
	}
    }
    return true;
}
<commit_msg>Parse the area and needle origin.<commit_after>/**
 * Project
 * #    #     #     ######   ######
 * #   #     # #    #     #  #     #
 * #  #     #   #   #     #  #     #
 * ###     #     #  ######   ######
 * #  #    #######  #   #    #   #
 * #   #   #     #  #    #   #    #
 * #    #  #     #  #     #  #     #
 *
 * Copyright (c) 2014, Project KARR
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "AngularInstrument.h"

#include <string>

using namespace std;

AngularInstrument::AngularInstrument() : Instrument() {
}

AngularInstrument::~AngularInstrument() {
}

void AngularInstrument::draw() {
}

void AngularInstrument::update(float newVal) {
}

bool AngularInstrument::parseFromTree(boost::property_tree::ptree &instrumentTree) {

    for (auto &tags : instrumentTree) {
	if (tags.first == "id") {
	    mId = GetInstrumentIdForString(tags.second.get_value<string>());
	    if (mId == IID_UNKNOWN)
		return false;
	}
	else if (tags.first == "area") {
	    auto attrTree = tags.second.get_child("<xmlattr>");
	    mX = attrTree.get_child("x").get_value<int>();
	    mY = attrTree.get_child("y").get_value<int>();
	    mW = attrTree.get_child("w").get_value<int>();
	    mH = attrTree.get_child("h").get_value<int>();
	}
	else if (tags.first == "background") {
	    mBackground.open(tags.second.get_value<string>());
	}
	else if (tags.first == "needle") {
	    mNeedle.open(tags.second.get_value<string>());
	    auto attrTree = tags.second.get_child("<xmlattr>");
	    mNeedleOriginX = attrTree.get_child("x").get_value<int>();
	    mNeedleOriginY = attrTree.get_child("y").get_value<int>();
	}
    }
    return true;
}
<|endoftext|>


<commit_before>/*
 *  BeagleCPUImpl.cpp
 *  BEAGLE
 *
 * @author Andrew Rambaut
 * @author Marc Suchard
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "BeagleCPUImpl.h"

int BeagleCPUImpl::initialize(int bufferCount, int maxTipStateCount,
		int stateCount, int patternCount, int eigenDecompositionCount,
		int matrixCount) {
	kBufferCount = bufferCount;
	kTipCount = maxTipStateCount;
	assert(bufferCount > kTipCount);
	kStateCount = stateCount;
	kPatternCount = patternCount;
	kMatrixCount = matrixCount;

	kMatrixSize = (1 + stateCount) * stateCount;

	cMatrices = (double **) malloc(sizeof(double *) * eigenDecompositionCount);
	if (cMatrices == 0L)
		throw std::bad_alloc();
	storedCMatrices = (double **) malloc(sizeof(double *)
			* eigenDecompositionCount);
	if (storedCMatrices == 0L)
		throw std::bad_alloc();
	eigenValues
			= (double **) malloc(sizeof(double *) * eigenDecompositionCount);
	if (eigenValues == 0L)
		throw std::bad_alloc();
	storedEigenValues = (double **) malloc(sizeof(double *)
			* eigenDecompositionCount);
	if (storedEigenValues == 0L)
		throw std::bad_alloc();

	for (int i = 0; i < eigenDecompositionCount; i++) {
		cMatrices[i] = (double *) malloc(sizeof(double) * stateCount
				* stateCount * stateCount);
		if (cMatrices[i] == 0L)
			throw std::bad_alloc();
		storedCMatrices[i] = (double *) malloc(sizeof(double) * stateCount
				* stateCount * stateCount);
		if (storedCMatrices[i] == 0L)
			throw std::bad_alloc();
		eigenValues[i] = (double *) malloc(sizeof(double) * stateCount);
		if (eigenValues[i] == 0L)
			throw std::bad_alloc();
		storedEigenValues[i] = (double *) malloc(sizeof(double) * stateCount);
		if (storedEigenValues[i] == 0L)
			throw std::bad_alloc();
	}

	branchLengths.resize(kMatrixCount);
	storedBranchLengths.resize(kMatrixCount);

	// a temporary array used in calculating log likelihoods
	integrationTmp.resize(patternCount * stateCount);

	kPartialsSize = kPatternCount * stateCount;

	partials.assign(kBufferCount, 0L);
	tipStates.assign(kTipCount, 0L);

	for (int i = 0; i < kTipCount; i++) {
		tipStates[i] = (int *) malloc(sizeof(int) * kPatternCount);
	}
	for (int i = kTipCount; i < kBufferCount; i++) {
		partials[i] = (double *) malloc(sizeof(double) * kPartialsSize);
		if (partials[i] == 0L)
			throw std::bad_alloc();
	}

	std::vector<double> emptyMat(kMatrixSize);
	transitionMatrices.assign(kMatrixCount, emptyMat);

	fprintf(stderr, "done through here!\n");
	return SUCCESS;
}

BeagleCPUImpl::~BeagleCPUImpl() {
	// free all that stuff...
}

int BeagleCPUImpl::setPartials(int bufferIndex, const double* inPartials) {
	assert(partials[bufferIndex] == 0L);
	partials[bufferIndex] = (double *) malloc(sizeof(double) * kPartialsSize);
	if (partials[bufferIndex] == 0L)
		return OUT_OF_MEMORY_ERROR;
	memcpy(partials[bufferIndex], inPartials, sizeof(double) * kPartialsSize);
	return NO_ERROR;
}

int BeagleCPUImpl::getPartials(int bufferIndex, double *outPartials) {
	memcpy(outPartials, partials[bufferIndex], sizeof(double) * kPartialsSize);
	return NO_ERROR;
}

int BeagleCPUImpl::setTipStates(int tipIndex, const int* inStates) {
	tipStates[tipIndex] = (int *) malloc(sizeof(int) * kPatternCount);
	for (int i = 0; i < kPatternCount; i++) {
		tipStates[tipIndex][i] = (inStates[i] < stateCount ? inStates[i]
				: stateCount);
	}
	return NO_ERROR;
}

int BeagleCPUImpl::setEigenDecomposition(int eigenIndex,
		const double** inEigenVectors, const double** inInverseEigenVectors,
		const double* inEigenValues) {
	int l = 0;
	for (int i = 0; i < stateCount; i++) {
		eigenValues[eigenIndex][i] = inEigenValues[i];

		for (int j = 0; j < stateCount; j++) {
			for (int k = 0; k < stateCount; k++) {
				cMatrices[eigenIndex][l] = inEigenVectors[i][k]
						* inInverseEigenVectors[k][j];
				l++;
			}
		}
	}
	return NO_ERROR;
}

int BeagleCPUImpl::setTransitionMatrix(int matrixIndex, const double* inMatrix) {
	assert(false);
}

void BeagleCPUImpl::updateTransitionMatrices(int eigenIndex,
		const int* probabilityIndices, const int* firstDerivativeIndices,
		const int* secondDervativeIndices, const double* edgeLengths, int count) {
	static double tmp[stateCount];

	for (int u = 0; u < count; u++) {
		int nodeIndex = probabilityIndices[u];

		int n = 0;
		int matrixIndex = 0;
		for (int i = 0; i < stateCount; i++) {
			tmp[i] = exp(eigenValues[eigenIndex][i] * edgeLengths[u]);
		}

		int m = 0;
		for (int i = 0; i < stateCount; i++) {
			for (int j = 0; j < stateCount; j++) {
				double sum = 0.0;
				for (int k = 0; k < stateCount; k++) {
					sum += cMatrices[eigenIndex][m] * tmp[k];
					m++;
				}
				if (sum > 0)
					transitionMatrices[nodeIndex][nodeIndex][n] = sum;
				else
					transitionMatrices[nodeIndex][nodeIndex][n] = 0;

				n++;
			}
			transitionMatrices[nodeIndex][nodeIndex][n] = 1.0;
			n++;
		}
		if (kMatrixCount > 1) {
			eigenIndex++;
		}

	}
	return NO_ERROR;
}

void BeagleCPUImpl::updatePartials(int* operations, int count, int rescale) {

	int x = 0;
	for (int op = 0; op < count; op++) {
		const int parIndex = operations[x++];
		const int child1Index = operations[x++];
		const int child1TransMatIndex = operations[x++];
		const int child1Index = operations[x++];
		const int child1TransMatIndex = operations[x++];

		assert(parIndex < partials.size());
		assert(parIndex >= tipStates.size());
		assert(child1Index < partials.size());
		assert(child2Index < partials.size());
		assert(child1TransMatIndex < transitionMatrices.size());
		assert(child2TransMatIndex < transitionMatrices.size());

		const double * child1TransMat = transitionMatrices[child1TransMatIndex];
		assert(child1TransMat);
		const double * child2TransMat = transitionMatrices[child2TransMatIndex];
		assert(child2TransMat);
		double * destPartial = partials[parIndex];
		assert(destPartial);

		if (child1Index < kTipCount) {
			if (child2Index < kTipCount) {
				updateStatesStates(destPartial, tipStates[child1Index], child1TransMat, tipStates[child2Index], child2TransMat);
			} else {
				updateStatesPartials(destPartial, tipStates[child1Index], child1TransMat, partials[child2Index], child2TransMat);
			}
		} else {
			if (nodeIndex2 < kTipCount) {
				updateStatesPartials(destPartial, tipStates[child2Index], child2TransMat, partials[child1Index], child1TransMat);
			} else {
				updatePartialsPartials(destPartial, partials[child1Index], child1TransMat, partials[child2Index], child2TransMat);
			}
		}
	}
}

/*
 * Calculates partial likelihoods at a node when both children have states.
 */
void BeagleCPUImpl::updateStatesStates(	double * destP,
										const int * child1States,
										const double *child1TransMat,
										const int * child2States,
										const double *child2TransMat)
{

	int v = 0;
	for (int k = 0; k < kPatternCount; k++) {

		const int state0 = child0States[k];
		const int state2 = child2States[k];
		int w = 0;
		for (int i = 0; i < stateCount; i++) {
			destP[v] = child0TransMat[w + state0] * child2TransMat[w + state2];
			v++;
			w += (stateCount + 1);
		}

	}
}

/*
 * Calculates partial likelihoods at a node when one child has states and one has partials.
 */
void BeagleCPUImpl::updateStatesPartials(double * destP, const int * states1, const double *matrices1, const double * partials2, const double *matrices2)
{
	int u = 0;
	int v = 0;

	for (int l = 0; l < kCategoryCount; l++) {
		for (int k = 0; k < kPatternCount; k++) {

			int state1 = states1[k];

			int w = l * kMatrixSize;

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

				double tmp = matrices1[w + state1];

				double sum = 0.0;
				for (int j = 0; j < stateCount; j++) {
					sum += matrices2[w] * partials2[v + j];
					w++;
				}

				// increment for the extra column at the end
				w++;

				destP[u] = tmp * sum;
				u++;
			}

			v += stateCount;
		}
	}

}

void BeagleCPUImpl::updatePartialsPartials(double * destP, const double * partials1, const double *matrices1, const double * partials2, const double *matrices2)
{
	double sum1, sum2;

	int u = 0;
	int v = 0;

	for (int k = 0; k < kPatternCount; k++) {

		int w = 0;

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

			sum1 = sum2 = 0.0;

			for (int j = 0; j < stateCount; j++) {
				sum1 += matrices1[w] * partials1[v + j];
				sum2 += matrices2[w] * partials2[v + j];
				w++;
			}

			// increment for the extra column at the end
			w++;

			destP[u] = sum1 * sum2;

			u++;
		}
		v += stateCount;
	}

}

int BeagleCPUImpl::calculateRootLogLikelihoods(
	const int* bufferIndices,
	int count,
	const double* weights,
	const double** stateFrequencies,
	double* outLogLikelihoods)
{
	// this shouldn't be set to 0 here (we should do it in the loop)
	for (int k = 0; k < kPatternCount; k++)
		outLogLikelihoods[k] = 0.0;

	for (int subsetIndex = 0 ; subsetIndex < count; ++subsetIndex ) {
		assert(subsetIndex < partials.size());
		const int rootPartialIndex = bufferIndices[subsetIndex];
		const double * rootPartials = partials[rootPartialIndex];
		assert(rootPartials);
		const double * frequencies = stateFrequencies[weights];
		const double wt = weights[subsetIndex];
		int u = 0;
		int v = 0;
		for (int k = 0; k < kPatternCount; k++) {

			double sum = 0.0;
			for (int i = 0; i < stateCount; i++) {

				sum += frequencies[i] * rootPartials[v];
				u++;
				v++;
			}
			outLogLikelihoods[k] += sum*wt;
		}
	}

	// this shouldn't be set to 0 here (we should do it in the loop)
	for (int k = 0; k < kPatternCount; k++)
		outLogLikelihoods[k] = log(outLogLikelihoods[k]);
}

int BeagleCPUImpl::calculateEdgeLogLikelihoods(const int * parentBufferIndices,
								 const int* childBufferIndices,
								 const int* probabilityIndices,
								 const int* firstDerivativeIndices,
								 const int* secondDerivativeIndices,
								 int count,
								 const double* weights,
								 const double** stateFrequencies,
								 double* outLogLikelihoods,
								 double* outFirstDerivatives,
								 double* outSecondDerivatives)
{
	assert(0);
}

BeagleImpl* BeagleCPUImplFactory::createImpl(int bufferCount, int tipCount,
		int stateCount, int patternCount, int eigenDecompositionCount,
		int matrixCount) {
	BeagleImpl* impl = new BeagleCPUImpl();
	try {
		if(impl->initialize(nodeCount,tipCount,stateCount,patternCount,categoryCount,matrixCount))
		return impl;
	}
	except(...)
	{
		delete impl;
		throw;
	}
	delete impl;
	return NULL;
}

const char* BeagleCPUImplFactory::getName() {
	return "CPU";
}

<commit_msg>temp - more compile errors<commit_after>/*
 *  BeagleCPUImpl.cpp
 *  BEAGLE
 *
 * @author Andrew Rambaut
 * @author Marc Suchard
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "BeagleCPUImpl.h"

int BeagleCPUImpl::initialize(int bufferCount, int maxTipStateCount,
		int stateCount, int patternCount, int eigenDecompositionCount,
		int matrixCount) {
	kBufferCount = bufferCount;
	kTipCount = maxTipStateCount;
	assert(bufferCount > kTipCount);
	kStateCount = stateCount;
	kPatternCount = patternCount;
	kMatrixCount = matrixCount;

	kMatrixSize = (1 + stateCount) * stateCount;

	cMatrices = (double **) malloc(sizeof(double *) * eigenDecompositionCount);
	if (cMatrices == 0L)
		throw std::bad_alloc();
	storedCMatrices = (double **) malloc(sizeof(double *)
			* eigenDecompositionCount);
	if (storedCMatrices == 0L)
		throw std::bad_alloc();
	eigenValues
			= (double **) malloc(sizeof(double *) * eigenDecompositionCount);
	if (eigenValues == 0L)
		throw std::bad_alloc();
	storedEigenValues = (double **) malloc(sizeof(double *)
			* eigenDecompositionCount);
	if (storedEigenValues == 0L)
		throw std::bad_alloc();

	for (int i = 0; i < eigenDecompositionCount; i++) {
		cMatrices[i] = (double *) malloc(sizeof(double) * stateCount
				* stateCount * stateCount);
		if (cMatrices[i] == 0L)
			throw std::bad_alloc();
		storedCMatrices[i] = (double *) malloc(sizeof(double) * stateCount
				* stateCount * stateCount);
		if (storedCMatrices[i] == 0L)
			throw std::bad_alloc();
		eigenValues[i] = (double *) malloc(sizeof(double) * stateCount);
		if (eigenValues[i] == 0L)
			throw std::bad_alloc();
		storedEigenValues[i] = (double *) malloc(sizeof(double) * stateCount);
		if (storedEigenValues[i] == 0L)
			throw std::bad_alloc();
	}

	branchLengths.resize(kMatrixCount);
	storedBranchLengths.resize(kMatrixCount);

	// a temporary array used in calculating log likelihoods
	integrationTmp.resize(patternCount * stateCount);

	kPartialsSize = kPatternCount * stateCount;

	partials.assign(kBufferCount, 0L);
	tipStates.assign(kTipCount, 0L);

	for (int i = 0; i < kTipCount; i++) {
		tipStates[i] = (int *) malloc(sizeof(int) * kPatternCount);
	}
	for (int i = kTipCount; i < kBufferCount; i++) {
		partials[i] = (double *) malloc(sizeof(double) * kPartialsSize);
		if (partials[i] == 0L)
			throw std::bad_alloc();
	}

	std::vector<double> emptyMat(kMatrixSize);
	transitionMatrices.assign(kMatrixCount, emptyMat);

	fprintf(stderr, "done through here!\n");
	return SUCCESS;
}

BeagleCPUImpl::~BeagleCPUImpl() {
	// free all that stuff...
}

int BeagleCPUImpl::setPartials(int bufferIndex, const double* inPartials) {
	assert(partials[bufferIndex] == 0L);
	partials[bufferIndex] = (double *) malloc(sizeof(double) * kPartialsSize);
	if (partials[bufferIndex] == 0L)
		return OUT_OF_MEMORY_ERROR;
	memcpy(partials[bufferIndex], inPartials, sizeof(double) * kPartialsSize);
	return NO_ERROR;
}

int BeagleCPUImpl::getPartials(int bufferIndex, double *outPartials) {
	memcpy(outPartials, partials[bufferIndex], sizeof(double) * kPartialsSize);
	return NO_ERROR;
}

int BeagleCPUImpl::setTipStates(int tipIndex, const int* inStates) {
	tipStates[tipIndex] = (int *) malloc(sizeof(int) * kPatternCount);
	for (int i = 0; i < kPatternCount; i++) {
		tipStates[tipIndex][i] = (inStates[i] < kStateCount ? inStates[i]
				: kStateCount);
	}
	return NO_ERROR;
}

int BeagleCPUImpl::setEigenDecomposition(int eigenIndex,
		const double** inEigenVectors, const double** inInverseEigenVectors,
		const double* inEigenValues) {
	int l = 0;
	for (int i = 0; i < kStateCount; i++) {
		eigenValues[eigenIndex][i] = inEigenValues[i];

		for (int j = 0; j < kStateCount; j++) {
			for (int k = 0; k < kStateCount; k++) {
				cMatrices[eigenIndex][l] = inEigenVectors[i][k]
						* inInverseEigenVectors[k][j];
				l++;
			}
		}
	}
	return NO_ERROR;
}

int BeagleCPUImpl::setTransitionMatrix(int matrixIndex, const double* inMatrix) {
	assert(false);
}

int BeagleCPUImpl::updateTransitionMatrices(int eigenIndex,
		const int* probabilityIndices, const int* firstDerivativeIndices,
		const int* secondDervativeIndices, const double* edgeLengths, int count) {
	std::vector<double> tmp;
	tmp.resize(kStateCount);

	for (int u = 0; u < count; u++) {
		int nodeIndex = probabilityIndices[u];

		int n = 0;
		int matrixIndex = 0;
		for (int i = 0; i < kStateCount; i++) {
			tmp[i] = exp(eigenValues[eigenIndex][i] * edgeLengths[u]);
		}

		int m = 0;
		for (int i = 0; i < kStateCount; i++) {
			for (int j = 0; j < kStateCount; j++) {
				double sum = 0.0;
				for (int k = 0; k < kStateCount; k++) {
					sum += cMatrices[eigenIndex][m] * tmp[k];
					m++;
				}
				if (sum > 0)
					transitionMatrices[nodeIndex][nodeIndex][n] = sum;
				else
					transitionMatrices[nodeIndex][nodeIndex][n] = 0;

				n++;
			}
			transitionMatrices[nodeIndex][nodeIndex][n] = 1.0;
			n++;
		}
		if (kMatrixCount > 1) {
			eigenIndex++;
		}

	}
	return NO_ERROR;
}

int BeagleCPUImpl::updatePartials(int* operations, int count, int rescale) {

	int x = 0;
	for (int op = 0; op < count; op++) {
		const int parIndex = operations[x++];
		const int child1Index = operations[x++];
		const int child1TransMatIndex = operations[x++];
		const int child1Index = operations[x++];
		const int child1TransMatIndex = operations[x++];

		assert(parIndex < partials.size());
		assert(parIndex >= tipStates.size());
		assert(child1Index < partials.size());
		assert(child2Index < partials.size());
		assert(child1TransMatIndex < transitionMatrices.size());
		assert(child2TransMatIndex < transitionMatrices.size());

		const double * child1TransMat = transitionMatrices[child1TransMatIndex];
		assert(child1TransMat);
		const double * child2TransMat = transitionMatrices[child2TransMatIndex];
		assert(child2TransMat);
		double * destPartial = partials[parIndex];
		assert(destPartial);

		if (child1Index < kTipCount) {
			if (child2Index < kTipCount) {
				updateStatesStates(destPartial, tipStates[child1Index], child1TransMat, tipStates[child2Index], child2TransMat);
			} else {
				updateStatesPartials(destPartial, tipStates[child1Index], child1TransMat, partials[child2Index], child2TransMat);
			}
		} else {
			if (nodeIndex2 < kTipCount) {
				updateStatesPartials(destPartial, tipStates[child2Index], child2TransMat, partials[child1Index], child1TransMat);
			} else {
				updatePartialsPartials(destPartial, partials[child1Index], child1TransMat, partials[child2Index], child2TransMat);
			}
		}
	}
	return NO_ERROR;
}

/*
 * Calculates partial likelihoods at a node when both children have states.
 */
int BeagleCPUImpl::updateStatesStates(	double * destP,
										const int * child1States,
										const double *child1TransMat,
										const int * child2States,
										const double *child2TransMat)
{

	int v = 0;
	for (int k = 0; k < kPatternCount; k++) {

		const int state0 = child0States[k];
		const int state2 = child2States[k];
		int w = 0;
		for (int i = 0; i < kStateCount; i++) {
			destP[v] = child0TransMat[w + state0] * child2TransMat[w + state2];
			v++;
			w += (kStateCount + 1);
		}

	}
	return NO_ERROR;
}

/*
 * Calculates partial likelihoods at a node when one child has states and one has partials.
 */
int BeagleCPUImpl::updateStatesPartials(double * destP, const int * states1, const double *matrices1, const double * partials2, const double *matrices2)
{
	int u = 0;
	int v = 0;

	for (int l = 0; l < kCategoryCount; l++) {
		for (int k = 0; k < kPatternCount; k++) {

			int state1 = states1[k];

			int w = l * kMatrixSize;

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

				double tmp = matrices1[w + state1];

				double sum = 0.0;
				for (int j = 0; j < kStateCount; j++) {
					sum += matrices2[w] * partials2[v + j];
					w++;
				}

				// increment for the extra column at the end
				w++;

				destP[u] = tmp * sum;
				u++;
			}

			v += kStateCount;
		}
	}
	return NO_ERROR;
}

int BeagleCPUImpl::updatePartialsPartials(double * destP, const double * partials1, const double *matrices1, const double * partials2, const double *matrices2)
{
	double sum1, sum2;

	int u = 0;
	int v = 0;

	for (int k = 0; k < kPatternCount; k++) {

		int w = 0;

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

			sum1 = sum2 = 0.0;

			for (int j = 0; j < kStateCount; j++) {
				sum1 += matrices1[w] * partials1[v + j];
				sum2 += matrices2[w] * partials2[v + j];
				w++;
			}

			// increment for the extra column at the end
			w++;

			destP[u] = sum1 * sum2;

			u++;
		}
		v += kStateCount;
	}
	return NO_ERROR;
}

int BeagleCPUImpl::calculateRootLogLikelihoods(
	const int* bufferIndices,
	int count,
	const double* weights,
	const double** stateFrequencies,
	double* outLogLikelihoods)
{
	// this shouldn't be set to 0 here (we should do it in the loop)
	for (int k = 0; k < kPatternCount; k++)
		outLogLikelihoods[k] = 0.0;

	for (int subsetIndex = 0 ; subsetIndex < count; ++subsetIndex ) {
		assert(subsetIndex < partials.size());
		const int rootPartialIndex = bufferIndices[subsetIndex];
		const double * rootPartials = partials[rootPartialIndex];
		assert(rootPartials);
		const double * frequencies = stateFrequencies[weights];
		const double wt = weights[subsetIndex];
		int u = 0;
		int v = 0;
		for (int k = 0; k < kPatternCount; k++) {

			double sum = 0.0;
			for (int i = 0; i < stateCount; i++) {

				sum += frequencies[i] * rootPartials[v];
				u++;
				v++;
			}
			outLogLikelihoods[k] += sum*wt;
		}
	}

	// this shouldn't be set to 0 here (we should do it in the loop)
	for (int k = 0; k < kPatternCount; k++)
		outLogLikelihoods[k] = log(outLogLikelihoods[k]);
	return NO_ERROR;
}

int BeagleCPUImpl::calculateEdgeLogLikelihoods(const int * parentBufferIndices,
								 const int* childBufferIndices,
								 const int* probabilityIndices,
								 const int* firstDerivativeIndices,
								 const int* secondDerivativeIndices,
								 int count,
								 const double* weights,
								 const double** stateFrequencies,
								 double* outLogLikelihoods,
								 double* outFirstDerivatives,
								 double* outSecondDerivatives)
{
	assert(0);
}

BeagleImpl* BeagleCPUImplFactory::createImpl(int bufferCount, int tipCount,
		int kStateCount, int patternCount, int eigenDecompositionCount,
		int matrixCount) {
	BeagleImpl* impl = new BeagleCPUImpl();
	try {
		if(impl->initialize(nodeCount,tipCount,kStateCount,patternCount,categoryCount,matrixCount))
		return impl;
	}
	except(...)
	{
		delete impl;
		throw;
	}
	delete impl;
	return NULL;
}

const char* BeagleCPUImplFactory::getName() {
	return "CPU";
}

<|endoftext|>


<commit_before>#pragma once

#include "slotted_bag.hpp"
#include "thread_pool_options.hpp"
#include "thread_pool_state.hpp"

#include <atomic>
#include <thread>
#include <limits>
#include <mutex>
#include <chrono>
#include <condition_variable>

namespace tp
{

/**
* @brief The Worker class owns task queue and executing thread.
* In thread it tries to pop task from queue. If queue is empty then it tries
* to steal task from the sibling worker. If steal was unsuccessful then spins
* with one millisecond delay.
* @details State Machine:
*
*            +----------------+---------------+
*            |                |               |
*            v                |               |
*       +--------+       +----------+      +------+
*    +--| Active | ----> | BusyWait | ---> | Idle |
*    |  +--------+       +----------+      +------+
*    |       ^
*    |       |
*    +-------+
*
*/
template <typename Task, template<typename> class Queue>
class Worker final
{
    using WorkerVector = std::vector<std::unique_ptr<Worker<Task, Queue>>>;

    class WorkerStoppedException final : public std::exception
    {
    };

    /**
    * @brief State An Enum representing the Rouser thread state.
    */
    enum class State
    {
        Initialized,
        Running,
        Stopped
    };

public:
    /**
    * @brief Worker Constructor.
    * @param busy_wait_options The busy wait behaviour options.
    * @param queue_size Length of underlying task queue.
    */
    explicit Worker(ThreadPoolOptions::BusyWaitOptions const& busy_wait_options, size_t queue_size);

    /**
    * @brief Copy ctor implementation.
    */
    Worker(Worker const&) = delete;

    /**
    * @brief Copy assignment implementation.
    */
    Worker& operator=(Worker const& rhs) = delete;

    /**
    * @brief Move ctor implementation.
    */
    Worker(Worker&& rhs) = delete;

    /**
    * @brief Move assignment implementaion.
    */
    Worker& operator=(Worker&& rhs) = delete;

    /**
    * @brief Destructor implementation.
    */
    ~Worker();

    /**
    * @brief start Create the executing thread and start tasks execution.
    * @param id Worker ID.
    * @param state A pointer to thread pool's shared state.
    * @note The parameters passed into this function generally relate to the global thread pool state.
    */
    void start(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state);

    /**
    * @brief stop Stop all worker's thread and stealing activity.
    * Waits until the executing thread becomes finished.
    * @note Stop may only be called once start() has been invoked.
    * Repeated successful calls to stop() will be no-ops after the first.
    */
    void stop();

    /**
    * @brief tryPost Post task to queue.
    * @param handler Handler to be executed in executing thread.
    * @return true on success.
    */
    template <typename Handler>
    bool tryPost(Handler&& handler);

    /**
    * @brief tryGetLocalTask Get one task from this worker queue.
    * @param task Place for the obtained task to be stored.
    * @return true on success.
    */
    bool tryGetLocalTask(Task& task);

    /**
    * @brief getWorkerIdForCurrentThread Return worker ID associated with
    * current thread if exists.
    * @return Worker ID.
    */
    static size_t getWorkerIdForCurrentThread();

    /**
    * @brief wake Awake the worker if it was previously asleep.
    */
    void wake();

private:

    /**
    * @brief tryRoundRobinSteal Try stealing a thread from sibling workers in a round-robin fashion.
    * @param task Place for the obtained task to be stored.
    * @param workers Sibling workers for performing round robin work stealing.
    * @return true upon success, false otherwise.
    */
    bool tryRoundRobinSteal(Task& task, WorkerVector& workers);

    /**
    * @brief HandleTask Process a specific task.
    * @param task The task to be processed.
    */
    void handleTask(Task& task);

    /**
    * @brief tryGetTask Try to obtain a work item.
    * @details This entails attempting to pop an item from the local queue, and if not successful,
    * the worker will attempt to perform a round robin steal.
    * @param task Place for the obtained task to be stored.
    * @param workers Sibling workers for performing round robin work stealing.
    * @return true upon success, false otherwise.
    */
    bool tryGetTask(Task& task, WorkerVector& workers);

    /**
    * @brief threadFunc Executing thread function.
    * @param id Worker ID.
    * @param state A pointer to thread pool's shared state.
    * @note The parameters passed into this function generally relate to the global thread pool state.
    */
    void threadFunc(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state);

    Queue<Task> m_queue;
    std::atomic<State> m_state;
    std::thread m_thread;
    size_t m_next_donor;
    ThreadPoolOptions::BusyWaitOptions m_busy_wait_options;

    std::mutex m_idle_mutex;
    std::condition_variable m_idle_cv;

    bool m_is_idle;
    bool m_abort_idle;

};

/// Implementation

namespace detail
{
    inline size_t& thread_id()
    {
        static thread_local size_t tss_id = std::numeric_limits<size_t>::max();
        return tss_id;
    }
}

template <typename Task, template<typename> class Queue>
inline Worker<Task, Queue>::Worker(ThreadPoolOptions::BusyWaitOptions const& busy_wait_options, size_t queue_size)
    : m_queue(queue_size)
    , m_state(State::Initialized)
    , m_next_donor(0) // Initialized in threadFunc.
    , m_busy_wait_options(busy_wait_options)
    , m_is_idle(false)
    , m_abort_idle(false)
{
}

template <typename Task, template<typename> class Queue>
inline Worker<Task, Queue>::~Worker()
{
    stop();
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::stop()
{
    auto expectedState = State::Running;
    if (m_state.compare_exchange_strong(expectedState, State::Stopped, std::memory_order_acq_rel, std::memory_order_relaxed))
    {
        wake();
        m_thread.join();
    }
    else if (expectedState == State::Initialized)
        throw std::runtime_error("Cannot stop Worker: stop may only be calld after the Worker has been started.");
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::start(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state)
{
    auto expectedState = State::Initialized;
    if (!m_state.compare_exchange_strong(expectedState, State::Running, std::memory_order_acq_rel, std::memory_order_relaxed))
        throw std::runtime_error("Cannot start Worker: it has previously been started or stopped.");

    m_thread = std::thread(&Worker<Task, Queue>::threadFunc, this, id, state);
}

template <typename Task, template<typename> class Queue>
inline size_t Worker<Task, Queue>::getWorkerIdForCurrentThread()
{
    return detail::thread_id();
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::wake()
{
    bool notify;
    {
        std::unique_lock<std::mutex> lock(m_idle_mutex);

        m_abort_idle = true;
        notify = m_is_idle;
    }

    // Notify outside of lock.
    if (notify)
        m_idle_cv.notify_one();
}

template <typename Task, template<typename> class Queue>
template <typename Handler>
inline bool Worker<Task, Queue>::tryPost(Handler&& handler)
{
    return m_queue.push(std::forward<Handler>(handler));
}

template <typename Task, template<typename> class Queue>
inline bool Worker<Task, Queue>::tryGetLocalTask(Task& task)
{
    return m_queue.pop(task);
}

template <typename Task, template<typename> class Queue>
inline bool Worker<Task, Queue>::tryRoundRobinSteal(Task& task, WorkerVector& workers)
{
    auto starting_index = m_next_donor;

    // Iterate once through the worker ring, checking for queued work items on each thread.
    do
    {
        // Don't steal from local queue.
        if (m_next_donor != detail::thread_id() && workers[m_next_donor]->tryGetLocalTask(task))
        {
            // Increment before returning so that m_next_donor always points to the worker that has gone the longest
            // without a steal attempt. This helps enforce fairness in the stealing.
            ++m_next_donor %= workers.size();
            return true;
        }

        ++m_next_donor %= workers.size();
    } while (m_next_donor != starting_index);

    return false;
}

template <typename Task, template <typename> class Queue>
void Worker<Task, Queue>::handleTask(Task& task)
{
    try
    {
        task();
    }
    catch (...)
    {
        // Suppress all exceptions.
    }
}

template <typename Task, template <typename> class Queue>
bool Worker<Task, Queue>::tryGetTask(Task& task, WorkerVector& workers)
{
    if (m_state.load(std::memory_order_acquire) != State::Running)
        throw WorkerStoppedException();

    // Prioritize local queue, then try stealing from sibling workers.
    return tryGetLocalTask(task) || tryRoundRobinSteal(task, workers);
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::threadFunc(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state)
{
    detail::thread_id() = id;
    m_next_donor = (id + 1) % state->workers().size();
    Task handler;
    bool task_found = false;

    try
    {
        while (true)
        {
            // By default, this loop operates in the active state.
            // We poll for items from our local task queue and try to steal from others.
            if (tryGetTask(handler, state->workers()))
            {
                handleTask(handler);
                continue;
            };

            // We were unable to obtain a task.
            // We now transition into the busy wait state.
            task_found = false;
            state->numBusyWaiters().fetch_add(1, std::memory_order_acq_rel);

            for (auto i = 0u; i < m_busy_wait_options.numIterations() && !task_found; i++)
            {
                std::this_thread::sleep_for(m_busy_wait_options.iterationFunction()(i));
                task_found = tryGetTask(handler, state->workers());
            }

            // If we found a task during our busy wait sequence, we abort it and transition back into the active loop.
            if (task_found)
            {
                state->numBusyWaiters().fetch_sub(1, std::memory_order_acq_rel);
                handleTask(handler); // Handle the task body only once we decrement the busy waiting loop.
                continue;
            }

            // No tasks were found during the busy wait sequence.
            // We now transition into the idle state.
            {
                std::unique_lock<std::mutex> lock(m_idle_mutex);
                m_is_idle = false;
                m_abort_idle = false;
            }

            // We put this worker up for grabs as a recipient to new posts in the thread pool.
            state->idleWorkers().fill(id);

            // We need to transition out of the busy wait state after we have submitted ourselves to the idle
            // worker queue in order to avoid a race.
            state->numBusyWaiters().fetch_sub(1, std::memory_order_acq_rel);

            // While we were adding this worker to the idle worker bag, a job may have been posted into this
            // worker's queue. We need to check for work again before initiating the deep sleep sequence, otherwise
            // the given task may be lost.
            // Any further posts will flip the m_abort_idle flag to true, and we will catch them later.
            if (tryGetTask(handler, state->workers()))
            {
                handleTask(handler);
                // A task was indeed posted in the time it took this worker to enter the bag.
                // We remove the worker from the bag. If the internal state of the bag was not changed,
                // this means a different thread has already removed this worker from the idle queue,
                // and this case will be caught below. Looping early in this case will cause a loss of synchronization.
                if (state->idleWorkers().empty(id))
                    continue;
            }

            {
                std::unique_lock<std::mutex> lock(m_idle_mutex);

                // A post has occurred during the initialization of the sleep sequence! Abort the sleep sequence.
                if (m_abort_idle)
                    continue;

                m_is_idle = true;
                m_idle_cv.wait(lock, [this]() { return m_abort_idle; });
            }
        }
    }
    catch (WorkerStoppedException)
    {
        // Allow thread function to complete.
    }
}

}<commit_msg>print in catch<commit_after>#pragma once

#include "slotted_bag.hpp"
#include "thread_pool_options.hpp"
#include "thread_pool_state.hpp"

#include <atomic>
#include <thread>
#include <limits>
#include <mutex>
#include <chrono>
#include <condition_variable>

namespace tp
{

/**
* @brief The Worker class owns task queue and executing thread.
* In thread it tries to pop task from queue. If queue is empty then it tries
* to steal task from the sibling worker. If steal was unsuccessful then spins
* with one millisecond delay.
* @details State Machine:
*
*            +----------------+---------------+
*            |                |               |
*            v                |               |
*       +--------+       +----------+      +------+
*    +--| Active | ----> | BusyWait | ---> | Idle |
*    |  +--------+       +----------+      +------+
*    |       ^
*    |       |
*    +-------+
*
*/
template <typename Task, template<typename> class Queue>
class Worker final
{
    using WorkerVector = std::vector<std::unique_ptr<Worker<Task, Queue>>>;

    class WorkerStoppedException final : public std::exception
    {
    };

    /**
    * @brief State An Enum representing the Rouser thread state.
    */
    enum class State
    {
        Initialized,
        Running,
        Stopped
    };

public:
    /**
    * @brief Worker Constructor.
    * @param busy_wait_options The busy wait behaviour options.
    * @param queue_size Length of underlying task queue.
    */
    explicit Worker(ThreadPoolOptions::BusyWaitOptions const& busy_wait_options, size_t queue_size);

    /**
    * @brief Copy ctor implementation.
    */
    Worker(Worker const&) = delete;

    /**
    * @brief Copy assignment implementation.
    */
    Worker& operator=(Worker const& rhs) = delete;

    /**
    * @brief Move ctor implementation.
    */
    Worker(Worker&& rhs) = delete;

    /**
    * @brief Move assignment implementaion.
    */
    Worker& operator=(Worker&& rhs) = delete;

    /**
    * @brief Destructor implementation.
    */
    ~Worker();

    /**
    * @brief start Create the executing thread and start tasks execution.
    * @param id Worker ID.
    * @param state A pointer to thread pool's shared state.
    * @note The parameters passed into this function generally relate to the global thread pool state.
    */
    void start(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state);

    /**
    * @brief stop Stop all worker's thread and stealing activity.
    * Waits until the executing thread becomes finished.
    * @note Stop may only be called once start() has been invoked.
    * Repeated successful calls to stop() will be no-ops after the first.
    */
    void stop();

    /**
    * @brief tryPost Post task to queue.
    * @param handler Handler to be executed in executing thread.
    * @return true on success.
    */
    template <typename Handler>
    bool tryPost(Handler&& handler);

    /**
    * @brief tryGetLocalTask Get one task from this worker queue.
    * @param task Place for the obtained task to be stored.
    * @return true on success.
    */
    bool tryGetLocalTask(Task& task);

    /**
    * @brief getWorkerIdForCurrentThread Return worker ID associated with
    * current thread if exists.
    * @return Worker ID.
    */
    static size_t getWorkerIdForCurrentThread();

    /**
    * @brief wake Awake the worker if it was previously asleep.
    */
    void wake();

private:

    /**
    * @brief tryRoundRobinSteal Try stealing a thread from sibling workers in a round-robin fashion.
    * @param task Place for the obtained task to be stored.
    * @param workers Sibling workers for performing round robin work stealing.
    * @return true upon success, false otherwise.
    */
    bool tryRoundRobinSteal(Task& task, WorkerVector& workers);

    /**
    * @brief HandleTask Process a specific task.
    * @param task The task to be processed.
    */
    void handleTask(Task& task);

    /**
    * @brief tryGetTask Try to obtain a work item.
    * @details This entails attempting to pop an item from the local queue, and if not successful,
    * the worker will attempt to perform a round robin steal.
    * @param task Place for the obtained task to be stored.
    * @param workers Sibling workers for performing round robin work stealing.
    * @return true upon success, false otherwise.
    */
    bool tryGetTask(Task& task, WorkerVector& workers);

    /**
    * @brief threadFunc Executing thread function.
    * @param id Worker ID.
    * @param state A pointer to thread pool's shared state.
    * @note The parameters passed into this function generally relate to the global thread pool state.
    */
    void threadFunc(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state);

    Queue<Task> m_queue;
    std::atomic<State> m_state;
    std::thread m_thread;
    size_t m_next_donor;
    ThreadPoolOptions::BusyWaitOptions m_busy_wait_options;

    std::mutex m_idle_mutex;
    std::condition_variable m_idle_cv;

    bool m_is_idle;
    bool m_abort_idle;

};

/// Implementation

namespace detail
{
    inline size_t& thread_id()
    {
        static thread_local size_t tss_id = std::numeric_limits<size_t>::max();
        return tss_id;
    }
}

template <typename Task, template<typename> class Queue>
inline Worker<Task, Queue>::Worker(ThreadPoolOptions::BusyWaitOptions const& busy_wait_options, size_t queue_size)
    : m_queue(queue_size)
    , m_state(State::Initialized)
    , m_next_donor(0) // Initialized in threadFunc.
    , m_busy_wait_options(busy_wait_options)
    , m_is_idle(false)
    , m_abort_idle(false)
{
}

template <typename Task, template<typename> class Queue>
inline Worker<Task, Queue>::~Worker()
{
    stop();
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::stop()
{
    auto expectedState = State::Running;
    if (m_state.compare_exchange_strong(expectedState, State::Stopped, std::memory_order_acq_rel, std::memory_order_relaxed))
    {
        wake();
        m_thread.join();
    }
    else if (expectedState == State::Initialized)
        throw std::runtime_error("Cannot stop Worker: stop may only be calld after the Worker has been started.");
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::start(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state)
{
    auto expectedState = State::Initialized;
    if (!m_state.compare_exchange_strong(expectedState, State::Running, std::memory_order_acq_rel, std::memory_order_relaxed))
        throw std::runtime_error("Cannot start Worker: it has previously been started or stopped.");

    m_thread = std::thread(&Worker<Task, Queue>::threadFunc, this, id, state);
}

template <typename Task, template<typename> class Queue>
inline size_t Worker<Task, Queue>::getWorkerIdForCurrentThread()
{
    return detail::thread_id();
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::wake()
{
    bool notify;
    {
        std::unique_lock<std::mutex> lock(m_idle_mutex);

        m_abort_idle = true;
        notify = m_is_idle;
    }

    // Notify outside of lock.
    if (notify)
        m_idle_cv.notify_one();
}

template <typename Task, template<typename> class Queue>
template <typename Handler>
inline bool Worker<Task, Queue>::tryPost(Handler&& handler)
{
    return m_queue.push(std::forward<Handler>(handler));
}

template <typename Task, template<typename> class Queue>
inline bool Worker<Task, Queue>::tryGetLocalTask(Task& task)
{
    return m_queue.pop(task);
}

template <typename Task, template<typename> class Queue>
inline bool Worker<Task, Queue>::tryRoundRobinSteal(Task& task, WorkerVector& workers)
{
    auto starting_index = m_next_donor;

    // Iterate once through the worker ring, checking for queued work items on each thread.
    do
    {
        // Don't steal from local queue.
        if (m_next_donor != detail::thread_id() && workers[m_next_donor]->tryGetLocalTask(task))
        {
            // Increment before returning so that m_next_donor always points to the worker that has gone the longest
            // without a steal attempt. This helps enforce fairness in the stealing.
            ++m_next_donor %= workers.size();
            return true;
        }

        ++m_next_donor %= workers.size();
    } while (m_next_donor != starting_index);

    return false;
}

template <typename Task, template <typename> class Queue>
void Worker<Task, Queue>::handleTask(Task& task)
{
    try
    {
        task();
    }
    catch (...)
    {
		LogPrint("mempool", "%s\n", "Unknown Worker task Error!!!");
		printf("Unknown Worker task Error!!\n");
        // Suppress all exceptions.
    }
}

template <typename Task, template <typename> class Queue>
bool Worker<Task, Queue>::tryGetTask(Task& task, WorkerVector& workers)
{
    if (m_state.load(std::memory_order_acquire) != State::Running)
        throw WorkerStoppedException();

    // Prioritize local queue, then try stealing from sibling workers.
    return tryGetLocalTask(task) || tryRoundRobinSteal(task, workers);
}

template <typename Task, template<typename> class Queue>
inline void Worker<Task, Queue>::threadFunc(const size_t id, std::shared_ptr<ThreadPoolState<Task, Queue>> state)
{
    detail::thread_id() = id;
    m_next_donor = (id + 1) % state->workers().size();
    Task handler;
    bool task_found = false;

    try
    {
        while (true)
        {
            // By default, this loop operates in the active state.
            // We poll for items from our local task queue and try to steal from others.
            if (tryGetTask(handler, state->workers()))
            {
                handleTask(handler);
                continue;
            };

            // We were unable to obtain a task.
            // We now transition into the busy wait state.
            task_found = false;
            state->numBusyWaiters().fetch_add(1, std::memory_order_acq_rel);

            for (auto i = 0u; i < m_busy_wait_options.numIterations() && !task_found; i++)
            {
                std::this_thread::sleep_for(m_busy_wait_options.iterationFunction()(i));
                task_found = tryGetTask(handler, state->workers());
            }

            // If we found a task during our busy wait sequence, we abort it and transition back into the active loop.
            if (task_found)
            {
                state->numBusyWaiters().fetch_sub(1, std::memory_order_acq_rel);
                handleTask(handler); // Handle the task body only once we decrement the busy waiting loop.
                continue;
            }

            // No tasks were found during the busy wait sequence.
            // We now transition into the idle state.
            {
                std::unique_lock<std::mutex> lock(m_idle_mutex);
                m_is_idle = false;
                m_abort_idle = false;
            }

            // We put this worker up for grabs as a recipient to new posts in the thread pool.
            state->idleWorkers().fill(id);

            // We need to transition out of the busy wait state after we have submitted ourselves to the idle
            // worker queue in order to avoid a race.
            state->numBusyWaiters().fetch_sub(1, std::memory_order_acq_rel);

            // While we were adding this worker to the idle worker bag, a job may have been posted into this
            // worker's queue. We need to check for work again before initiating the deep sleep sequence, otherwise
            // the given task may be lost.
            // Any further posts will flip the m_abort_idle flag to true, and we will catch them later.
            if (tryGetTask(handler, state->workers()))
            {
                handleTask(handler);
                // A task was indeed posted in the time it took this worker to enter the bag.
                // We remove the worker from the bag. If the internal state of the bag was not changed,
                // this means a different thread has already removed this worker from the idle queue,
                // and this case will be caught below. Looping early in this case will cause a loss of synchronization.
                if (state->idleWorkers().empty(id))
                    continue;
            }

            {
                std::unique_lock<std::mutex> lock(m_idle_mutex);

                // A post has occurred during the initialization of the sleep sequence! Abort the sleep sequence.
                if (m_abort_idle)
                    continue;

                m_is_idle = true;
                m_idle_cv.wait(lock, [this]() { return m_abort_idle; });
            }
        }
    }
    catch (WorkerStoppedException &e)
    {
        // Allow thread function to complete.
		LogPrint("mempool", "%s: %s\n", "Worker Error", e.what());
		printf("worker error %s\n", e.what())
    }
}

}<|endoftext|>