<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "PythonScriptModule.h"
#include "PythonEngine.h"
//#include <stdlib.h> //_putenv for PYTHONHOME on windows
#include <Poco/Environment.h>

#include "MemoryLeakCheck.h"

using namespace Foundation;

namespace PythonScript
{
    PythonEngine::PythonEngine(Framework* framework) :
        framework_(framework)
    {
    }

    PythonEngine::~PythonEngine()
    {
        //deinit / free
    }

    void PythonEngine::Initialize()
    {
        if (!Py_IsInitialized())
        {
#ifdef _WIN32
            Poco::Environment::set("PYTHONHOME", ".\\pymodules");
            //_putenv("PYTHONHOME = .\\pymodules");
            //loads pymodules/lib/site.py which is the windows
            //std::cout << "PYTHONHOME SET";
#endif
            Py_Initialize();
#ifdef _WIN32
            //for some reason setting env vars has no effect when running from inside visual studio,
            //so for VS use, the PYTHONHOME env var had to be set in the project file
            //.. that is inconvenient, so changed the path manipulation to back here.
            RunString("import sys; sys.path.append('pymodules/python26_Lib.zip');");

#endif
            RunString("import sys; sys.path.append('pymodules');"); //XXX change to the c equivalent
            RunString("import sys; sys.path.append('pymodules/lib');"); // libraries directory
            RunString("import sys; sys.path.append('pymodules/DLLs');"); // dll directory (PYTHONHOME doesent seem to work to get these)
        }
        else
        {
            //LogWarning() //XXX add module ref here to be able to do logging
            std::cout << "Python already initialized in PythonScriptModule init!";
        }
    }

    /* load modules and get pointers to py functions - used to be in module postinitialize
        pModule = PyImport_Import(pName);
        Py_DECREF(pName);

        if (pModule != NULL) {
            pFunc = PyObject_GetAttrString(pModule, "onChat");
            //pFunc is a new reference

            if (pFunc && PyCallable_Check(pFunc)) {
                LogInfo("Registered callback onChat from chathandler.py");
            }
            else {
                if (PyErr_Occurred())
                    PyErr_Print();
                LogInfo("Cannot find function");
            }
        }
        else
            LogInfo("chathandler.py not found");
    */

    void PythonEngine::Uninitialize()
    {
        /*Py_XDECREF(pFunc);
        Py_DECREF(pModule);*/

        Py_Finalize();
    }

    /*void PythonEngine::Reset()
    {
        //should clear own internal state etc too i guess XXX
        Py_Finalize();
        Py_Initialize();
        //no ref to mod here now XXX
        //PythonModule::LogInfo("Python interpreter reseted: all memory and state cleared.");
    }*/

    //void PythonEngine::RunString(QString codestr, QMap<QString, QObject*> context)
    void PythonEngine::RunString(const QString &codestr, const QVariantMap &context)
    {
        PyRun_SimpleString(codestr.toAscii().data());
        //\note: doesn't handle extra context given, that was added to the interface for js
        //can be added here too if needed.
    }

    void PythonEngine::RunScript(const QString &scriptname)
    {
        FILE *fp = fopen(scriptname.toAscii().data(), "r");
        if (!fp)
        {
            PythonScriptModule::LogInfo("Failed to open script " + scriptname.toStdString());
            return;
        }

        PyRun_SimpleFile(fp, scriptname.toAscii().data());
        fclose(fp);
    }

    //===============================================================================================//

    //                                    //
    //         "GENERIC INTERFACE"        //
    //                                    //
    /* deprecated - PythonQt does this too

    Foundation::ScriptObject* PythonEngine::LoadScript(const std::string& scriptname, std::string& error)
    {
        PyObject *pName, *pModule;
        error = "None";
        //std::string scriptPath("pymodules");
        //PyImport_ImportModule(scriptPath.c_str());
        pName = PyString_FromString(scriptname.c_str());
        //pName = PyString_FromString(scriptPath.c_str());
        if(pName==NULL){ error = "name parsing failed"; return NULL;}
        pModule = PyImport_Import(pName);
        if(pModule==NULL){ error = "module loading failed"; return NULL;}
        PythonScriptObject* obj = new PythonScriptObject();
        obj->pythonRef = pModule;
        return obj;
    }

    Foundation::ScriptObject* PythonEngine::GetObject(const Foundation::ScriptObject& script,
                                                      const std::string& objectname,
                                                      std::string& error)
    {
        PyObject *pDict, *pClass, *pInstance;
        error = "None";
        // try casting script to PythonScriptObject
        PythonScriptObject* pythonscript = (PythonScriptObject*)&script;
        pDict = PyModule_GetDict(pythonscript->pythonRef);
        if(pDict==NULL){error = "unable to get module namespace"; return NULL;}
        // Build the name of a callable class
        pClass = PyDict_GetItemString(pDict, objectname.c_str());
        if(pClass==NULL){error = "unable get class from module namespace"; return NULL;}
        PythonScriptObject* obj = new PythonScriptObject();
        obj->pythonRef = pClass;

        // Create an instance of the class
        if (PyCallable_Check(pClass)) {
            pInstance = PyObject_CallObject(pClass, NULL);
        } else {
        error = "unable to create instance from class"; return NULL;
        }
        obj->pythonObj = pInstance;
        return obj;
    }

    */
}
<commit_msg>don't free python interpreter at Uninitialize(), since we don't (afaik) have a mechanism to do it the right order - Qt destructors can call into python<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"
#include "PythonScriptModule.h"
#include "PythonEngine.h"
//#include <stdlib.h> //_putenv for PYTHONHOME on windows
#include <Poco/Environment.h>

#include "MemoryLeakCheck.h"

using namespace Foundation;

namespace PythonScript
{
    PythonEngine::PythonEngine(Framework* framework) :
        framework_(framework)
    {
    }

    PythonEngine::~PythonEngine()
    {
        //deinit / free
    }

    void PythonEngine::Initialize()
    {
        if (!Py_IsInitialized())
        {
#ifdef _WIN32
            Poco::Environment::set("PYTHONHOME", ".\\pymodules");
            //_putenv("PYTHONHOME = .\\pymodules");
            //loads pymodules/lib/site.py which is the windows
            //std::cout << "PYTHONHOME SET";
#endif
            Py_Initialize();
#ifdef _WIN32
            //for some reason setting env vars has no effect when running from inside visual studio,
            //so for VS use, the PYTHONHOME env var had to be set in the project file
            //.. that is inconvenient, so changed the path manipulation to back here.
            RunString("import sys; sys.path.append('pymodules/python26_Lib.zip');");

#endif
            RunString("import sys; sys.path.append('pymodules');"); //XXX change to the c equivalent
            RunString("import sys; sys.path.append('pymodules/lib');"); // libraries directory
            RunString("import sys; sys.path.append('pymodules/DLLs');"); // dll directory (PYTHONHOME doesent seem to work to get these)
        }
        else
        {
            //LogWarning() //XXX add module ref here to be able to do logging
            std::cout << "Python already initialized in PythonScriptModule init!";
        }
    }

    /* load modules and get pointers to py functions - used to be in module postinitialize
        pModule = PyImport_Import(pName);
        Py_DECREF(pName);

        if (pModule != NULL) {
            pFunc = PyObject_GetAttrString(pModule, "onChat");
            //pFunc is a new reference

            if (pFunc && PyCallable_Check(pFunc)) {
                LogInfo("Registered callback onChat from chathandler.py");
            }
            else {
                if (PyErr_Occurred())
                    PyErr_Print();
                LogInfo("Cannot find function");
            }
        }
        else
            LogInfo("chathandler.py not found");
    */

    void PythonEngine::Uninitialize()
    {
        /*Py_XDECREF(pFunc);
        Py_DECREF(pModule);*/

        /* Py_Finalize(); */
    }

    /*void PythonEngine::Reset()
    {
        //should clear own internal state etc too i guess XXX
        Py_Finalize();
        Py_Initialize();
        //no ref to mod here now XXX
        //PythonModule::LogInfo("Python interpreter reseted: all memory and state cleared.");
    }*/

    //void PythonEngine::RunString(QString codestr, QMap<QString, QObject*> context)
    void PythonEngine::RunString(const QString &codestr, const QVariantMap &context)
    {
        PyRun_SimpleString(codestr.toAscii().data());
        //\note: doesn't handle extra context given, that was added to the interface for js
        //can be added here too if needed.
    }

    void PythonEngine::RunScript(const QString &scriptname)
    {
        FILE *fp = fopen(scriptname.toAscii().data(), "r");
        if (!fp)
        {
            PythonScriptModule::LogInfo("Failed to open script " + scriptname.toStdString());
            return;
        }

        PyRun_SimpleFile(fp, scriptname.toAscii().data());
        fclose(fp);
    }

    //===============================================================================================//

    //                                    //
    //         "GENERIC INTERFACE"        //
    //                                    //
    /* deprecated - PythonQt does this too

    Foundation::ScriptObject* PythonEngine::LoadScript(const std::string& scriptname, std::string& error)
    {
        PyObject *pName, *pModule;
        error = "None";
        //std::string scriptPath("pymodules");
        //PyImport_ImportModule(scriptPath.c_str());
        pName = PyString_FromString(scriptname.c_str());
        //pName = PyString_FromString(scriptPath.c_str());
        if(pName==NULL){ error = "name parsing failed"; return NULL;}
        pModule = PyImport_Import(pName);
        if(pModule==NULL){ error = "module loading failed"; return NULL;}
        PythonScriptObject* obj = new PythonScriptObject();
        obj->pythonRef = pModule;
        return obj;
    }

    Foundation::ScriptObject* PythonEngine::GetObject(const Foundation::ScriptObject& script,
                                                      const std::string& objectname,
                                                      std::string& error)
    {
        PyObject *pDict, *pClass, *pInstance;
        error = "None";
        // try casting script to PythonScriptObject
        PythonScriptObject* pythonscript = (PythonScriptObject*)&script;
        pDict = PyModule_GetDict(pythonscript->pythonRef);
        if(pDict==NULL){error = "unable to get module namespace"; return NULL;}
        // Build the name of a callable class
        pClass = PyDict_GetItemString(pDict, objectname.c_str());
        if(pClass==NULL){error = "unable get class from module namespace"; return NULL;}
        PythonScriptObject* obj = new PythonScriptObject();
        obj->pythonRef = pClass;

        // Create an instance of the class
        if (PyCallable_Check(pClass)) {
            pInstance = PyObject_CallObject(pClass, NULL);
        } else {
        error = "unable to create instance from class"; return NULL;
        }
        obj->pythonObj = pInstance;
        return obj;
    }

    */
}
<|endoftext|>


<commit_before>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.70
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "MoleculeLookup.h" //Header spec.
#include "EnsemblePreprocessor.h" //For box total
#include "PRNG.h" //For index selection
#include "PDBSetup.h" //For init.
#include "Molecules.h" //For init.
#include <algorithm>
#include <utility>
#include <iostream>
#ifdef GOMC_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#include "CUDAMemoryManager.cuh"
#include "VariablesCUDA.cuh"
#endif

void MoleculeLookup::Init(const Molecules& mols,
                          const pdb_setup::Atoms& atomData,
                          Forcefield &ff,
                          bool restartFromCheckpoint)
{
  this->restartFromCheckpoint = restartFromCheckpoint;

  numKinds = mols.GetKindsCount();
  molLookup.resize(mols.count);
  molLookupCount = mols.count;
  // beta has same size as total number of atoms
  molIndex.resize(atomData.beta.size());
  atomIndex.resize(atomData.beta.size());
  molKind.resize(atomData.beta.size());
  atomKind.resize(atomData.beta.size());
  atomCharge.resize(atomData.beta.size());

  //+1 to store end value
  boxAndKindStart.resize(numKinds * BOX_TOTAL + 1);
  boxAndKindSwappableCounts.resize(numKinds * BOX_TOTAL);

  boxAndKindStartCount = numKinds * BOX_TOTAL + 1;

  // vector[box][kind] = list of mol indices for kind in box
  std::vector<std::vector<std::vector<uint> > > indexVector;
  indexVector.resize(BOX_TOTAL);
  fixedMolecule.resize(mols.count);

  for (int i = 0; i < (int) numKinds * BOX_TOTAL; i++){
    boxAndKindSwappableCounts[i] = 0;
  }

  for (uint b = 0; b < BOX_TOTAL; ++b) {
    indexVector[b].resize(numKinds);
  }

  int counter = 0;
  for(uint m = 0; m < mols.count; ++m) {
    uint box = atomData.box[mols.start[m]];
    uint kind = mols.kIndex[m];
    indexVector[box][kind].push_back(m);
    const MoleculeKind& mk = mols.GetKind(m);
    for(uint a = 0; a < mk.NumAtoms(); ++a) {
      molIndex[counter] = int(m);
      atomIndex[counter] = int(a);
      molKind[counter] = int(kind);
      atomKind[counter] = int(mk.AtomKind(a));
      atomCharge[counter] = mk.AtomCharge(a);
      ++counter;
    }

    /* We don't currently support hybrid molecules - part fixed part flexible
      so we get a consensus based on the precendent of betas defined in this method */
    uint pStart = 0, pEnd = 0;
    mols.GetRangeStartStop(pStart, pEnd, m);
    fixedMolecule[m] = GetConsensusMolBeta(pStart, pEnd, atomData.beta, m, box, mols.kinds[mols.kIndex[m]].name);

    //Find the kind that can be swap(beta == 0) or move(beta == 0 or 2)
    if(fixedMolecule[m] == 0) {
      if(std::find(canSwapKind.begin(), canSwapKind.end(), kind) ==
          canSwapKind.end())
        canSwapKind.push_back(kind);

      if(std::find(canMoveKind.begin(), canMoveKind.end(), kind) ==
          canMoveKind.end())
        canMoveKind.push_back(kind);

      boxAndKindSwappableCounts[box * numKinds + kind]++;

    } else if(fixedMolecule[m] == 2) {
      if(std::find(canMoveKind.begin(), canMoveKind.end(), kind) ==
          canMoveKind.end())
        canMoveKind.push_back(kind);

    }
  }

  uint* progress = &molLookup[0];
  for (uint b = 0; b < BOX_TOTAL; ++b) {
    for (uint k = 0; k < numKinds; ++k) {
      boxAndKindStart[b * numKinds + k] = progress - &molLookup[0];
      progress = std::copy(indexVector[b][k].begin(),
                           indexVector[b][k].end(), progress);
    }
  }

  boxAndKindStart[numKinds * BOX_TOTAL] = mols.count;

    restartMoleculeIndices.resize(molLookupCount);
    std::iota(restartMoleculeIndices.begin(), restartMoleculeIndices.end(), 0);
  }

// allocate and set gpu variables
#ifdef GOMC_CUDA
  VariablesCUDA *cudaVars = ff.particles->getCUDAVars();
  int numMol = mols.count + 1;
  // allocate memory to store molecule start atom index
  CUMALLOC((void**) &cudaVars->gpu_startAtomIdx, numMol * sizeof(int));
  // copy start atom index
  cudaMemcpy(cudaVars->gpu_startAtomIdx, mols.start, numMol * sizeof(int), cudaMemcpyHostToDevice);
#endif

}

uint MoleculeLookup::NumInBox(const uint box) const
{
  return boxAndKindStart[(box + 1) * numKinds]
         - boxAndKindStart[box * numKinds];
}

void MoleculeLookup::TotalAndDensity
(uint * numByBox, uint * numByKindBox, double * molFractionByKindBox,
 double * densityByKindBox, double const*const volInv) const
{
  for (uint b = 0; b < BOX_TOTAL; ++b) {
    numByBox[b] = 0.0;
    for (uint k = 0; k < numKinds; ++k) {
      uint numMK = NumKindInBox(k, b);
      uint mkIdx = k + numKinds * b;
      numByKindBox[mkIdx] = numMK;
      densityByKindBox[mkIdx] = numMK * volInv[b];
      numByBox[b] += numMK;
    }

    //Calculate mol fractions
    if (numKinds > 1) {
      for (uint k = 0; k < numKinds; ++k) {
        uint mkIdx = k + numKinds * b;
        if (numByBox[b] > 0) {
          molFractionByKindBox[mkIdx] = (double)numByKindBox[mkIdx] /
                                        (double)numByBox[b];
        } else {
          molFractionByKindBox[mkIdx] = 0.0;
        }
      }
    }

  }

}

#ifdef VARIABLE_PARTICLE_NUMBER

bool MoleculeLookup::ShiftMolBox(const uint mol, const uint currentBox,
                                 const uint intoBox, const uint kind)
{
  uint index = std::find(
                 molLookup.begin() + boxAndKindStart[currentBox * numKinds + kind],
                 molLookup.begin() + boxAndKindStart[currentBox * numKinds + kind + 1], mol)
               - molLookup.begin();
  assert(index != boxAndKindStart[currentBox * numKinds + kind + 1]);
  assert(molLookup[index] == mol);
  Shift(index, currentBox, intoBox, kind);
  return true;
}

void MoleculeLookup::Shift(const uint index, const uint currentBox,
                           const uint intoBox, const uint kind)
{
  uint oldIndex = index;
  uint newIndex;
  uint section = currentBox * numKinds + kind;

  boxAndKindSwappableCounts[section]--;
  boxAndKindSwappableCounts[intoBox * numKinds + kind]++;

  if(currentBox >= intoBox) {
    while (section != intoBox * numKinds + kind) {
      newIndex = boxAndKindStart[section]++;
      std::swap(molLookup[oldIndex], molLookup[newIndex]);
      std::swap(oldIndex, newIndex);
      --section;
    }
  } else {
    while (section != intoBox * numKinds + kind) {
      newIndex = --boxAndKindStart[++section];
      std::swap(molLookup[oldIndex], molLookup[newIndex]);
      std::swap(oldIndex, newIndex);
    }
  }
}

#endif /*ifdef VARIABLE_PARTICLE_NUMBER*/

uint MoleculeLookup::GetConsensusMolBeta( const uint pStart,
                                          const uint pEnd,
                                          const std::vector<double> & betas,
                                          const uint m,
                                          const uint box,
                                          const std::string & name){
  double firstBeta = 0.0;
  double consensusBeta = 0.0;
  for (uint p = pStart; p < pEnd; ++p) {
    if (p == pStart){
      firstBeta = betas[p];
      consensusBeta = firstBeta;
    }
    if (firstBeta != betas[p]){
      std::cout <<
      "\nWarning: Conflict between the beta values of atoms in the same molecule" <<
      "\nName : " << name <<
      "\nMol Index : " << m <<
      "\nConflicting Indices" <<
      "\nStarting Index : " << pStart <<
      "\nConflicting Index : " << p  << std::endl;
      /* A beta == 1 functions like multiplying any number  by 0,
        even if there is only 1 atom with beta == 1,
        the entire molecule will be fixed */
      if (firstBeta == 1.0 || betas[p] == 1.0){
        std::cout << "Beta == 1.0 takes precedent, so " <<
        "\nName : " << name <<
        "\nMol Index : " << m <<
        "\nis fixed in place."  << std::endl;
        consensusBeta = 1.0;
        break;
      } else {
        std::cout << "Beta == 2.0 takes precedent, so " <<
        "\nName: " << name <<
        "\nMol Index: " << m <<
        "\nis fixed in box " << box << std::endl;
        consensusBeta = 2.0;
      }
    }
  }
  return (uint)consensusBeta;
}

MoleculeLookup::box_iterator MoleculeLookup::box_iterator::operator++(int)
{
  box_iterator tmp = *this;
  ++(*this);
  return tmp;
}

MoleculeLookup::box_iterator::box_iterator(const uint* _pLook, const uint* _pSec)
  : pIt(_pLook + * _pSec) {}

MoleculeLookup::box_iterator MoleculeLookup::BoxBegin(const uint box) const
{
  return box_iterator(&molLookup[0], &boxAndKindStart[box * numKinds]);
}

MoleculeLookup::box_iterator MoleculeLookup::BoxEnd(const uint box) const
{
  return box_iterator(&molLookup[0], &boxAndKindStart[(box + 1)* numKinds]);
}

MoleculeLookup& MoleculeLookup::operator=(const MoleculeLookup & rhs){
  molLookup = rhs.molLookup;
  molLookupCount = rhs.molLookupCount;
  //index [BOX_TOTAL * kind + box] is the first element of that kind/box in
  //molLookup
  //index [BOX_TOTAL * kind + box + 1] is the element after the end
  //of that kind/box
  boxAndKindStart = rhs.boxAndKindStart;
  boxAndKindSwappableCounts = rhs.boxAndKindSwappableCounts;
  boxAndKindStartCount = rhs.boxAndKindStartCount;
  numKinds = rhs.numKinds;
  fixedMolecule = rhs.fixedMolecule;
  canSwapKind = rhs.canSwapKind; //Kinds that can move intra and inter box
  canMoveKind = rhs.canMoveKind; //Kinds that can move intra box only
  molIndex = rhs.molIndex; // stores the molecule index for global atom index
  atomIndex = rhs.atomIndex; // stores the local atom index for global atom index
  molKind = rhs.molKind; // stores the molecule kind for global atom index
  atomKind = rhs.atomKind; // stores the atom kind for global atom index
  atomCharge = rhs.atomCharge; // stores the atom's charge for global atom index

  return *this;

}

bool MoleculeLookup::operator==(const MoleculeLookup & rhs){
  bool result;

  result &= (molLookup == rhs.molLookup);
  result &= (molLookupCount == rhs.molLookupCount);
  //index [BOX_TOTAL * kind + box] is the first element of that kind/box in
  //molLookup
  //index [BOX_TOTAL * kind + box + 1] is the element after the end
  //of that kind/box
  result &= (boxAndKindStart == rhs.boxAndKindStart);
  result &= (boxAndKindSwappableCounts == rhs.boxAndKindSwappableCounts);
  result &= (boxAndKindStartCount == rhs.boxAndKindStartCount);
  result &= (numKinds == rhs.numKinds);
  result &= (fixedMolecule == rhs.fixedMolecule);
  result &= (canSwapKind == rhs.canSwapKind); //Kinds that can move intra and inter box
  result &= (canMoveKind == rhs.canMoveKind); //Kinds that can move intra box only
  result &= (molIndex == rhs.molIndex); // stores the molecule index for global atom index
  result &= (atomIndex == rhs.atomIndex); // stores the local atom index for global atom index
  result &= (molKind == rhs.molKind); // stores the molecule kind for global atom index
  result &= (atomKind == rhs.atomKind); // stores the atom kind for global atom index
  result &= (atomCharge == rhs.atomCharge); // stores the atom's charge for global atom index

  return result;

}

void MoleculeLookup::swap(MoleculeLookup& oldMolLookup, MoleculeLookup& newMolLookup)
{
  using std::swap;
  swap(oldMolLookup.atomCharge, newMolLookup.atomCharge);
  swap(oldMolLookup.atomIndex, newMolLookup.atomIndex);
  swap(oldMolLookup.atomKind, newMolLookup.atomKind);
  swap(oldMolLookup.boxAndKindStart, newMolLookup.boxAndKindStart);
  swap(oldMolLookup.boxAndKindStartCount, newMolLookup.boxAndKindStartCount);
  swap(oldMolLookup.boxAndKindSwappableCounts, newMolLookup.boxAndKindSwappableCounts);
  swap(oldMolLookup.canMoveKind, newMolLookup.canMoveKind);
  swap(oldMolLookup.canSwapKind, newMolLookup.canSwapKind);
  swap(oldMolLookup.fixedMolecule, newMolLookup.fixedMolecule);
  swap(oldMolLookup.molIndex, newMolLookup.molIndex);
  swap(oldMolLookup.molKind, newMolLookup.molKind);
  swap(oldMolLookup.molLookup, newMolLookup.molLookup);
  swap(oldMolLookup.molLookupCount, newMolLookup.molLookupCount);
  swap(oldMolLookup.numKinds, newMolLookup.numKinds);
}
<commit_msg>added restart vects to assignment operator of mollook<commit_after>/*******************************************************************************
GPU OPTIMIZED MONTE CARLO (GOMC) 2.70
Copyright (C) 2018  GOMC Group
A copy of the GNU General Public License can be found in the COPYRIGHT.txt
along with this program, also can be found at <http://www.gnu.org/licenses/>.
********************************************************************************/
#include "MoleculeLookup.h" //Header spec.
#include "EnsemblePreprocessor.h" //For box total
#include "PRNG.h" //For index selection
#include "PDBSetup.h" //For init.
#include "Molecules.h" //For init.
#include <algorithm>
#include <utility>
#include <iostream>
#ifdef GOMC_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#include "CUDAMemoryManager.cuh"
#include "VariablesCUDA.cuh"
#endif

void MoleculeLookup::Init(const Molecules& mols,
                          const pdb_setup::Atoms& atomData,
                          Forcefield &ff,
                          bool restartFromCheckpoint)
{
  this->restartFromCheckpoint = restartFromCheckpoint;

  numKinds = mols.GetKindsCount();
  molLookup.resize(mols.count);
  molLookupCount = mols.count;
  // beta has same size as total number of atoms
  molIndex.resize(atomData.beta.size());
  atomIndex.resize(atomData.beta.size());
  molKind.resize(atomData.beta.size());
  atomKind.resize(atomData.beta.size());
  atomCharge.resize(atomData.beta.size());

  //+1 to store end value
  boxAndKindStart.resize(numKinds * BOX_TOTAL + 1);
  boxAndKindSwappableCounts.resize(numKinds * BOX_TOTAL);

  boxAndKindStartCount = numKinds * BOX_TOTAL + 1;

  // vector[box][kind] = list of mol indices for kind in box
  std::vector<std::vector<std::vector<uint> > > indexVector;
  indexVector.resize(BOX_TOTAL);
  fixedMolecule.resize(mols.count);

  for (int i = 0; i < (int) numKinds * BOX_TOTAL; i++){
    boxAndKindSwappableCounts[i] = 0;
  }

  for (uint b = 0; b < BOX_TOTAL; ++b) {
    indexVector[b].resize(numKinds);
  }

  int counter = 0;
  for(uint m = 0; m < mols.count; ++m) {
    uint box = atomData.box[mols.start[m]];
    uint kind = mols.kIndex[m];
    indexVector[box][kind].push_back(m);
    const MoleculeKind& mk = mols.GetKind(m);
    for(uint a = 0; a < mk.NumAtoms(); ++a) {
      molIndex[counter] = int(m);
      atomIndex[counter] = int(a);
      molKind[counter] = int(kind);
      atomKind[counter] = int(mk.AtomKind(a));
      atomCharge[counter] = mk.AtomCharge(a);
      ++counter;
    }

    /* We don't currently support hybrid molecules - part fixed part flexible
      so we get a consensus based on the precendent of betas defined in this method */
    uint pStart = 0, pEnd = 0;
    mols.GetRangeStartStop(pStart, pEnd, m);
    fixedMolecule[m] = GetConsensusMolBeta(pStart, pEnd, atomData.beta, m, box, mols.kinds[mols.kIndex[m]].name);

    //Find the kind that can be swap(beta == 0) or move(beta == 0 or 2)
    if(fixedMolecule[m] == 0) {
      if(std::find(canSwapKind.begin(), canSwapKind.end(), kind) ==
          canSwapKind.end())
        canSwapKind.push_back(kind);

      if(std::find(canMoveKind.begin(), canMoveKind.end(), kind) ==
          canMoveKind.end())
        canMoveKind.push_back(kind);

      boxAndKindSwappableCounts[box * numKinds + kind]++;

    } else if(fixedMolecule[m] == 2) {
      if(std::find(canMoveKind.begin(), canMoveKind.end(), kind) ==
          canMoveKind.end())
        canMoveKind.push_back(kind);

    }
  }

  uint* progress = &molLookup[0];
  for (uint b = 0; b < BOX_TOTAL; ++b) {
    for (uint k = 0; k < numKinds; ++k) {
      boxAndKindStart[b * numKinds + k] = progress - &molLookup[0];
      progress = std::copy(indexVector[b][k].begin(),
                           indexVector[b][k].end(), progress);
    }
  }

  boxAndKindStart[numKinds * BOX_TOTAL] = mols.count;

    restartMoleculeIndices.resize(molLookupCount);
    std::iota(restartMoleculeIndices.begin(), restartMoleculeIndices.end(), 0);
  }

// allocate and set gpu variables
#ifdef GOMC_CUDA
  VariablesCUDA *cudaVars = ff.particles->getCUDAVars();
  int numMol = mols.count + 1;
  // allocate memory to store molecule start atom index
  CUMALLOC((void**) &cudaVars->gpu_startAtomIdx, numMol * sizeof(int));
  // copy start atom index
  cudaMemcpy(cudaVars->gpu_startAtomIdx, mols.start, numMol * sizeof(int), cudaMemcpyHostToDevice);
#endif

}

uint MoleculeLookup::NumInBox(const uint box) const
{
  return boxAndKindStart[(box + 1) * numKinds]
         - boxAndKindStart[box * numKinds];
}

void MoleculeLookup::TotalAndDensity
(uint * numByBox, uint * numByKindBox, double * molFractionByKindBox,
 double * densityByKindBox, double const*const volInv) const
{
  for (uint b = 0; b < BOX_TOTAL; ++b) {
    numByBox[b] = 0.0;
    for (uint k = 0; k < numKinds; ++k) {
      uint numMK = NumKindInBox(k, b);
      uint mkIdx = k + numKinds * b;
      numByKindBox[mkIdx] = numMK;
      densityByKindBox[mkIdx] = numMK * volInv[b];
      numByBox[b] += numMK;
    }

    //Calculate mol fractions
    if (numKinds > 1) {
      for (uint k = 0; k < numKinds; ++k) {
        uint mkIdx = k + numKinds * b;
        if (numByBox[b] > 0) {
          molFractionByKindBox[mkIdx] = (double)numByKindBox[mkIdx] /
                                        (double)numByBox[b];
        } else {
          molFractionByKindBox[mkIdx] = 0.0;
        }
      }
    }

  }

}

#ifdef VARIABLE_PARTICLE_NUMBER

bool MoleculeLookup::ShiftMolBox(const uint mol, const uint currentBox,
                                 const uint intoBox, const uint kind)
{
  uint index = std::find(
                 molLookup.begin() + boxAndKindStart[currentBox * numKinds + kind],
                 molLookup.begin() + boxAndKindStart[currentBox * numKinds + kind + 1], mol)
               - molLookup.begin();
  assert(index != boxAndKindStart[currentBox * numKinds + kind + 1]);
  assert(molLookup[index] == mol);
  Shift(index, currentBox, intoBox, kind);
  return true;
}

void MoleculeLookup::Shift(const uint index, const uint currentBox,
                           const uint intoBox, const uint kind)
{
  uint oldIndex = index;
  uint newIndex;
  uint section = currentBox * numKinds + kind;

  boxAndKindSwappableCounts[section]--;
  boxAndKindSwappableCounts[intoBox * numKinds + kind]++;

  if(currentBox >= intoBox) {
    while (section != intoBox * numKinds + kind) {
      newIndex = boxAndKindStart[section]++;
      std::swap(molLookup[oldIndex], molLookup[newIndex]);
      std::swap(oldIndex, newIndex);
      --section;
    }
  } else {
    while (section != intoBox * numKinds + kind) {
      newIndex = --boxAndKindStart[++section];
      std::swap(molLookup[oldIndex], molLookup[newIndex]);
      std::swap(oldIndex, newIndex);
    }
  }
}

#endif /*ifdef VARIABLE_PARTICLE_NUMBER*/

uint MoleculeLookup::GetConsensusMolBeta( const uint pStart,
                                          const uint pEnd,
                                          const std::vector<double> & betas,
                                          const uint m,
                                          const uint box,
                                          const std::string & name){
  double firstBeta = 0.0;
  double consensusBeta = 0.0;
  for (uint p = pStart; p < pEnd; ++p) {
    if (p == pStart){
      firstBeta = betas[p];
      consensusBeta = firstBeta;
    }
    if (firstBeta != betas[p]){
      std::cout <<
      "\nWarning: Conflict between the beta values of atoms in the same molecule" <<
      "\nName : " << name <<
      "\nMol Index : " << m <<
      "\nConflicting Indices" <<
      "\nStarting Index : " << pStart <<
      "\nConflicting Index : " << p  << std::endl;
      /* A beta == 1 functions like multiplying any number  by 0,
        even if there is only 1 atom with beta == 1,
        the entire molecule will be fixed */
      if (firstBeta == 1.0 || betas[p] == 1.0){
        std::cout << "Beta == 1.0 takes precedent, so " <<
        "\nName : " << name <<
        "\nMol Index : " << m <<
        "\nis fixed in place."  << std::endl;
        consensusBeta = 1.0;
        break;
      } else {
        std::cout << "Beta == 2.0 takes precedent, so " <<
        "\nName: " << name <<
        "\nMol Index: " << m <<
        "\nis fixed in box " << box << std::endl;
        consensusBeta = 2.0;
      }
    }
  }
  return (uint)consensusBeta;
}

MoleculeLookup::box_iterator MoleculeLookup::box_iterator::operator++(int)
{
  box_iterator tmp = *this;
  ++(*this);
  return tmp;
}

MoleculeLookup::box_iterator::box_iterator(const uint* _pLook, const uint* _pSec)
  : pIt(_pLook + * _pSec) {}

MoleculeLookup::box_iterator MoleculeLookup::BoxBegin(const uint box) const
{
  return box_iterator(&molLookup[0], &boxAndKindStart[box * numKinds]);
}

MoleculeLookup::box_iterator MoleculeLookup::BoxEnd(const uint box) const
{
  return box_iterator(&molLookup[0], &boxAndKindStart[(box + 1)* numKinds]);
}

MoleculeLookup& MoleculeLookup::operator=(const MoleculeLookup & rhs){
  molLookup = rhs.molLookup;
  molLookupCount = rhs.molLookupCount;
  //index [BOX_TOTAL * kind + box] is the first element of that kind/box in
  //molLookup
  //index [BOX_TOTAL * kind + box + 1] is the element after the end
  //of that kind/box
  boxAndKindStart = rhs.boxAndKindStart;
  boxAndKindSwappableCounts = rhs.boxAndKindSwappableCounts;
  boxAndKindStartCount = rhs.boxAndKindStartCount;
  numKinds = rhs.numKinds;
  fixedMolecule = rhs.fixedMolecule;
  canSwapKind = rhs.canSwapKind; //Kinds that can move intra and inter box
  canMoveKind = rhs.canMoveKind; //Kinds that can move intra box only
  molIndex = rhs.molIndex; // stores the molecule index for global atom index
  atomIndex = rhs.atomIndex; // stores the local atom index for global atom index
  molKind = rhs.molKind; // stores the molecule kind for global atom index
  atomKind = rhs.atomKind; // stores the atom kind for global atom index
  atomCharge = rhs.atomCharge; // stores the atom's charge for global atom index

  /* For consistent trajectory ordering across checkpoints */
  restartFromCheckpoint = rhs.restartFromCheckpoint;
  restartMoleculeIndices = rhs.restartMoleculeIndices;
  for (int b = 0; b < BOX_TOTAL; ++b)
    restartedNumAtomsInBox[b] = rhs.restartedNumAtomsInBox[b];

  return *this;

}

bool MoleculeLookup::operator==(const MoleculeLookup & rhs){
  bool result;

  result &= (molLookup == rhs.molLookup);
  result &= (molLookupCount == rhs.molLookupCount);
  //index [BOX_TOTAL * kind + box] is the first element of that kind/box in
  //molLookup
  //index [BOX_TOTAL * kind + box + 1] is the element after the end
  //of that kind/box
  result &= (boxAndKindStart == rhs.boxAndKindStart);
  result &= (boxAndKindSwappableCounts == rhs.boxAndKindSwappableCounts);
  result &= (boxAndKindStartCount == rhs.boxAndKindStartCount);
  result &= (numKinds == rhs.numKinds);
  result &= (fixedMolecule == rhs.fixedMolecule);
  result &= (canSwapKind == rhs.canSwapKind); //Kinds that can move intra and inter box
  result &= (canMoveKind == rhs.canMoveKind); //Kinds that can move intra box only
  result &= (molIndex == rhs.molIndex); // stores the molecule index for global atom index
  result &= (atomIndex == rhs.atomIndex); // stores the local atom index for global atom index
  result &= (molKind == rhs.molKind); // stores the molecule kind for global atom index
  result &= (atomKind == rhs.atomKind); // stores the atom kind for global atom index
  result &= (atomCharge == rhs.atomCharge); // stores the atom's charge for global atom index

  /* For consistent trajectory ordering across checkpoints */
  result &= (restartFromCheckpoint = rhs.restartFromCheckpoint);
  result &= (restartMoleculeIndices == rhs.restartMoleculeIndices);
  for (int b = 0; b < BOX_TOTAL; ++b)
    result &= (restartedNumAtomsInBox[b] == rhs.restartedNumAtomsInBox[b]);

  return result;

}

void MoleculeLookup::swap(MoleculeLookup& oldMolLookup, MoleculeLookup& newMolLookup)
{
  using std::swap;
  swap(oldMolLookup.atomCharge, newMolLookup.atomCharge);
  swap(oldMolLookup.atomIndex, newMolLookup.atomIndex);
  swap(oldMolLookup.atomKind, newMolLookup.atomKind);
  swap(oldMolLookup.boxAndKindStart, newMolLookup.boxAndKindStart);
  swap(oldMolLookup.boxAndKindStartCount, newMolLookup.boxAndKindStartCount);
  swap(oldMolLookup.boxAndKindSwappableCounts, newMolLookup.boxAndKindSwappableCounts);
  swap(oldMolLookup.canMoveKind, newMolLookup.canMoveKind);
  swap(oldMolLookup.canSwapKind, newMolLookup.canSwapKind);
  swap(oldMolLookup.fixedMolecule, newMolLookup.fixedMolecule);
  swap(oldMolLookup.molIndex, newMolLookup.molIndex);
  swap(oldMolLookup.molKind, newMolLookup.molKind);
  swap(oldMolLookup.molLookup, newMolLookup.molLookup);
  swap(oldMolLookup.molLookupCount, newMolLookup.molLookupCount);
  swap(oldMolLookup.numKinds, newMolLookup.numKinds);
    /* For consistent trajectory ordering across checkpoints */
  swap(oldMolLookup.restartFromCheckpoint, newMolLookup.restartFromCheckpoint);
  swap(oldMolLookup.restartMoleculeIndices, newMolLookup.restartMoleculeIndices);
  for (int b = 0; b < BOX_TOTAL; ++b)
    swap(oldMolLookup.restartedNumAtomsInBox[b], newMolLookup.restartedNumAtomsInBox[b]);
}
<|endoftext|>


<commit_before>//
//  PlaybackWidget.cpp
//  RunParticles
//
//  Created by Doug Letterman on 10/26/14.
//
//

#include "PlaybackWidget.h"

#include <QGridLayout>
#include <QVBoxLayout>

#include "Util.h"

PlaybackWidget::PlaybackWidget(QWidget *parent) :
    QWidget(parent)
{
    setObjectName("PlaybackWidget");
    setWindowTitle("Playback controls");
    _rewindButton = new QPushButton(QString::fromUtf8("\u25C0\u25C0"), this);//<<
    _backButton = new QPushButton(QString::fromUtf8("\u25C0"), this); // <
    _pauseButton = new QPushButton(QString::fromUtf8("\u2588"), this); // [ ]
    _forwardButton = new QPushButton(QString::fromUtf8("\u25BA"), this); // >
    _playSpeedCombo = new QComboBox(this);
    _playSpeedCombo->addItem("1x");
    _playSpeedCombo->addItem("2x");
    _playSpeedCombo->addItem("4x");
    _playSpeedCombo->addItem("8x");
    _playSpeedCombo->addItem("16x");
    _playSpeedCombo->addItem("32x");
    _playSpeedCombo->addItem("64x");
    _slider = new QSlider(Qt::Horizontal, this);
    _currentTimeLineEdit = new QLineEdit(this);
    _currentTimeLineEdit->setReadOnly(true);
    _currentTimeLineEdit->setText("0");
    _currentTimeLineEdit->setAlignment(Qt::AlignRight);
    _statusBar = new QStatusBar(this);
    _progressBar = new QProgressBar();
    _statusBar->addPermanentWidget(_progressBar);
    _statusBar->show();
    _layoutPlaybackControls();

    /* connect the buttons up to relay signals */
    connect(_rewindButton, SIGNAL(clicked()), SIGNAL(signalRewind()));
    connect(_backButton, SIGNAL(clicked()), SIGNAL(signalBack()));
    connect(_pauseButton, SIGNAL(clicked()), SIGNAL(signalPause()));
    connect(_forwardButton, SIGNAL(clicked()), SIGNAL(signalForward()));
    connect(_playSpeedCombo, SIGNAL(activated(const QString&)),
            SIGNAL(signalPlaybackRateChanged(const QString&)));
    connect(_slider, SIGNAL(valueChanged(int)),
            SIGNAL(signalTimeSliderChanged(int)));
    setTimeSliderMaximum(1800);
    hideProgress();
}

void
PlaybackWidget::setTime(double mapSeconds)
{
    QString time = Util::secondsToString(mapSeconds);
    _currentTimeLineEdit->setText(time);
    _slider->blockSignals(true);
    _slider->setSliderPosition(int(mapSeconds));
    _slider->blockSignals(false);
}

void
PlaybackWidget::setTimeSliderMaximum(int max)
{
    _slider->setMaximum(max);
}

void
PlaybackWidget::updateStatus(const QString &message, int total, int done)
{
    if (done < total)
        _progressBar->show();
    _statusBar->showMessage(message);
    _progressBar->setMaximum(total);
    _progressBar->setValue(done);
}

void
PlaybackWidget::hideProgress()
{
    _progressBar->hide();
    _statusBar->clearMessage();
}

void
PlaybackWidget::_layoutPlaybackControls()
{
    QVBoxLayout *mainCol = new QVBoxLayout(this);
    mainCol->setMargin(0);
    mainCol->setSpacing(2);
    QGridLayout *layout = new QGridLayout();
    layout->setMargin(8);
    layout->setSpacing(8);
    layout->addWidget(_rewindButton, 0, 0);
    layout->addWidget(_backButton, 0, 1);
    layout->addWidget(_pauseButton, 0, 2);
    layout->addWidget(_forwardButton, 0, 3);
    layout->addWidget(_playSpeedCombo, 0, 4);
    layout->addWidget(_slider, 1, 0, 1, 4);
    layout->addWidget(_currentTimeLineEdit, 1, 4);
    for (int i=0; i < layout->columnCount()-1; i++)
        layout->setColumnStretch(i, 1);
    layout->setColumnMinimumWidth(4, 100);
    layout->setRowStretch(0, 2);
    /* make the buttons expand vertically */
    _rewindButton->setSizePolicy(QSizePolicy::Preferred,
                                 QSizePolicy::Expanding);
    _backButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    _pauseButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    _forwardButton->setSizePolicy(QSizePolicy::Preferred,
                                  QSizePolicy::Expanding);
    mainCol->addLayout(layout);
    mainCol->addWidget(_statusBar);
}
<commit_msg>Playback speed goes to 256x.<commit_after>//
//  PlaybackWidget.cpp
//  RunParticles
//
//  Created by Doug Letterman on 10/26/14.
//
//

#include "PlaybackWidget.h"

#include <QGridLayout>
#include <QVBoxLayout>

#include "Util.h"

PlaybackWidget::PlaybackWidget(QWidget *parent) :
    QWidget(parent)
{
    setObjectName("PlaybackWidget");
    setWindowTitle("Playback controls");
    _rewindButton = new QPushButton(QString::fromUtf8("\u25C0\u25C0"), this);//<<
    _backButton = new QPushButton(QString::fromUtf8("\u25C0"), this); // <
    _pauseButton = new QPushButton(QString::fromUtf8("\u2588"), this); // [ ]
    _forwardButton = new QPushButton(QString::fromUtf8("\u25BA"), this); // >
    _playSpeedCombo = new QComboBox(this);
    _playSpeedCombo->addItem("1x");
    _playSpeedCombo->addItem("2x");
    _playSpeedCombo->addItem("4x");
    _playSpeedCombo->addItem("8x");
    _playSpeedCombo->addItem("16x");
    _playSpeedCombo->addItem("32x");
    _playSpeedCombo->addItem("64x");
    _playSpeedCombo->addItem("128x");
    _playSpeedCombo->addItem("256x");
    _slider = new QSlider(Qt::Horizontal, this);
    _currentTimeLineEdit = new QLineEdit(this);
    _currentTimeLineEdit->setReadOnly(true);
    _currentTimeLineEdit->setText("0");
    _currentTimeLineEdit->setAlignment(Qt::AlignRight);
    _statusBar = new QStatusBar(this);
    _progressBar = new QProgressBar();
    _statusBar->addPermanentWidget(_progressBar);
    _statusBar->show();
    _layoutPlaybackControls();

    /* connect the buttons up to relay signals */
    connect(_rewindButton, SIGNAL(clicked()), SIGNAL(signalRewind()));
    connect(_backButton, SIGNAL(clicked()), SIGNAL(signalBack()));
    connect(_pauseButton, SIGNAL(clicked()), SIGNAL(signalPause()));
    connect(_forwardButton, SIGNAL(clicked()), SIGNAL(signalForward()));
    connect(_playSpeedCombo, SIGNAL(activated(const QString&)),
            SIGNAL(signalPlaybackRateChanged(const QString&)));
    connect(_slider, SIGNAL(valueChanged(int)),
            SIGNAL(signalTimeSliderChanged(int)));
    setTimeSliderMaximum(1800);
    hideProgress();
}

void
PlaybackWidget::setTime(double mapSeconds)
{
    QString time = Util::secondsToString(mapSeconds);
    _currentTimeLineEdit->setText(time);
    _slider->blockSignals(true);
    _slider->setSliderPosition(int(mapSeconds));
    _slider->blockSignals(false);
}

void
PlaybackWidget::setTimeSliderMaximum(int max)
{
    _slider->setMaximum(max);
}

void
PlaybackWidget::updateStatus(const QString &message, int total, int done)
{
    if (done < total)
        _progressBar->show();
    _statusBar->showMessage(message);
    _progressBar->setMaximum(total);
    _progressBar->setValue(done);
}

void
PlaybackWidget::hideProgress()
{
    _progressBar->hide();
    _statusBar->clearMessage();
}

void
PlaybackWidget::_layoutPlaybackControls()
{
    QVBoxLayout *mainCol = new QVBoxLayout(this);
    mainCol->setMargin(0);
    mainCol->setSpacing(2);
    QGridLayout *layout = new QGridLayout();
    layout->setMargin(8);
    layout->setSpacing(8);
    layout->addWidget(_rewindButton, 0, 0);
    layout->addWidget(_backButton, 0, 1);
    layout->addWidget(_pauseButton, 0, 2);
    layout->addWidget(_forwardButton, 0, 3);
    layout->addWidget(_playSpeedCombo, 0, 4);
    layout->addWidget(_slider, 1, 0, 1, 4);
    layout->addWidget(_currentTimeLineEdit, 1, 4);
    for (int i=0; i < layout->columnCount()-1; i++)
        layout->setColumnStretch(i, 1);
    layout->setColumnMinimumWidth(4, 100);
    layout->setRowStretch(0, 2);
    /* make the buttons expand vertically */
    _rewindButton->setSizePolicy(QSizePolicy::Preferred,
                                 QSizePolicy::Expanding);
    _backButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    _pauseButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    _forwardButton->setSizePolicy(QSizePolicy::Preferred,
                                  QSizePolicy::Expanding);
    mainCol->addLayout(layout);
    mainCol->addWidget(_statusBar);
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/

#include "debugginghelper.h"

#include <coreplugin/icore.h>
#include <QtCore/QFileInfo>
#include <QtCore/QCoreApplication>
#include <QtCore/QHash>
#include <QtCore/QProcess>
#include <QtCore/QDir>
#include <QtCore/QDateTime>

#include <QtGui/QDesktopServices>

using namespace ProjectExplorer;

QString DebuggingHelperLibrary::findSystemQt(const Environment &env)
{
    QStringList paths = env.path();
    foreach (const QString &path, paths) {
        foreach (const QString &possibleCommand, possibleQMakeCommands()) {
            const QFileInfo qmake(path + QLatin1Char('/') + possibleCommand);
            if (qmake.exists()) {
                if (!qtVersionForQMake(qmake.absoluteFilePath()).isNull()) {
                    return qmake.absoluteFilePath();
                }
            }
        }
    }
    return QString::null;
}

bool DebuggingHelperLibrary::hasDebuggingHelperLibrary(const QString &qmakePath)
{
    return !debuggingHelperLibrary(qmakePath).isNull();
}

QStringList DebuggingHelperLibrary::debuggingHelperLibraryDirectories(const QString &qtInstallData, const QString &qtpath)
{
    const QChar slash = QLatin1Char('/');
    const uint hash = qHash(qtpath);
    QStringList directories;
    directories
            << (qtInstallData + QLatin1String("/qtc-debugging-helper/"))
            << QDir::cleanPath((QCoreApplication::applicationDirPath() + QLatin1String("/../qtc-debugging-helper/") + QString::number(hash))) + slash
            << (QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QLatin1String("/qtc-debugging-helper/") + QString::number(hash)) + slash;
    return directories;
}

QStringList DebuggingHelperLibrary::debuggingHelperLibraryLocations(const QString &qmakePath)
{
    return debuggingHelperLibraryLocations(qtInstallDataDir(qmakePath), qtDir(qmakePath));
}

QString DebuggingHelperLibrary::debuggingHelperLibrary(const QString &qmakePath)
{
    return debuggingHelperLibrary(qtInstallDataDir(qmakePath), qtDir(qmakePath));
}

QString DebuggingHelperLibrary::qtInstallDataDir(const QString &qmakePath)
{
    QProcess proc;
    proc.start(qmakePath, QStringList() << QLatin1String("-query") << QLatin1String("QT_INSTALL_DATA"));
    if (proc.waitForFinished())
        return QString(proc.readAll().trimmed());
    return QString::null;
}

QString DebuggingHelperLibrary::qtDir(const QString &qmakePath)
{
    QDir dir = QFileInfo(qmakePath).absoluteDir();
    dir.cdUp();
    return dir.absolutePath();
}

// Debugging Helper Library

static inline QString helperFilePath(const QString &directory)
{
#if defined(Q_OS_WIN)
    return directory + QLatin1String("debug/gdbmacros.dll");
#elif defined(Q_OS_MAC)
    return directory + QLatin1String("libgdbmacros.dylib");
#else // generic UNIX
    return directory + QLatin1String("libgdbmacros.so");
#endif
}

QStringList DebuggingHelperLibrary::debuggingHelperLibraryLocations(const QString &qtInstallData, const QString &qtpath)
{
    QStringList result;
    foreach(const QString &directory, debuggingHelperLibraryDirectories(qtInstallData, qtpath))
        result << QFileInfo(helperFilePath(directory)).filePath();
    return result;
}

QString DebuggingHelperLibrary::debuggingHelperLibrary(const QString &qtInstallData, const QString &qtpath)
{
    foreach(const QString &directory, debuggingHelperLibraryDirectories(qtInstallData, qtpath)) {
        const QFileInfo fi(helperFilePath(directory));
        if (fi.exists())
            return fi.filePath();
    }
    return QString();
}

QString DebuggingHelperLibrary::buildDebuggingHelperLibrary(const QString &qmakePath, const QString &make, const Environment &env)
{
    QString errorMessage;
    const QString directory = copyDebuggingHelperLibrary(qtInstallDataDir(qmakePath), qtDir(qmakePath), &errorMessage);
    if (directory.isEmpty())
        return errorMessage;
    return buildDebuggingHelperLibrary(directory, make, qmakePath, QString::null, env);
}

// Copy helper source files to a target directory, replacing older files.
static bool copyDebuggingHelperFiles(const QStringList &files,
                                     const QString &targetDirectory,
                                     QString *errorMessage)
{
    const QString dumperSourcePath = Core::ICore::instance()->resourcePath() + QLatin1String("/gdbmacros/");
    if (!QDir().mkpath(targetDirectory)) {
        *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The target directory %1 could not be created.").arg(targetDirectory);
        return false;
    }
    foreach (const QString &file, files) {
        const QString source = dumperSourcePath + file;
        const QString dest = targetDirectory + file;
        const QFileInfo destInfo(dest);
        if (destInfo.exists()) {
            if (destInfo.lastModified() >= QFileInfo(source).lastModified())
                continue;
            if (!QFile::remove(dest)) {
                *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The existing file %1 could not be removed.").arg(destInfo.absoluteFilePath());
                return false;
            }
        }
        if (!QFile::copy(source, dest)) {
            *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The file %1 could not be copied to %2.").arg(source, dest);
            return false;
        }
    }
    return true;
}

QString DebuggingHelperLibrary::copyDebuggingHelperLibrary(const QString &qtInstallData,
                                                           const QString &qtdir,
                                                           QString *errorMessage)
{
    // Locations to try:
    //    $QTDIR/qtc-debugging-helper
    //    $APPLICATION-DIR/qtc-debugging-helper/$hash
    //    $USERDIR/qtc-debugging-helper/$hash
    const QStringList directories = DebuggingHelperLibrary::debuggingHelperLibraryDirectories(qtInstallData, qtdir);

    QStringList files;
    files << QLatin1String("gdbmacros.cpp") << QLatin1String("gdbmacros.h") << QLatin1String("gdbmacros.pro")
          << QLatin1String("LICENSE.LGPL") << QLatin1String("LGPL_EXCEPTION.TXT");
    // Try to find a writeable directory.
    foreach(const QString &directory, directories)
        if (copyDebuggingHelperFiles(files, directory, errorMessage)) {
            errorMessage->clear();
            return directory;
        }
    *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The debugger helpers could not be built in any of the directories:\n- %1\n\nReason: %2")
                    .arg(directories.join(QLatin1String("\n- ")), *errorMessage);
    return QString();
}

QString DebuggingHelperLibrary::buildDebuggingHelperLibrary(const QString &directory, const QString &makeCommand, const QString &qmakeCommand, const QString &mkspec, const Environment &env)
{
    QString output;
    const QChar newline = QLatin1Char('\n');
    // Setup process
    QProcess proc;
    proc.setEnvironment(env.toStringList());
    proc.setWorkingDirectory(directory);
    proc.setProcessChannelMode(QProcess::MergedChannels);

    output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Building debugging helper library in %1\n").arg(directory);
    output += newline;

    const QString makeFullPath = env.searchInPath(makeCommand);
    if (QFileInfo(directory + QLatin1String("/Makefile")).exists()) {
        if (!makeFullPath.isEmpty()) {
            const QString cleanTarget = QLatin1String("distclean");
            output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Running %1 %2...\n").arg(makeFullPath, cleanTarget);
            proc.start(makeFullPath, QStringList(cleanTarget));
            proc.waitForFinished();
            output += QString::fromLocal8Bit(proc.readAll());
        } else {
            output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "%1 not found in PATH\n").arg(makeCommand);
            return output;
        }
    }
    output += newline;
    output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Running %1 ...\n").arg(qmakeCommand);

    QStringList makeArgs;
    makeArgs << QLatin1String("-spec")<< (mkspec.isEmpty() ? QString(QLatin1String("default")) : mkspec) << QLatin1String("gdbmacros.pro");
    proc.start(qmakeCommand, makeArgs);
    proc.waitForFinished();

    output += proc.readAll();

    output += newline;;
    if (!makeFullPath.isEmpty()) {
        output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Running %1 ...\n").arg(makeFullPath);
        proc.start(makeFullPath, QStringList());
        proc.waitForFinished();
        output += proc.readAll();
    } else {
        output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "%1 not found in PATH\n").arg(makeCommand);
    }
    return output;
}

QString DebuggingHelperLibrary::qtVersionForQMake(const QString &qmakePath)
{
    QProcess qmake;
    qmake.start(qmakePath, QStringList(QLatin1String("--version")));
    if (!qmake.waitForFinished())
        return false;
    QString output = qmake.readAllStandardOutput();
    QRegExp regexp(QLatin1String("(QMake version|QMake version:)[\\s]*([\\d.]*)"), Qt::CaseInsensitive);
    regexp.indexIn(output);
    if (regexp.cap(2).startsWith(QLatin1String("2."))) {
        QRegExp regexp2(QLatin1String("Using Qt version[\\s]*([\\d\\.]*)"), Qt::CaseInsensitive);
        regexp2.indexIn(output);
        return regexp2.cap(1);
    }
    return QString();
}

QStringList DebuggingHelperLibrary::possibleQMakeCommands()
{
    // On windows noone has renamed qmake, right?
#ifdef Q_OS_WIN
    return QStringList(QLatin1String("qmake.exe"));
#else
    // On unix some distributions renamed qmake to avoid clashes
    QStringList result;
    result << QLatin1String("qmake-qt4") << QLatin1String("qmake4") << QLatin1String("qmake");
    return result;
#endif
}

<commit_msg>Fixed building debugging helpers: Added missing gdbmacros_p.h<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/

#include "debugginghelper.h"

#include <coreplugin/icore.h>
#include <QtCore/QFileInfo>
#include <QtCore/QCoreApplication>
#include <QtCore/QHash>
#include <QtCore/QProcess>
#include <QtCore/QDir>
#include <QtCore/QDateTime>

#include <QtGui/QDesktopServices>

using namespace ProjectExplorer;

QString DebuggingHelperLibrary::findSystemQt(const Environment &env)
{
    QStringList paths = env.path();
    foreach (const QString &path, paths) {
        foreach (const QString &possibleCommand, possibleQMakeCommands()) {
            const QFileInfo qmake(path + QLatin1Char('/') + possibleCommand);
            if (qmake.exists()) {
                if (!qtVersionForQMake(qmake.absoluteFilePath()).isNull()) {
                    return qmake.absoluteFilePath();
                }
            }
        }
    }
    return QString::null;
}

bool DebuggingHelperLibrary::hasDebuggingHelperLibrary(const QString &qmakePath)
{
    return !debuggingHelperLibrary(qmakePath).isNull();
}

QStringList DebuggingHelperLibrary::debuggingHelperLibraryDirectories(const QString &qtInstallData, const QString &qtpath)
{
    const QChar slash = QLatin1Char('/');
    const uint hash = qHash(qtpath);
    QStringList directories;
    directories
            << (qtInstallData + QLatin1String("/qtc-debugging-helper/"))
            << QDir::cleanPath((QCoreApplication::applicationDirPath() + QLatin1String("/../qtc-debugging-helper/") + QString::number(hash))) + slash
            << (QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QLatin1String("/qtc-debugging-helper/") + QString::number(hash)) + slash;
    return directories;
}

QStringList DebuggingHelperLibrary::debuggingHelperLibraryLocations(const QString &qmakePath)
{
    return debuggingHelperLibraryLocations(qtInstallDataDir(qmakePath), qtDir(qmakePath));
}

QString DebuggingHelperLibrary::debuggingHelperLibrary(const QString &qmakePath)
{
    return debuggingHelperLibrary(qtInstallDataDir(qmakePath), qtDir(qmakePath));
}

QString DebuggingHelperLibrary::qtInstallDataDir(const QString &qmakePath)
{
    QProcess proc;
    proc.start(qmakePath, QStringList() << QLatin1String("-query") << QLatin1String("QT_INSTALL_DATA"));
    if (proc.waitForFinished())
        return QString(proc.readAll().trimmed());
    return QString::null;
}

QString DebuggingHelperLibrary::qtDir(const QString &qmakePath)
{
    QDir dir = QFileInfo(qmakePath).absoluteDir();
    dir.cdUp();
    return dir.absolutePath();
}

// Debugging Helper Library

static inline QString helperFilePath(const QString &directory)
{
#if defined(Q_OS_WIN)
    return directory + QLatin1String("debug/gdbmacros.dll");
#elif defined(Q_OS_MAC)
    return directory + QLatin1String("libgdbmacros.dylib");
#else // generic UNIX
    return directory + QLatin1String("libgdbmacros.so");
#endif
}

QStringList DebuggingHelperLibrary::debuggingHelperLibraryLocations(const QString &qtInstallData, const QString &qtpath)
{
    QStringList result;
    foreach(const QString &directory, debuggingHelperLibraryDirectories(qtInstallData, qtpath))
        result << QFileInfo(helperFilePath(directory)).filePath();
    return result;
}

QString DebuggingHelperLibrary::debuggingHelperLibrary(const QString &qtInstallData, const QString &qtpath)
{
    foreach(const QString &directory, debuggingHelperLibraryDirectories(qtInstallData, qtpath)) {
        const QFileInfo fi(helperFilePath(directory));
        if (fi.exists())
            return fi.filePath();
    }
    return QString();
}

QString DebuggingHelperLibrary::buildDebuggingHelperLibrary(const QString &qmakePath, const QString &make, const Environment &env)
{
    QString errorMessage;
    const QString directory = copyDebuggingHelperLibrary(qtInstallDataDir(qmakePath), qtDir(qmakePath), &errorMessage);
    if (directory.isEmpty())
        return errorMessage;
    return buildDebuggingHelperLibrary(directory, make, qmakePath, QString::null, env);
}

// Copy helper source files to a target directory, replacing older files.
static bool copyDebuggingHelperFiles(const QStringList &files,
                                     const QString &targetDirectory,
                                     QString *errorMessage)
{
    const QString dumperSourcePath = Core::ICore::instance()->resourcePath() + QLatin1String("/gdbmacros/");
    if (!QDir().mkpath(targetDirectory)) {
        *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The target directory %1 could not be created.").arg(targetDirectory);
        return false;
    }
    foreach (const QString &file, files) {
        const QString source = dumperSourcePath + file;
        const QString dest = targetDirectory + file;
        const QFileInfo destInfo(dest);
        if (destInfo.exists()) {
            if (destInfo.lastModified() >= QFileInfo(source).lastModified())
                continue;
            if (!QFile::remove(dest)) {
                *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The existing file %1 could not be removed.").arg(destInfo.absoluteFilePath());
                return false;
            }
        }
        if (!QFile::copy(source, dest)) {
            *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The file %1 could not be copied to %2.").arg(source, dest);
            return false;
        }
    }
    return true;
}

QString DebuggingHelperLibrary::copyDebuggingHelperLibrary(const QString &qtInstallData,
                                                           const QString &qtdir,
                                                           QString *errorMessage)
{
    // Locations to try:
    //    $QTDIR/qtc-debugging-helper
    //    $APPLICATION-DIR/qtc-debugging-helper/$hash
    //    $USERDIR/qtc-debugging-helper/$hash
    const QStringList directories = DebuggingHelperLibrary::debuggingHelperLibraryDirectories(qtInstallData, qtdir);

    QStringList files;
    files << QLatin1String("gdbmacros.cpp") << QLatin1String("gdbmacros_p.h") << QLatin1String("gdbmacros.h") << QLatin1String("gdbmacros.pro")
          << QLatin1String("LICENSE.LGPL") << QLatin1String("LGPL_EXCEPTION.TXT");
    // Try to find a writeable directory.
    foreach(const QString &directory, directories)
        if (copyDebuggingHelperFiles(files, directory, errorMessage)) {
            errorMessage->clear();
            return directory;
        }
    *errorMessage = QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "The debugger helpers could not be built in any of the directories:\n- %1\n\nReason: %2")
                    .arg(directories.join(QLatin1String("\n- ")), *errorMessage);
    return QString();
}

QString DebuggingHelperLibrary::buildDebuggingHelperLibrary(const QString &directory, const QString &makeCommand, const QString &qmakeCommand, const QString &mkspec, const Environment &env)
{
    QString output;
    const QChar newline = QLatin1Char('\n');
    // Setup process
    QProcess proc;
    proc.setEnvironment(env.toStringList());
    proc.setWorkingDirectory(directory);
    proc.setProcessChannelMode(QProcess::MergedChannels);

    output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Building debugging helper library in %1\n").arg(directory);
    output += newline;

    const QString makeFullPath = env.searchInPath(makeCommand);
    if (QFileInfo(directory + QLatin1String("/Makefile")).exists()) {
        if (!makeFullPath.isEmpty()) {
            const QString cleanTarget = QLatin1String("distclean");
            output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Running %1 %2...\n").arg(makeFullPath, cleanTarget);
            proc.start(makeFullPath, QStringList(cleanTarget));
            proc.waitForFinished();
            output += QString::fromLocal8Bit(proc.readAll());
        } else {
            output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "%1 not found in PATH\n").arg(makeCommand);
            return output;
        }
    }
    output += newline;
    output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Running %1 ...\n").arg(qmakeCommand);

    QStringList makeArgs;
    makeArgs << QLatin1String("-spec")<< (mkspec.isEmpty() ? QString(QLatin1String("default")) : mkspec) << QLatin1String("gdbmacros.pro");
    proc.start(qmakeCommand, makeArgs);
    proc.waitForFinished();

    output += proc.readAll();

    output += newline;;
    if (!makeFullPath.isEmpty()) {
        output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "Running %1 ...\n").arg(makeFullPath);
        proc.start(makeFullPath, QStringList());
        proc.waitForFinished();
        output += proc.readAll();
    } else {
        output += QCoreApplication::translate("ProjectExplorer::DebuggingHelperLibrary", "%1 not found in PATH\n").arg(makeCommand);
    }
    return output;
}

QString DebuggingHelperLibrary::qtVersionForQMake(const QString &qmakePath)
{
    QProcess qmake;
    qmake.start(qmakePath, QStringList(QLatin1String("--version")));
    if (!qmake.waitForFinished())
        return false;
    QString output = qmake.readAllStandardOutput();
    QRegExp regexp(QLatin1String("(QMake version|QMake version:)[\\s]*([\\d.]*)"), Qt::CaseInsensitive);
    regexp.indexIn(output);
    if (regexp.cap(2).startsWith(QLatin1String("2."))) {
        QRegExp regexp2(QLatin1String("Using Qt version[\\s]*([\\d\\.]*)"), Qt::CaseInsensitive);
        regexp2.indexIn(output);
        return regexp2.cap(1);
    }
    return QString();
}

QStringList DebuggingHelperLibrary::possibleQMakeCommands()
{
    // On windows noone has renamed qmake, right?
#ifdef Q_OS_WIN
    return QStringList(QLatin1String("qmake.exe"));
#else
    // On unix some distributions renamed qmake to avoid clashes
    QStringList result;
    result << QLatin1String("qmake-qt4") << QLatin1String("qmake4") << QLatin1String("qmake");
    return result;
#endif
}

<|endoftext|>


<commit_before>#include "Runtime/Character/CCharAnimTime.hpp"

#include <algorithm>
#include <cmath>
#include <cfloat>

namespace urde {

CCharAnimTime CCharAnimTime::Infinity() {
  CCharAnimTime ret(1.f);
  ret.x4_type = EType::Infinity;
  return ret;
}

bool CCharAnimTime::EqualsZero() const {
  if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing)
    return true;

  return (x0_time == 0.f);
}

bool CCharAnimTime::EpsilonZero() const { return (std::fabs(x0_time) < 0.00001f); }

bool CCharAnimTime::GreaterThanZero() const {
  if (EqualsZero())
    return false;
  return (x0_time > 0.f);
}

bool CCharAnimTime::operator==(const CCharAnimTime& other) const {
  if (x4_type == EType::NonZero) {
    if (other.x4_type == EType::NonZero)
      return x0_time == other.x0_time;
    return false;
  }

  if (EqualsZero()) {
    if (other.EqualsZero()) {
      int type = -1;
      if (x4_type != EType::ZeroDecreasing) {
        if (x4_type != EType::ZeroSteady)
          type = 1;
        else
          type = 0;
      }

      int otherType = -1;
      if (other.x4_type != EType::ZeroDecreasing) {
        if (other.x4_type != EType::ZeroSteady)
          otherType = 1;
        else
          otherType = 0;
      }

      return type == otherType;
    }
    return false;
  }

  if (other.x4_type == EType::Infinity)
    return x0_time * other.x0_time < 0.f;

  return false;
}

bool CCharAnimTime::operator!=(const CCharAnimTime& other) const { return !(*this == other); }

bool CCharAnimTime::operator>=(const CCharAnimTime& other) const {
  if (*this == other)
    return true;

  return (*this > other);
}

bool CCharAnimTime::operator<=(const CCharAnimTime& other) const {
  if (*this == other)
    return true;

  return (*this < other);
}

bool CCharAnimTime::operator>(const CCharAnimTime& other) const { return (!(*this == other) && !(*this < other)); }

bool CCharAnimTime::operator<(const CCharAnimTime& other) const {
  if (x4_type == EType::NonZero) {
    if (other.x4_type == EType::NonZero)
      return x0_time < other.x0_time;
    if (other.EqualsZero())
      return x0_time < 0.f;
    else
      return other.x0_time > 0.f;
  }

  if (EqualsZero()) {
    if (other.EqualsZero()) {
      int type = -1;
      if (x4_type != EType::ZeroDecreasing) {
        if (x4_type != EType::ZeroSteady)
          type = 1;
        else
          type = 0;
      }

      int otherType = -1;
      if (other.x4_type != EType::ZeroDecreasing) {
        if (other.x4_type != EType::ZeroSteady)
          otherType = 1;
        else
          otherType = 0;
      }

      return type < otherType;
    }

    if (other.x4_type == EType::NonZero)
      return other.x0_time > 0.f;
    return other.x0_time < 0.f;
  } else {
    if (x4_type == EType::Infinity)
      return x0_time < 0.f && other.x0_time > 0.f;
    return x0_time < other.x0_time;
  }
}

CCharAnimTime& CCharAnimTime::operator*=(const CCharAnimTime& other) {
  *this = *this * other;
  return *this;
}

CCharAnimTime& CCharAnimTime::operator+=(const CCharAnimTime& other) {
  *this = *this + other;
  return *this;
}

CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const {
  if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
    if (other.x0_time != x0_time)
      return CCharAnimTime();
    return *this;
  } else if (x4_type == EType::Infinity)
    return *this;
  else if (other.x4_type == EType::Infinity)
    return other;

  if (!EqualsZero() || !other.EqualsZero())
    return CCharAnimTime(x0_time + other.x0_time);

  int type = -1;
  if (x4_type != EType::ZeroDecreasing) {
    if (x4_type != EType::ZeroSteady)
      type = 1;
    else
      type = 0;
  }

  int otherType = -1;
  if (other.x4_type != EType::ZeroDecreasing) {
    if (other.x4_type != EType::ZeroSteady)
      otherType = 1;
    else
      otherType = 0;
  }

  type += otherType;
  otherType = std::max(-1, std::min(type, 1));

  CCharAnimTime ret;
  if (otherType == -1)
    ret.x4_type = EType::ZeroDecreasing;
  else if (otherType == 0)
    ret.x4_type = EType::ZeroSteady;
  else
    ret.x4_type = EType::ZeroIncreasing;

  return ret;
}

CCharAnimTime& CCharAnimTime::operator-=(const CCharAnimTime& other) {
  *this = *this - other;
  return *this;
}

CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const {
  if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
    if (other.x0_time == x0_time)
      return CCharAnimTime();
    return *this;
  } else if (x4_type == EType::Infinity)
    return *this;
  else if (other.x4_type == EType::Infinity) {
    CCharAnimTime ret(-other.x0_time);
    ret.x4_type = EType::Infinity;
    return ret;
  }

  if (!EqualsZero() || !other.EqualsZero())
    return CCharAnimTime(x0_time - other.x0_time);

  int type = -1;
  if (x4_type != EType::ZeroDecreasing) {
    if (x4_type != EType::ZeroSteady)
      type = 1;
    else
      type = 0;
  }

  int otherType = -1;
  if (other.x4_type != EType::ZeroDecreasing) {
    if (other.x4_type != EType::ZeroSteady)
      otherType = 1;
    else
      otherType = 0;
  }

  CCharAnimTime ret;
  type -= otherType;
  if (type == -1)
    ret.x4_type = EType::ZeroDecreasing;
  else if (type == 0)
    ret.x4_type = EType::ZeroSteady;
  else
    ret.x4_type = EType::ZeroIncreasing;

  return ret;
}

CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const {
  if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
    if (other.x0_time != x0_time)
      return CCharAnimTime();
    return *this;
  } else if (x4_type == EType::Infinity)
    return *this;
  else if (other.x4_type == EType::Infinity)
    return other;

  if (!EqualsZero() || !other.EqualsZero())
    return CCharAnimTime(x0_time * other.x0_time);

  int type = -1;
  if (x4_type != EType::ZeroDecreasing) {
    if (x4_type != EType::ZeroSteady)
      type = 1;
    else
      type = 0;
  }

  int otherType = -1;
  if (other.x4_type != EType::ZeroDecreasing) {
    if (other.x4_type != EType::ZeroSteady)
      otherType = 1;
    else
      otherType = 0;
  }

  type += otherType;
  otherType = std::max(-1, std::min(type, 1));

  CCharAnimTime ret;
  if (otherType == -1)
    ret.x4_type = EType::ZeroDecreasing;
  else if (otherType == 0)
    ret.x4_type = EType::ZeroSteady;
  else
    ret.x4_type = EType::ZeroIncreasing;
  return ret;
}

CCharAnimTime CCharAnimTime::operator*(const float& other) const {
  CCharAnimTime ret;
  if (other == 0.f)
    return ret;

  if (!EqualsZero())
    return CCharAnimTime(x0_time * other);

  if (other > 0.f)
    return *this;
  else if (other == 0.f)
    return ret;

  ret.x4_type = x4_type;
  return ret;
}

float CCharAnimTime::operator/(const CCharAnimTime& other) const {
  if (other.EqualsZero())
    return 0.f;

  return x0_time / other.x0_time;
}

} // namespace urde
<commit_msg>CCharAnimTime: Fixes & cleanup<commit_after>#include "Runtime/Character/CCharAnimTime.hpp"

#include <cmath>

namespace urde {

CCharAnimTime CCharAnimTime::Infinity() {
  return {EType::Infinity, 1.f};
}

bool CCharAnimTime::EqualsZero() const {
  if (x4_type == EType::ZeroIncreasing || x4_type == EType::ZeroSteady || x4_type == EType::ZeroDecreasing)
    return true;

  return x0_time == 0.f;
}

bool CCharAnimTime::EpsilonZero() const { return (std::fabs(x0_time) < 0.00001f); }

bool CCharAnimTime::GreaterThanZero() const {
  if (EqualsZero())
    return false;
  return x0_time > 0.f;
}

bool CCharAnimTime::operator==(const CCharAnimTime& other) const {
  if (x4_type == EType::NonZero) {
    if (other.x4_type == EType::NonZero)
      return x0_time == other.x0_time;
    return false;
  }

  if (EqualsZero()) {
    if (other.EqualsZero()) {
      int type = -1;
      if (x4_type != EType::ZeroDecreasing) {
        if (x4_type != EType::ZeroSteady)
          type = 1;
        else
          type = 0;
      }

      int otherType = -1;
      if (other.x4_type != EType::ZeroDecreasing) {
        if (other.x4_type != EType::ZeroSteady)
          otherType = 1;
        else
          otherType = 0;
      }

      return type == otherType;
    }
    return false;
  }

  if (other.x4_type == EType::Infinity)
    return x0_time * other.x0_time < 0.f;

  return false;
}

bool CCharAnimTime::operator!=(const CCharAnimTime& other) const { return !(*this == other); }

bool CCharAnimTime::operator>=(const CCharAnimTime& other) const {
  if (*this == other)
    return true;

  return *this > other;
}

bool CCharAnimTime::operator<=(const CCharAnimTime& other) const {
  if (*this == other)
    return true;

  return *this < other;
}

bool CCharAnimTime::operator>(const CCharAnimTime& other) const { return (!(*this == other) && !(*this < other)); }

bool CCharAnimTime::operator<(const CCharAnimTime& other) const {
  if (x4_type == EType::NonZero) {
    if (other.x4_type == EType::NonZero)
      return x0_time < other.x0_time;
    if (other.EqualsZero())
      return x0_time < 0.f;
    else
      return other.x0_time > 0.f;
  }

  if (EqualsZero()) {
    if (other.EqualsZero()) {
      int type = -1;
      if (x4_type != EType::ZeroDecreasing) {
        if (x4_type != EType::ZeroSteady)
          type = 1;
        else
          type = 0;
      }

      int otherType = -1;
      if (other.x4_type != EType::ZeroDecreasing) {
        if (other.x4_type != EType::ZeroSteady)
          otherType = 1;
        else
          otherType = 0;
      }

      return type < otherType;
    }

    if (other.x4_type == EType::NonZero)
      return other.x0_time > 0.f;
    return other.x0_time < 0.f;
  } else {
    if (x4_type == EType::Infinity)
      return x0_time < 0.f && other.x0_time > 0.f;
    return x0_time < other.x0_time;
  }
}

CCharAnimTime& CCharAnimTime::operator*=(const CCharAnimTime& other) {
  return *this = *this * other;
}

CCharAnimTime& CCharAnimTime::operator+=(const CCharAnimTime& other) {
  return *this = *this + other;
}

CCharAnimTime CCharAnimTime::operator+(const CCharAnimTime& other) const {
  if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
    if (other.x0_time != x0_time)
      return {};
    return *this;
  } else if (x4_type == EType::Infinity)
    return *this;
  else if (other.x4_type == EType::Infinity)
    return other;

  if (!EqualsZero() || !other.EqualsZero())
    return {x0_time + other.x0_time};

  int type = -1;
  if (x4_type != EType::ZeroDecreasing) {
    type = x4_type == EType::ZeroSteady ? 0 : 1;
  }

  int otherType = -1;
  if (other.x4_type != EType::ZeroDecreasing) {
    otherType = other.x4_type == EType::ZeroSteady ? 0 : 1;
  }

  type += otherType;
  otherType = std::max(-1, std::min(type, 1));

  if (otherType == -1)
    return {EType::ZeroDecreasing, 0.f};
  else if (otherType == 0)
    return {EType::ZeroSteady, 0.f};
  else
    return {EType::ZeroIncreasing, 0.f};
}

CCharAnimTime& CCharAnimTime::operator-=(const CCharAnimTime& other) {
  return *this = *this - other;
}

CCharAnimTime CCharAnimTime::operator-(const CCharAnimTime& other) const {
  if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
    if (other.x0_time == x0_time)
      return {};
    return *this;
  } else if (x4_type == EType::Infinity)
    return *this;
  else if (other.x4_type == EType::Infinity) {
    return {EType::Infinity, -other.x0_time};
  }

  if (!EqualsZero() || !other.EqualsZero())
    return {x0_time - other.x0_time};

  int type = -1;
  if (x4_type != EType::ZeroDecreasing) {
    if (x4_type != EType::ZeroSteady)
      type = 1;
    else
      type = 0;
  }

  int otherType = -1;
  if (other.x4_type != EType::ZeroDecreasing) {
    if (other.x4_type != EType::ZeroSteady)
      otherType = 1;
    else
      otherType = 0;
  }

  type -= otherType;
  if (type == -1)
    return {EType::ZeroDecreasing, 0.f};
  else if (type == 0)
    return {EType::ZeroSteady, 0.f};
  else
    return {EType::ZeroIncreasing, 0.f};
}

CCharAnimTime CCharAnimTime::operator*(const CCharAnimTime& other) const {
  if (x4_type == EType::Infinity && other.x4_type == EType::Infinity) {
    if (other.x0_time != x0_time)
      return {};
    return *this;
  } else if (x4_type == EType::Infinity)
    return *this;
  else if (other.x4_type == EType::Infinity)
    return other;

  if (!EqualsZero() || !other.EqualsZero())
    return {x0_time * other.x0_time};

  int type = -1;
  if (x4_type != EType::ZeroDecreasing) {
    if (x4_type != EType::ZeroSteady)
      type = 1;
    else
      type = 0;
  }

  int otherType = -1;
  if (other.x4_type != EType::ZeroDecreasing) {
    if (other.x4_type != EType::ZeroSteady)
      otherType = 1;
    else
      otherType = 0;
  }

  type += otherType;
  otherType = std::max(-1, std::min(type, 1));

  if (otherType == -1)
    return {EType::ZeroDecreasing, 0.f};
  else if (otherType == 0)
    return {EType::ZeroSteady, 0.f};
  else
    return {EType::ZeroIncreasing, 0.f};
}

CCharAnimTime CCharAnimTime::operator*(const float& other) const {
  if (other == 0.f)
    return {};

  if (!EqualsZero())
    return {x0_time * other};

  if (other > 0.f)
    return *this;

  if (x4_type == EType::ZeroDecreasing) {
    return {EType::ZeroIncreasing, 0.f};
  } else if (x4_type == EType::ZeroSteady) {
    return {EType::ZeroSteady, 0.f};
  } else {
    return {EType::ZeroDecreasing, 0.f};
  }
}

float CCharAnimTime::operator/(const CCharAnimTime& other) const {
  if (other.EqualsZero())
    return 0.f;

  return x0_time / other.x0_time;
}

} // namespace urde
<|endoftext|>


<commit_before>///
/// @file  S2LoadBalancer.cpp
/// @brief The S2LoadBalancer evenly distributes the work load between
///        the threads in the computation of the special leaves.
///
/// Simply parallelizing the computation of the special leaves in the
/// Lagarias-Miller-Odlyzko and Deleglise-Rivat algorithms by
/// subdividing the sieve interval by the number of threads into
/// equally sized subintervals does not scale because the distribution
/// of the special leaves is highly skewed and most special leaves are
/// in the first few segments whereas later on there are very few
/// special leaves.
///
/// Based on the above observations it is clear that we need some kind
/// of load balancing in order to scale our parallel algorithm for
/// computing special leaves. Below are the ideas I used to develop a
/// load balancing algorithm that achieves a high load balance by
/// dynamically increasing or decreasing the interval size based on
/// the relative standard deviation of the thread run-times.
///
/// 1) Start with a tiny segment size of x^(1/3) / (log x * log log x)
///    and one segment per thread. Our algorithm uses equally sized
///    intervals, for each thread the interval_size is
///    segment_size * segments_per_thread and the threads process
///    adjacent intervals i.e.
///    [base + interval_size * thread_id, base + interval_size * (thread_id + 1)].
///
/// 2) If the relative standard deviation of the thread run-times is
///    large then we know the special leaves are distributed unevenly,
///    else if the relative standard deviation is low the special
///    leaves are more evenly distributed.
///
/// 3) If the special leaves are distributed unevenly then we can
///    increase the load balance by decreasing the interval_size.
///    Contrary if the special leaves are more evenly distributed
///    we can increase the interval_size in order to improve the
///    algorithm's efficiency.
///
/// 4) We can't use a static threshold for as to when the relative
///    standard deviation is low or large as this threshold varies for
///    different PC architectures. So instead we compare the current
///    relative standard deviation to the previous one in order to
///    decide whether to increase or decrease the interval_size.
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    sum += mean * mean;
  }

  double std_dev = sqrt(sum / max(1.0, n - 1.0));
  double rsd = 100 * std_dev / average;

  return rsd;
}

} // namespace

namespace primecount {

S2LoadBalancer::S2LoadBalancer(maxint_t x, int64_t y, int64_t z, int64_t threads) :
  x_((double) x),
  z_((double) z),
  rsd_(40),
  avg_seconds_(0),
  count_(0)
{
  sqrtz_ = isqrt(z);

  double log_threads = max(1.0, log((double) threads));
  decrease_dividend_ = max(0.5, log_threads / 3);
  min_seconds_ = 0.02 * log_threads;
  update_min_size(log(x_) * log(log(x_)));

  double alpha = get_alpha(x, y);
  double x16 = pow(x_, 1.0 / 6.0);
  smallest_special_leaf_ = (int64_t) (x / (y * sqrt(alpha) * x16));
}

double S2LoadBalancer::get_rsd() const
{
  return rsd_;
}

int64_t S2LoadBalancer::get_min_segment_size() const
{
  return min_size_;
}

bool S2LoadBalancer::decrease_size(double seconds, double decrease) const
{
  return seconds > min_seconds_ &&
         rsd_ > decrease;
}

bool S2LoadBalancer::increase_size(double seconds, double decrease) const
{
  return seconds < avg_seconds_ &&
        !decrease_size(seconds, decrease);
}

/// Used to decide whether to use a smaller or larger
/// segment_size and/or segments_per_thread.
///
double S2LoadBalancer::get_decrease_threshold(double seconds) const
{
  double log_seconds = max(min_seconds_, log(seconds));
  double dont_decrease = min(decrease_dividend_ / (seconds * log_seconds), rsd_);
  return rsd_ + dont_decrease;
}

void S2LoadBalancer::update_avg_seconds(double seconds)
{
  seconds = max(seconds, min_seconds_);
  double dividend = avg_seconds_ * count_ + seconds;
  avg_seconds_ = dividend / (count_ + 1);
  count_++;
}

void S2LoadBalancer::update_min_size(double divisor)
{
  double size = sqrt(z_) / max(1.0, divisor);
  min_size_ = max((int64_t) (1 << 9), (int64_t) size);
  min_size_ = next_power_of_2(min_size_);
}

/// Balance the load in the computation of the special leaves
/// by dynamically adjusting the segment_size and segments_per_thread.
/// @param timings  Timings of the threads.
///
void S2LoadBalancer::update(int64_t low,
                            int64_t threads,
                            int64_t* segment_size,
                            int64_t* segments_per_thread,
                            aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  update_avg_seconds(seconds);
  double decrease_threshold = get_decrease_threshold(seconds);
  rsd_ = max(0.1, relative_standard_deviation(timings));

  // 1 segment per thread
  if (*segment_size < sqrtz_)
  {
    if (increase_size(seconds, decrease_threshold))
      *segment_size <<= 1;
    else if (decrease_size(seconds, decrease_threshold))
      if (*segment_size > min_size_)
        *segment_size >>= 1;
  }
  // many segments per thread
  else if (low > smallest_special_leaf_)
  {
    double factor = decrease_threshold / rsd_;
    factor = in_between(0.5, factor, 2);
    double n = *segments_per_thread * factor;
    n = max(1.0, n);

    if ((n < *segments_per_thread && seconds > min_seconds_) ||
        (n > *segments_per_thread && seconds < avg_seconds_))
    {
      *segments_per_thread = (int) n;
    }
  }

  int64_t high = low + *segment_size * *segments_per_thread * threads;

  // near smallest_special_leaf_ the hard special leaves
  // are distributed unevenly so use min_size_
  if (low <= smallest_special_leaf_ &&
      high > smallest_special_leaf_)
  {
    *segment_size = min_size_;
  }

  high = low + *segment_size * *segments_per_thread * threads;

  // increase min_size_
  if (high >= smallest_special_leaf_)
  {
    update_min_size(1);
    *segment_size = min_size_;
  }
}

} // namespace
<commit_msg>Update S2LoadBalancer.cpp<commit_after>///
/// @file  S2LoadBalancer.cpp
/// @brief The S2LoadBalancer evenly distributes the work load between
///        the threads in the computation of the special leaves.
///
/// Simply parallelizing the computation of the special leaves in the
/// Lagarias-Miller-Odlyzko and Deleglise-Rivat algorithms by
/// subdividing the sieve interval by the number of threads into
/// equally sized subintervals does not scale because the distribution
/// of the special leaves is highly skewed and most special leaves are
/// in the first few segments whereas later on there are very few
/// special leaves.
///
/// Based on the above observations it is clear that we need some kind
/// of load balancing in order to scale our parallel algorithm for
/// computing special leaves. Below are the ideas I used to develop a
/// load balancing algorithm that achieves a high load balance by
/// dynamically increasing or decreasing the interval size based on
/// the relative standard deviation of the thread run-times.
///
/// 1) Start with a tiny segment size of x^(1/3) / (log x * log log x)
///    and one segment per thread. Our algorithm uses equally sized
///    intervals, for each thread the interval_size is
///    segment_size * segments_per_thread and the threads process
///    adjacent intervals i.e.
///    [base + interval_size * thread_id, base + interval_size * (thread_id + 1)].
///
/// 2) If the relative standard deviation of the thread run-times is
///    large then we know the special leaves are distributed unevenly,
///    else if the relative standard deviation is low the special
///    leaves are more evenly distributed.
///
/// 3) If the special leaves are distributed unevenly then we can
///    increase the load balance by decreasing the interval_size.
///    Contrary if the special leaves are more evenly distributed
///    we can increase the interval_size in order to improve the
///    algorithm's efficiency.
///
/// 4) We can't use a static threshold for as to when the relative
///    standard deviation is low or large as this threshold varies for
///    different PC architectures. So instead we compare the current
///    relative standard deviation to the previous one in order to
///    decide whether to increase or decrease the interval_size.
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <S2LoadBalancer.hpp>
#include <primecount-internal.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>
#include <int128.hpp>

#include <stdint.h>
#include <algorithm>
#include <cmath>

using namespace std;
using namespace primecount;

namespace {

double get_average(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double sum = 0;

  for (size_t i = 0; i < n; i++)
    sum += timings[i];

  return sum / n;
}

double relative_standard_deviation(aligned_vector<double>& timings)
{
  size_t n = timings.size();
  double average = get_average(timings);
  double sum = 0;

  if (average == 0)
    return 0;

  for (size_t i = 0; i < n; i++)
  {
    double mean = timings[i] - average;
    sum += mean * mean;
  }

  double std_dev = sqrt(sum / max(1.0, n - 1.0));
  double rsd = 100 * std_dev / average;

  return rsd;
}

} // namespace

namespace primecount {

S2LoadBalancer::S2LoadBalancer(maxint_t x, int64_t y, int64_t z, int64_t threads) :
  x_((double) x),
  z_((double) z),
  rsd_(40),
  avg_seconds_(0),
  count_(0)
{
  sqrtz_ = isqrt(z);

  double log_threads = max(1.0, log((double) threads));
  decrease_dividend_ = max(0.5, log_threads / 3);
  min_seconds_ = 0.02 * log_threads;
  update_min_size(log(x_) * log(log(x_)));

  double alpha = get_alpha(x, y);
  double x16 = pow(x_, 1.0 / 6.0);
  smallest_special_leaf_ = (int64_t) (x / (y * sqrt(alpha) * x16));
}

double S2LoadBalancer::get_rsd() const
{
  return rsd_;
}

int64_t S2LoadBalancer::get_min_segment_size() const
{
  return min_size_;
}

bool S2LoadBalancer::decrease_size(double seconds, double decrease) const
{
  return seconds > min_seconds_ &&
         rsd_ > decrease;
}

bool S2LoadBalancer::increase_size(double seconds, double decrease) const
{
  return seconds < avg_seconds_ &&
        !decrease_size(seconds, decrease);
}

/// Used to decide whether to use a smaller or larger
/// segment_size and/or segments_per_thread.
///
double S2LoadBalancer::get_decrease_threshold(double seconds) const
{
  double log_seconds = max(min_seconds_, log(seconds));
  double dont_decrease = min(decrease_dividend_ / (seconds * log_seconds), rsd_);
  return rsd_ + dont_decrease;
}

void S2LoadBalancer::update_avg_seconds(double seconds)
{
  seconds = max(seconds, min_seconds_);
  double dividend = avg_seconds_ * count_ + seconds;
  avg_seconds_ = dividend / (count_ + 1);
  count_++;
}

void S2LoadBalancer::update_min_size(double divisor)
{
  double size = sqrt(z_) / max(1.0, divisor);
  min_size_ = max((int64_t) (1 << 9), (int64_t) size);
  min_size_ = next_power_of_2(min_size_);
}

/// Balance the load in the computation of the special leaves
/// by dynamically adjusting the segment_size and segments_per_thread.
/// @param timings  Timings of the threads.
///
void S2LoadBalancer::update(int64_t low,
                            int64_t threads,
                            int64_t* segment_size,
                            int64_t* segments_per_thread,
                            aligned_vector<double>& timings)
{
  double seconds = get_average(timings);
  update_avg_seconds(seconds);
  double decrease_threshold = get_decrease_threshold(seconds);
  rsd_ = max(0.1, relative_standard_deviation(timings));

  // 1 segment per thread
  if (*segment_size < sqrtz_)
  {
    if (increase_size(seconds, decrease_threshold))
      *segment_size <<= 1;
    else if (decrease_size(seconds, decrease_threshold))
      if (*segment_size > min_size_)
        *segment_size >>= 1;
  }
  // many segments per thread
  else if (low > smallest_special_leaf_)
  {
    double factor = decrease_threshold / rsd_;
    factor = in_between(0.5, factor, 2);
    double n = *segments_per_thread * factor;
    n = max(1.0, n);

    if ((n < *segments_per_thread && seconds > min_seconds_) ||
        (n > *segments_per_thread && seconds < avg_seconds_))
    {
      *segments_per_thread = (int) n;
    }
  }

  int64_t high = low + *segment_size * *segments_per_thread * threads;

  // near smallest_special_leaf_ the hard special leaves
  // are distributed unevenly so use min_size_
  if (low <= smallest_special_leaf_ &&
      high > smallest_special_leaf_)
  {
    *segment_size = min_size_;
  }

  high = low + *segment_size * *segments_per_thread * threads;

  // increase min_size_
  if (high >= smallest_special_leaf_)
  {
    update_min_size(1);
    *segment_size = max(min_size_, *segment_size);
}

} // namespace
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2009
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE for licensing information
 */

/*
 * ISP: MPI Dynamic Verification Tool
 *
 * File:        TransitionList.hpp
 * Description: Implements lists of transitions from an interleaving
 * Contact:     isp-dev@cs.utah.edu
 */

#ifndef _TRANSITIONLIST_HPP
#define _TRANSITIONLIST_HPP

#include <vector>
#include <list>
#include <algorithm>
#include <sstream>
#include <memory>
#include <boost/iterator/indirect_iterator.hpp>

#include "Envelope.hpp"
#include "Transition.hpp"

using std::unique_ptr;
using std::vector;
using boost::indirect_iterator;
using boost::make_indirect_iterator;

/*
 * This implements a TransitionList and updates "Intra-Completes-Before"
 */
class TransitionList {

public:
    const int pid;

    TransitionList(int p) : pid(p) {}

    inline unsigned int size() const { return tlist.size(); }

    inline Transition & get(int index) const { return *tlist[index]; }

    bool addTransition (unique_ptr<Transition> t);

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> begin () {
        return make_indirect_iterator(tlist.begin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> end () {
        return make_indirect_iterator(tlist.end());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rbegin () {
        return make_indirect_iterator(tlist.rbegin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rend () {
        return make_indirect_iterator(tlist.rend());
    }

private:
    std::vector<std::unique_ptr<Transition> > tlist;

    std::list<int> ulist;

    bool intraCB (const Transition &f, const Transition &s) const;
};

#endif
<commit_msg>Update docs.<commit_after>/*
 * Copyright (c) 2008-2009
 *
 * School of Computing, University of Utah,
 * Salt Lake City, UT 84112, USA
 *
 * and the Gauss Group
 * http://www.cs.utah.edu/formal_verification
 *
 * See LICENSE for licensing information
 */

/*
 * ISP: MPI Dynamic Verification Tool
 *
 * File:        TransitionList.hpp
 * Description: Implements lists of transitions from an interleaving
 * Contact:     isp-dev@cs.utah.edu
 */

#ifndef _TRANSITIONLIST_HPP
#define _TRANSITIONLIST_HPP

#include <vector>
#include <list>
#include <algorithm>
#include <sstream>
#include <memory>
#include <boost/iterator/indirect_iterator.hpp>

#include "Envelope.hpp"
#include "Transition.hpp"

using std::unique_ptr;
using std::vector;
using boost::indirect_iterator;
using boost::make_indirect_iterator;

/*
 * Each process collects a list of transitions.
 */
class TransitionList {

public:
    const int pid;

    TransitionList(int p) : pid(p) {}

    inline unsigned int size() const { return tlist.size(); }

    inline Transition & get(int index) const { return *tlist[index]; }

    bool addTransition (unique_ptr<Transition> t);

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> begin () {
        return make_indirect_iterator(tlist.begin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::iterator> end () {
        return make_indirect_iterator(tlist.end());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rbegin () {
        return make_indirect_iterator(tlist.rbegin());
    }

    inline indirect_iterator<vector<unique_ptr<Transition> >::reverse_iterator> rend () {
        return make_indirect_iterator(tlist.rend());
    }

private:
    std::vector<std::unique_ptr<Transition> > tlist;

    std::list<int> ulist;

    bool intraCB (const Transition &f, const Transition &s) const;
};

#endif
<|endoftext|>