<commit_before>#ifndef __EXTENSION_EXPLICIT_COUNTERSTRATEGY_HPP
#define __EXTENSION_EXPLICIT_COUNTERSTRATEGY_HPP

#include "gr1context.hpp"
#include <string>

/**
 * A class that computes an explicit state counterstrategy for an unrealizable specification
 */
template<class T> class XExtractExplicitCounterStrategy : public T {
protected:
    // New variables
    std::string outputFilename;

    // Inherited stuff used
    using T::mgr;
    using T::strategyDumpingData;
    using T::livenessGuarantees;
    using T::livenessAssumptions;
    using T::varVectorPre;
    using T::varVectorPost;
    using T::varCubePostOutput;
    using T::varCubePostInput;
    using T::varCubePreOutput;
    using T::varCubePreInput;
    using T::varCubePre;
    using T::varCubePost;
    using T::safetyEnv;
    using T::safetySys;
    using T::winningPositions;
    using T::initEnv;
    using T::initSys;
    using T::preVars;
    using T::postVars;
    using T::variableTypes;
    using T::variables;
    using T::variableNames;
    using T::realizable;
    using T::determinize;
    using T::postInputVars;
    using T::postOutputVars;

    XExtractExplicitCounterStrategy<T>(std::list<std::string> &filenames) : T(filenames) {
        if (filenames.size()==0) {
            outputFilename = "";
        } else {
            outputFilename = filenames.front();
            filenames.pop_front();
        }
    }

public:

/**
 * @brief Compute and print out (to stdout) an explicit-state counter strategy that is winning for
 *        the environment. The output is compatible with the old JTLV output of LTLMoP.
 *        This function requires that the unrealizability of the specification has already been
 *        detected and that the variables "strategyDumpingData" and
 *        "winningPositions" have been filled by the synthesis algorithm with meaningful data.
 * @param outputStream - Where the strategy shall be printed to.
 */
void execute() {
        T::execute();
        if (!realizable) {
            if (outputFilename=="") {
                computeAndPrintExplicitStateStrategy(std::cout);
            } else {
                std::ofstream of(outputFilename.c_str());
                if (of.fail()) {
                    SlugsException ex(false);
                    ex << "Error: Could not open output file'" << outputFilename << "\n";
                    throw ex;
                }
                computeAndPrintExplicitStateStrategy(of);
                if (of.fail()) {
                    SlugsException ex(false);
                    ex << "Error: Writing to output file'" << outputFilename << "failed. \n";
                    throw ex;
                }
                of.close();
            }
        }
}

void computeAndPrintExplicitStateStrategy(std::ostream &outputStream) {

    // We don't want any reordering from this point onwards, as
    // the BDD manipulations from this point onwards are 'kind of simple'.
    mgr.setAutomaticOptimisation(false);

    // List of states in existance so far. The first map
    // maps from a BF node pointer (for the pre variable valuation) and a goal
    // to a state number. The vector then contains the concrete valuation.
    std::map<std::pair<size_t, std::pair<unsigned int, unsigned int> >, unsigned int > lookupTableForPastStates;
    std::vector<BF> bfsUsedInTheLookupTable;
    std::list<std::pair<size_t, std::pair<unsigned int, unsigned int> > > todoList;

    // Prepare positional strategies for the individual goals
    std::vector<std::vector<BF> > positionalStrategiesForTheIndividualGoals(livenessAssumptions.size());
    for (unsigned int i=0;i<livenessAssumptions.size();i++) {
        //BF casesCovered = mgr.constantFalse();
        std::vector<BF> strategy(livenessGuarantees.size()+1);
        for (unsigned int j=0;j<livenessGuarantees.size()+1;j++) {
            strategy[j] = mgr.constantFalse();
        }
        for (auto it = strategyDumpingData.begin();it!=strategyDumpingData.end();it++) {
            if (boost::get<0>(*it) == i) {
                //Have to cover each guarantee (since the winning strategy depends on which guarantee is being pursued)
                //Essentially, the choice of which guarantee to pursue can be thought of as a system "move".
                //The environment always to chooses that prevent the appropriate guarantee.
                strategy[boost::get<1>(*it)] |= boost::get<2>(*it).UnivAbstract(varCubePostOutput) & !(strategy[boost::get<1>(*it)].ExistAbstract(varCubePost));
            }
        }

        positionalStrategiesForTheIndividualGoals[i] = strategy;
    }

    // Prepare initial to-do list from the allowed initial states. Select a single initial input valuation.

    // TODO: Support for non-special-robotics semantics
    BF_newDumpDot(*this,winningPositions,"PreInput PreOutput PostInput PostOutput","/tmp/winningPositions.dot");
    BF todoInit = (winningPositions & initEnv & initSys);
    while (!(todoInit.isFalse())) {
        BF concreteState = determinize(todoInit,preVars);

        //find which liveness guarantee is being prevented (finds the first liveness in order specified)
        // Note by Ruediger here: Removed "!livenessGuarantees[j]" as condition as it is non-positional
        unsigned int found_j_index = 0;
        for (unsigned int j=0;j<livenessGuarantees.size();j++) {
            if (!(concreteState & positionalStrategiesForTheIndividualGoals[0][j]).isFalse()) {
                found_j_index = j;
                break;
            }
        }

        std::pair<size_t, std::pair<unsigned int, unsigned int> > lookup = std::pair<size_t, std::pair<unsigned int, unsigned int> >(concreteState.getHashCode(),std::pair<unsigned int, unsigned int>(0,found_j_index));
        lookupTableForPastStates[lookup] = bfsUsedInTheLookupTable.size();
        bfsUsedInTheLookupTable.push_back(concreteState);
        //from now on use the same initial input valuation (but consider all other initial output valuations)
        todoInit &= !concreteState;
        todoList.push_back(lookup);
    }

    // Extract strategy
    while (todoList.size()>0) {
        std::pair<size_t, std::pair<unsigned int, unsigned int> > current = todoList.front();
        todoList.pop_front();
        unsigned int stateNum = lookupTableForPastStates[current];
        BF currentPossibilities = bfsUsedInTheLookupTable[stateNum];
        // Print state information
        outputStream << "State " << stateNum << " with rank (" << current.second.first << "," << current.second.second << ") -> <";
        bool first = true;
        for (unsigned int i=0;i<variables.size();i++) {
            if (variableTypes[i] < PostInput) {
                if (first) {
                    first = false;
                } else {
                    outputStream << ", ";
                }
                outputStream << variableNames[i] << ":";
                outputStream << (((currentPossibilities & variables[i]).isFalse())?"0":"1");
            }
        }

        outputStream << ">\n\tWith successors : ";
        first = true;

        // Can we enforce a deadlock?
        BF deadlockInput = (currentPossibilities & safetyEnv & !safetySys).UnivAbstract(varCubePostOutput);
        if (deadlockInput!=mgr.constantFalse()) {
            addDeadlocked(deadlockInput.ExistAbstract(varCubePre), current, bfsUsedInTheLookupTable,  lookupTableForPastStates, outputStream);
        } else {

            // No deadlock in sight
            currentPossibilities &= positionalStrategiesForTheIndividualGoals[current.second.first][current.second.second];
            BF remainingTransitions = currentPossibilities;

            // Choose one next input and stick to it!
            remainingTransitions = determinize(remainingTransitions,postInputVars);

            // Switching goals
            while (!(remainingTransitions & safetySys).isFalse()) {

                BF newCombination;

                if ((remainingTransitions & livenessAssumptions[current.second.first]).isFalse()) {
                    newCombination = determinize(remainingTransitions & safetySys, postOutputVars);
                } else {
                    newCombination = determinize((remainingTransitions & safetySys & livenessAssumptions[current.second.first]),postOutputVars);
                }

                // Jump as much forward  in the liveness assumption list as possible ("stuttering avoidance")
                unsigned int nextLivenessAssumption = current.second.first;
                bool firstTry = true;
                while (((nextLivenessAssumption != current.second.first) | firstTry) && !((livenessAssumptions[nextLivenessAssumption] & newCombination).isFalse())) {
                    nextLivenessAssumption  = (nextLivenessAssumption + 1) % livenessAssumptions.size();
                    firstTry = false;
                }

                //Mark which input has been captured by this case. Use the same input for other successors
                remainingTransitions &= !newCombination;

                if (nextLivenessAssumption != current.second.second) {
                    unsigned int found_j_index = 0;
                    for (unsigned int j=0;j<livenessGuarantees.size();j++) {
                        if (!(newCombination & !livenessGuarantees[j] & positionalStrategiesForTheIndividualGoals[current.second.first][j]).isFalse()) {
                            found_j_index = j;
                            break;
                        }
                    }
                    current.second.second = found_j_index;
                }

                // We don't need the pre information from the point onwards anymore.
                newCombination = newCombination.ExistAbstract(varCubePre).SwapVariables(varVectorPre,varVectorPost);

                unsigned int tn;

                std::pair<size_t, std::pair<unsigned int, unsigned int> > target;

                target = std::pair<size_t, std::pair<unsigned int, unsigned int> >(newCombination.getHashCode(),std::pair<unsigned int, unsigned int>(nextLivenessAssumption, current.second.second));

                if (lookupTableForPastStates.count(target)==0) {
                    tn = lookupTableForPastStates[target] = bfsUsedInTheLookupTable.size();
                    bfsUsedInTheLookupTable.push_back(newCombination);
                    todoList.push_back(target);
                } else {
                    tn = lookupTableForPastStates[target];
                }

                // Print
                if (first) {
                    first = false;
                } else {
                    outputStream << ", ";
                }
                outputStream << tn;

            }
        }

        outputStream << "\n";
    }
    }

    //This function adds a new successor-less "state" that captures the deadlock-causing input values
    //The outputvalues are omitted (indeed, no valuation exists that satisfies the system safeties)
    //Format compatible with JTLV counterstrategy

    void addDeadlocked(BF targetPositionCandidateSet, std::pair<size_t, std::pair<unsigned int, unsigned int> > current, std::vector<BF> &bfsUsedInTheLookupTable, std::map<std::pair<size_t, std::pair<unsigned int, unsigned int> >, unsigned int > &lookupTableForPastStates, std::ostream &outputStream) {

    BF newCombination = determinize(targetPositionCandidateSet, postVars) ;

    newCombination  = newCombination.ExistAbstract(varCubePreOutput);

    std::pair<size_t, std::pair<unsigned int, unsigned int> > target = std::pair<size_t, std::pair<unsigned int, unsigned int> >(newCombination.getHashCode(),std::pair<unsigned int, unsigned int>(current.second.first, current.second.second));
    unsigned int tn;

    if (lookupTableForPastStates.count(target)==0) {
        tn = lookupTableForPastStates[target] = bfsUsedInTheLookupTable.size();
        bfsUsedInTheLookupTable.push_back(newCombination);
        outputStream << tn << "\n";

        //Note that since we are printing here, we usually end up with the states being printed out of order.
        //TOTO: print in order
        outputStream << "State " << tn << " with rank (" << current.second.first << "," << current.second.second << ") -> <";
        bool first = true;
        for (unsigned int i=0;i<variables.size();i++) {
            if (variableTypes[i] < PreOutput) {
                if (first) {
                    first = false;
                } else {
                    outputStream << ", ";
                }
                outputStream << variableNames[i] << ":";
                outputStream << (((newCombination & variables[i]).isFalse())?"0":"1");
            }
        }
        outputStream << ">\n\tWith no successors.";

    } else {
        tn = lookupTableForPastStates[target];
        outputStream << tn;
    }

}

    static GR1Context* makeInstance(std::list<std::string> &filenames) {
        return new XExtractExplicitCounterStrategy<T>(filenames);
    }
};

#endif

<commit_msg>Small update of the counter-strategy code. Should correct some corner-cases<commit_after>#ifndef __EXTENSION_EXPLICIT_COUNTERSTRATEGY_HPP
#define __EXTENSION_EXPLICIT_COUNTERSTRATEGY_HPP

#include "gr1context.hpp"
#include <string>

/**
 * A class that computes an explicit state counterstrategy for an unrealizable specification
 */
template<class T> class XExtractExplicitCounterStrategy : public T {
protected:
    // New variables
    std::string outputFilename;

    // Inherited stuff used
    using T::mgr;
    using T::strategyDumpingData;
    using T::livenessGuarantees;
    using T::livenessAssumptions;
    using T::varVectorPre;
    using T::varVectorPost;
    using T::varCubePostOutput;
    using T::varCubePostInput;
    using T::varCubePreOutput;
    using T::varCubePreInput;
    using T::varCubePre;
    using T::varCubePost;
    using T::safetyEnv;
    using T::safetySys;
    using T::winningPositions;
    using T::initEnv;
    using T::initSys;
    using T::preVars;
    using T::postVars;
    using T::variableTypes;
    using T::variables;
    using T::variableNames;
    using T::realizable;
    using T::determinize;
    using T::postInputVars;
    using T::postOutputVars;

    XExtractExplicitCounterStrategy<T>(std::list<std::string> &filenames) : T(filenames) {
        if (filenames.size()==0) {
            outputFilename = "";
        } else {
            outputFilename = filenames.front();
            filenames.pop_front();
        }
    }

public:

/**
 * @brief Compute and print out (to stdout) an explicit-state counter strategy that is winning for
 *        the environment. The output is compatible with the old JTLV output of LTLMoP.
 *        This function requires that the unrealizability of the specification has already been
 *        detected and that the variables "strategyDumpingData" and
 *        "winningPositions" have been filled by the synthesis algorithm with meaningful data.
 * @param outputStream - Where the strategy shall be printed to.
 */
void execute() {
        T::execute();
        if (!realizable) {
            if (outputFilename=="") {
                computeAndPrintExplicitStateStrategy(std::cout);
            } else {
                std::ofstream of(outputFilename.c_str());
                if (of.fail()) {
                    SlugsException ex(false);
                    ex << "Error: Could not open output file'" << outputFilename << "\n";
                    throw ex;
                }
                computeAndPrintExplicitStateStrategy(of);
                if (of.fail()) {
                    SlugsException ex(false);
                    ex << "Error: Writing to output file'" << outputFilename << "failed. \n";
                    throw ex;
                }
                of.close();
            }
        }
}

void computeAndPrintExplicitStateStrategy(std::ostream &outputStream) {

    // We don't want any reordering from this point onwards, as
    // the BDD manipulations from this point onwards are 'kind of simple'.
    mgr.setAutomaticOptimisation(false);

    // List of states in existance so far. The first map
    // maps from a BF node pointer (for the pre variable valuation) and a goal
    // to a state number. The vector then contains the concrete valuation.
    std::map<std::pair<size_t, std::pair<unsigned int, unsigned int> >, unsigned int > lookupTableForPastStates;
    std::vector<BF> bfsUsedInTheLookupTable;
    std::list<std::pair<size_t, std::pair<unsigned int, unsigned int> > > todoList;

    // Prepare positional strategies for the individual goals
    std::vector<std::vector<BF> > positionalStrategiesForTheIndividualGoals(livenessAssumptions.size());
    for (unsigned int i=0;i<livenessAssumptions.size();i++) {
        //BF casesCovered = mgr.constantFalse();
        std::vector<BF> strategy(livenessGuarantees.size()+1);
        for (unsigned int j=0;j<livenessGuarantees.size()+1;j++) {
            strategy[j] = mgr.constantFalse();
        }
        for (auto it = strategyDumpingData.begin();it!=strategyDumpingData.end();it++) {
            if (boost::get<0>(*it) == i) {
                //Have to cover each guarantee (since the winning strategy depends on which guarantee is being pursued)
                //Essentially, the choice of which guarantee to pursue can be thought of as a system "move".
                //The environment always to chooses that prevent the appropriate guarantee.
                strategy[boost::get<1>(*it)] |= boost::get<2>(*it).UnivAbstract(varCubePostOutput) & !(strategy[boost::get<1>(*it)].ExistAbstract(varCubePost));
            }
        }

        positionalStrategiesForTheIndividualGoals[i] = strategy;
    }

    // Prepare initial to-do list from the allowed initial states. Select a single initial input valuation.

    // TODO: Support for non-special-robotics semantics
    BF_newDumpDot(*this,winningPositions,"PreInput PreOutput PostInput PostOutput","/tmp/winningPositions.dot");
    BF todoInit = (winningPositions & initEnv & initSys);
    while (!(todoInit.isFalse())) {
        BF concreteState = determinize(todoInit,preVars);

        //find which liveness guarantee is being prevented (finds the first liveness in order specified)
        // Note by Ruediger here: Removed "!livenessGuarantees[j]" as condition as it is non-positional
        unsigned int found_j_index = 0;
        for (unsigned int j=0;j<livenessGuarantees.size();j++) {
            if (!(concreteState & positionalStrategiesForTheIndividualGoals[0][j]).isFalse()) {
                found_j_index = j;
                break;
            }
        }

        std::pair<size_t, std::pair<unsigned int, unsigned int> > lookup = std::pair<size_t, std::pair<unsigned int, unsigned int> >(concreteState.getHashCode(),std::pair<unsigned int, unsigned int>(0,found_j_index));
        lookupTableForPastStates[lookup] = bfsUsedInTheLookupTable.size();
        bfsUsedInTheLookupTable.push_back(concreteState);
        //from now on use the same initial input valuation (but consider all other initial output valuations)
        todoInit &= !concreteState;
        todoList.push_back(lookup);
    }

    // Extract strategy
    while (todoList.size()>0) {
        std::pair<size_t, std::pair<unsigned int, unsigned int> > current = todoList.front();
        todoList.pop_front();
        unsigned int stateNum = lookupTableForPastStates[current];
        BF currentPossibilities = bfsUsedInTheLookupTable[stateNum];
        // Print state information
        outputStream << "State " << stateNum << " with rank (" << current.second.first << "," << current.second.second << ") -> <";
        bool first = true;
        for (unsigned int i=0;i<variables.size();i++) {
            if (variableTypes[i] < PostInput) {
                if (first) {
                    first = false;
                } else {
                    outputStream << ", ";
                }
                outputStream << variableNames[i] << ":";
                outputStream << (((currentPossibilities & variables[i]).isFalse())?"0":"1");
            }
        }

        outputStream << ">\n\tWith successors : ";
        first = true;

        // Can we enforce a deadlock?
        BF deadlockInput = (currentPossibilities & safetyEnv & !safetySys).UnivAbstract(varCubePostOutput);
        if (deadlockInput!=mgr.constantFalse()) {
            addDeadlocked(deadlockInput.ExistAbstract(varCubePre), current, bfsUsedInTheLookupTable,  lookupTableForPastStates, outputStream);
        } else {

            // No deadlock in sight
            currentPossibilities &= positionalStrategiesForTheIndividualGoals[current.second.first][current.second.second];
            BF remainingTransitions = currentPossibilities;

            // Choose one next input and stick to it!
            remainingTransitions = determinize(remainingTransitions,postInputVars);

            // Switching goals
            while (!(remainingTransitions & safetySys).isFalse()) {

                BF newCombination;
                BF safeTransition = remainingTransitions & safetySys;
                BF testerForLivenessAssumptions = safeTransition & livenessAssumptions[current.second.first];
                if (testerForLivenessAssumptions.isFalse()) {
                    newCombination = determinize(safeTransition, postOutputVars);
                } else {
                    newCombination = determinize(testerForLivenessAssumptions,postOutputVars);
                }

                // Jump as much forward  in the liveness assumption list as possible ("stuttering avoidance")
                unsigned int nextLivenessAssumption = current.second.first;
                bool firstTry = true;
                while (((nextLivenessAssumption != current.second.first) | firstTry) && !((livenessAssumptions[nextLivenessAssumption] & newCombination).isFalse())) {
                    nextLivenessAssumption  = (nextLivenessAssumption + 1) % livenessAssumptions.size();
                    firstTry = false;
                }

                //Mark which input has been captured by this case. Use the same input for other successors
                remainingTransitions &= !newCombination;

                if (nextLivenessAssumption != current.second.second) {
                    unsigned int found_j_index = 0;
                    for (unsigned int j=0;j<livenessGuarantees.size();j++) {
                        if (!(newCombination & !livenessGuarantees[j] & positionalStrategiesForTheIndividualGoals[current.second.first][j]).isFalse()) {
                            found_j_index = j;
                            break;
                        }
                    }
                    current.second.second = found_j_index;
                }

                // We don't need the pre information from the point onwards anymore.
                newCombination = newCombination.ExistAbstract(varCubePre).SwapVariables(varVectorPre,varVectorPost);

                unsigned int tn;

                std::pair<size_t, std::pair<unsigned int, unsigned int> > target;

                target = std::pair<size_t, std::pair<unsigned int, unsigned int> >(newCombination.getHashCode(),std::pair<unsigned int, unsigned int>(nextLivenessAssumption, current.second.second));

                if (lookupTableForPastStates.count(target)==0) {
                    tn = lookupTableForPastStates[target] = bfsUsedInTheLookupTable.size();
                    bfsUsedInTheLookupTable.push_back(newCombination);
                    todoList.push_back(target);
                } else {
                    tn = lookupTableForPastStates[target];
                }

                // Print
                if (first) {
                    first = false;
                } else {
                    outputStream << ", ";
                }
                outputStream << tn;

            }
        }

        outputStream << "\n";
    }
    }

    //This function adds a new successor-less "state" that captures the deadlock-causing input values
    //The outputvalues are omitted (indeed, no valuation exists that satisfies the system safeties)
    //Format compatible with JTLV counterstrategy

    void addDeadlocked(BF targetPositionCandidateSet, std::pair<size_t, std::pair<unsigned int, unsigned int> > current, std::vector<BF> &bfsUsedInTheLookupTable, std::map<std::pair<size_t, std::pair<unsigned int, unsigned int> >, unsigned int > &lookupTableForPastStates, std::ostream &outputStream) {

    BF newCombination = determinize(targetPositionCandidateSet, postVars) ;

    newCombination  = newCombination.ExistAbstract(varCubePreOutput);

    std::pair<size_t, std::pair<unsigned int, unsigned int> > target = std::pair<size_t, std::pair<unsigned int, unsigned int> >(newCombination.getHashCode(),std::pair<unsigned int, unsigned int>(current.second.first, current.second.second));
    unsigned int tn;

    if (lookupTableForPastStates.count(target)==0) {
        tn = lookupTableForPastStates[target] = bfsUsedInTheLookupTable.size();
        bfsUsedInTheLookupTable.push_back(newCombination);
        outputStream << tn << "\n";

        //Note that since we are printing here, we usually end up with the states being printed out of order.
        //TOTO: print in order
        outputStream << "State " << tn << " with rank (" << current.second.first << "," << current.second.second << ") -> <";
        bool first = true;
        for (unsigned int i=0;i<variables.size();i++) {
            if (variableTypes[i] < PreOutput) {
                if (first) {
                    first = false;
                } else {
                    outputStream << ", ";
                }
                outputStream << variableNames[i] << ":";
                outputStream << (((newCombination & variables[i]).isFalse())?"0":"1");
            }
        }
        outputStream << ">\n\tWith no successors.";

    } else {
        tn = lookupTableForPastStates[target];
        outputStream << tn;
    }

}

    static GR1Context* makeInstance(std::list<std::string> &filenames) {
        return new XExtractExplicitCounterStrategy<T>(filenames);
    }
};

#endif

<|endoftext|>


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

#ifndef UTIL_DETAIL_ALLOC_PMR
#define UTIL_DETAIL_ALLOC_PMR

#include <common>
#include <deque>
#include <delegate>
#include <util/units.hpp>

namespace os::mem::detail {

  class Pmr_pool : public std::enable_shared_from_this<Pmr_pool>, public std::pmr::memory_resource {
  public:
    using Resource     = os::mem::Pmr_pool::Resource;
    using Resource_ptr = os::mem::Pmr_pool::Resource_ptr;
    Pmr_pool(std::size_t total_max, std::size_t suballoc_max, std::size_t max_allocs)
      : cap_total_{total_max}, cap_suballoc_{suballoc_max}, max_resources_{max_allocs} {}

    void* do_allocate(size_t size, size_t align) override {
      if (UNLIKELY(size + allocated_ > cap_total_)) {
        throw std::bad_alloc();
      }

      // Adapt to memalign's minimum size- and alignemnt requiremnets
      if (align < sizeof(void*))
        align = sizeof(void*);

      if (size < sizeof(void*))
        size = sizeof(void*);

      void* buf = memalign(align, size);

      if (buf == nullptr) {
        throw std::bad_alloc();
      }

      allocated_ += size;
      allocations_++;
      return buf;
    }

    void do_deallocate (void* ptr, size_t size, size_t) override {

      // Adapt to memalign
      if (size < sizeof(void*))
        size = sizeof(void*);

      free(ptr);
      allocated_ -= size;
      deallocations_++;
    }

    bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
      return *this == other;
    }

    Resource_ptr resource_from_raw(Resource* raw) {
      Resource_ptr res_ptr(raw, [this](auto* res) {
          Expects(res->pool().get() == this);
          this->return_resource(res);
        });

      return res_ptr;
    }

    Resource_ptr new_resource() {
      Expects(resource_count() < max_resources_);

      auto res = resource_from_raw(new Pmr_resource(shared_ptr()));
      used_resources_++;

      Ensures(res != nullptr);
      Ensures(resource_count() <= max_resources_);
      return res;
    }

    Resource_ptr release_front() {
      auto released = std::move(free_resources_.front());
      free_resources_.pop_front();
      used_resources_++;
      return released;
    }

    void return_resource(Resource* raw) {
      Expects(used_resources_ > 0);
      auto res_ptr = resource_from_raw(raw);
      used_resources_--;
      free_resources_.emplace_back(std::move(res_ptr));
    }

    Resource_ptr get_resource() {

      if (! free_resources_.empty()) {

        auto& res = free_resources_.front();

        if (UNLIKELY(! res->empty() and resource_count() < max_resources_)) {
          return new_resource();
        }
        return release_front();
      }

      if (resource_count() >= max_resources_)
        return nullptr;

      return new_resource();
    }

    std::shared_ptr<Pmr_pool> shared_ptr() {
      return shared_from_this();
    }

    std::size_t resource_count() {
      return used_resources_ + free_resources_.size();
    }

    std::size_t free_resources() {
      return free_resources_.size();
    }

    std::size_t used_resources() {
      return used_resources_;
    }

    std::size_t total_capacity() {
      return cap_total_;
    }

    void set_resource_capacity(std::size_t sz) {
      cap_suballoc_ = sz;
    }

    void set_total_capacity(std::size_t sz) {
      cap_total_ = sz;
    }

    std::size_t resource_capacity() {
      if (cap_suballoc_ == 0)
        return cap_total_ / (used_resources_ + os::mem::Pmr_pool::resource_division_offset);
      return cap_suballoc_;
    }

    std::size_t bytes_booked() {
      return cap_suballoc_ * used_resources_;
    }

    std::size_t bytes_bookable() {
      auto booked = bytes_booked();
      if (booked > cap_total_)
        return 0;

      return cap_total_ - booked;
    }

    std::size_t allocated() {
      return allocated_;
    }

    std::size_t alloc_count() {
      return allocations_;
    }

    std::size_t dealloc_count() {
      return deallocations_;
    }

    bool full() {
      return allocated_ >= cap_total_;
    }

    bool empty() {
      return allocated_ == 0;
    }

    std::size_t allocatable() {
      auto allocd = allocated();
      if (allocd > cap_total_)
        return 0;
      return cap_total_ - allocd;
    }

    // NOTE: This can cause leaks or other chaos if you're not sure what you're doing
    void clear_free_resources() {
      for (auto& res : free_resources_) {
        *res = Resource(shared_ptr());
      }
    }

  private:
    std::size_t allocated_      = 0;
    std::size_t allocations_    = 0;
    std::size_t deallocations_  = 0;
    std::size_t cap_total_      = 0;
    std::size_t cap_suballoc_   = 0;
    std::size_t max_resources_  = 0;
    std::size_t used_resources_ = 0;
    std::deque<Resource_ptr> free_resources_{};
  };

} // os::mem::detail

namespace os::mem {

  //
  // Pmr_pool implementatino (PIMPL wrapper)
  //
  std::size_t Pmr_pool::total_capacity() { return impl->total_capacity(); }
  std::size_t Pmr_pool::resource_capacity() { return impl->resource_capacity(); }
  std::size_t Pmr_pool::allocatable() { return impl->allocatable(); }
  std::size_t Pmr_pool::allocated() { return impl->allocated(); }

  void Pmr_pool::set_resource_capacity(std::size_t s) { impl->set_resource_capacity(s); }
  void Pmr_pool::set_total_capacity(std::size_t s) { impl->set_total_capacity(s); };

  Pmr_pool::Pmr_pool(size_t sz, size_t sz_sub, size_t max_allocs)
    : impl{std::make_shared<detail::Pmr_pool>(sz, sz_sub, max_allocs)}{}
  Pmr_pool::Resource_ptr Pmr_pool::get_resource() { return impl->get_resource(); }
  std::size_t Pmr_pool::resource_count() { return impl->resource_count(); }
  std::size_t Pmr_pool::alloc_count() { return impl->alloc_count(); }
  std::size_t Pmr_pool::dealloc_count() { return impl->dealloc_count(); }
  void Pmr_pool::return_resource(Resource* res) { impl->return_resource(res); }
  bool Pmr_pool::full() { return impl->full(); }
  bool Pmr_pool::empty() { return impl->empty(); }

  //
  // Pmr_resource implementation
  //
  Pmr_resource::Pmr_resource(Pool_ptr p) : pool_{p} {}
  std::size_t Pmr_resource::capacity() { return pool_->resource_capacity(); }
  std::size_t Pmr_resource::allocatable() {
    auto cap = capacity();
    if (used > cap)
      return 0;
    return cap - used;
  }

  std::size_t Pmr_resource::allocated() {
    return used;
  }

  Pmr_resource::Pool_ptr Pmr_resource::pool() {
    return pool_;
  }

  void* Pmr_resource::do_allocate(std::size_t size, std::size_t align) {
    auto cap = capacity();
    if (UNLIKELY(size + used > cap)) {
      throw std::bad_alloc();
    }

    void* buf = pool_->allocate(size, align);

    used += size;
    allocs++;

    return buf;
  }

  void Pmr_resource::do_deallocate(void* ptr, std::size_t s, std::size_t a) {
    Expects(s != 0); // POSIX malloc will allow size 0, but return nullptr.
    bool trigger_non_full = UNLIKELY(full() and non_full != nullptr);
    bool trigger_avail_thresh = UNLIKELY(allocatable() < avail_thresh
                                         and allocatable() + s >= avail_thresh
                                         and avail != nullptr);

    pool_->deallocate(ptr,s,a);
    deallocs++;
    used -= s;

    if (UNLIKELY(trigger_avail_thresh)) {
      Ensures(allocatable() >= avail_thresh);
      Ensures(avail != nullptr);
      avail(*this);
    }

    if (UNLIKELY(trigger_non_full)) {
      Ensures(!full());
      Ensures(non_full != nullptr);
      non_full(*this);
    }
  }

  bool Pmr_resource::do_is_equal(const std::pmr::memory_resource& other) const noexcept {
    if (const auto* other_ptr = dynamic_cast<const Pmr_resource*>(&other)) {
      return this == other_ptr;
    }
    return false;
  }

  bool Pmr_resource::full() {
    return used >= capacity();
  }

  bool Pmr_resource::empty() {
    return used == 0;
  }
}

#endif
<commit_msg>pmr: Don't promise more capacity than whats actually remaining in pool<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2018 IncludeOS AS, Oslo, Norway
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef UTIL_DETAIL_ALLOC_PMR
#define UTIL_DETAIL_ALLOC_PMR

#include <common>
#include <deque>
#include <delegate>
#include <util/units.hpp>

namespace os::mem::detail {

  class Pmr_pool : public std::enable_shared_from_this<Pmr_pool>, public std::pmr::memory_resource {
  public:
    using Resource     = os::mem::Pmr_pool::Resource;
    using Resource_ptr = os::mem::Pmr_pool::Resource_ptr;
    Pmr_pool(std::size_t total_max, std::size_t suballoc_max, std::size_t max_allocs)
      : cap_total_{total_max}, cap_suballoc_{suballoc_max}, max_resources_{max_allocs} {}

    void* do_allocate(size_t size, size_t align) override {
      if (UNLIKELY(size + allocated_ > cap_total_)) {
        //printf("pmr about to throw bad alloc: sz=%zu alloc=%zu cap=%zu\n", size, allocated_, cap_total_);
        throw std::bad_alloc();
      }

      // Adapt to memalign's minimum size- and alignemnt requiremnets
      if (align < sizeof(void*))
        align = sizeof(void*);

      if (size < sizeof(void*))
        size = sizeof(void*);

      void* buf = memalign(align, size);

      if (buf == nullptr) {
        //printf("pmr memalign return nullptr, throw bad alloc\n");
        throw std::bad_alloc();
      }

      allocated_ += size;
      allocations_++;
      return buf;
    }

    void do_deallocate (void* ptr, size_t size, size_t) override {

      // Adapt to memalign
      if (size < sizeof(void*))
        size = sizeof(void*);

      free(ptr);
      allocated_ -= size;
      deallocations_++;
    }

    bool do_is_equal(const std::pmr::memory_resource& other) const noexcept override {
      return *this == other;
    }

    Resource_ptr resource_from_raw(Resource* raw) {
      Resource_ptr res_ptr(raw, [this](auto* res) {
          Expects(res->pool().get() == this);
          this->return_resource(res);
        });

      return res_ptr;
    }

    Resource_ptr new_resource() {
      Expects(resource_count() < max_resources_);

      auto res = resource_from_raw(new Pmr_resource(shared_ptr()));
      used_resources_++;

      Ensures(res != nullptr);
      Ensures(resource_count() <= max_resources_);
      return res;
    }

    Resource_ptr release_front() {
      auto released = std::move(free_resources_.front());
      free_resources_.pop_front();
      used_resources_++;
      return released;
    }

    void return_resource(Resource* raw) {
      Expects(used_resources_ > 0);
      auto res_ptr = resource_from_raw(raw);
      used_resources_--;
      free_resources_.emplace_back(std::move(res_ptr));
    }

    Resource_ptr get_resource() {

      if (! free_resources_.empty()) {

        auto& res = free_resources_.front();

        if (UNLIKELY(! res->empty() and resource_count() < max_resources_)) {
          return new_resource();
        }
        return release_front();
      }

      if (resource_count() >= max_resources_)
        return nullptr;

      return new_resource();
    }

    std::shared_ptr<Pmr_pool> shared_ptr() {
      return shared_from_this();
    }

    std::size_t resource_count() {
      return used_resources_ + free_resources_.size();
    }

    std::size_t free_resources() {
      return free_resources_.size();
    }

    std::size_t used_resources() {
      return used_resources_;
    }

    std::size_t total_capacity() {
      return cap_total_;
    }

    void set_resource_capacity(std::size_t sz) {
      cap_suballoc_ = sz;
    }

    void set_total_capacity(std::size_t sz) {
      cap_total_ = sz;
    }

    std::size_t resource_capacity() {
      if (cap_suballoc_ == 0)
      {
        return cap_total_ / (used_resources_ + os::mem::Pmr_pool::resource_division_offset);
      }
      return cap_suballoc_;
    }

    std::size_t bytes_booked() {
      return cap_suballoc_ * used_resources_;
    }

    std::size_t bytes_bookable() {
      auto booked = bytes_booked();
      if (booked > cap_total_)
        return 0;

      return cap_total_ - booked;
    }

    std::size_t allocated() {
      return allocated_;
    }

    std::size_t alloc_count() {
      return allocations_;
    }

    std::size_t dealloc_count() {
      return deallocations_;
    }

    bool full() {
      return allocated_ >= cap_total_;
    }

    bool empty() {
      return allocated_ == 0;
    }

    std::size_t allocatable() {
      auto allocd = allocated();
      if (allocd > cap_total_)
        return 0;
      return cap_total_ - allocd;
    }

    // NOTE: This can cause leaks or other chaos if you're not sure what you're doing
    void clear_free_resources() {
      for (auto& res : free_resources_) {
        *res = Resource(shared_ptr());
      }
    }

  private:
    std::size_t allocated_      = 0;
    std::size_t allocations_    = 0;
    std::size_t deallocations_  = 0;
    std::size_t cap_total_      = 0;
    std::size_t cap_suballoc_   = 0;
    std::size_t max_resources_  = 0;
    std::size_t used_resources_ = 0;
    std::deque<Resource_ptr> free_resources_{};
  };

} // os::mem::detail

namespace os::mem {

  //
  // Pmr_pool implementatino (PIMPL wrapper)
  //
  std::size_t Pmr_pool::total_capacity() { return impl->total_capacity(); }
  std::size_t Pmr_pool::resource_capacity() { return impl->resource_capacity(); }
  std::size_t Pmr_pool::allocatable() { return impl->allocatable(); }
  std::size_t Pmr_pool::allocated() { return impl->allocated(); }

  void Pmr_pool::set_resource_capacity(std::size_t s) { impl->set_resource_capacity(s); }
  void Pmr_pool::set_total_capacity(std::size_t s) { impl->set_total_capacity(s); };

  Pmr_pool::Pmr_pool(size_t sz, size_t sz_sub, size_t max_allocs)
    : impl{std::make_shared<detail::Pmr_pool>(sz, sz_sub, max_allocs)}{}
  Pmr_pool::Resource_ptr Pmr_pool::get_resource() { return impl->get_resource(); }
  std::size_t Pmr_pool::resource_count() { return impl->resource_count(); }
  std::size_t Pmr_pool::alloc_count() { return impl->alloc_count(); }
  std::size_t Pmr_pool::dealloc_count() { return impl->dealloc_count(); }
  void Pmr_pool::return_resource(Resource* res) { impl->return_resource(res); }
  bool Pmr_pool::full() { return impl->full(); }
  bool Pmr_pool::empty() { return impl->empty(); }

  //
  // Pmr_resource implementation
  //
  Pmr_resource::Pmr_resource(Pool_ptr p) : pool_{p} {}
  std::size_t Pmr_resource::capacity() {
    return std::min(pool_->resource_capacity(), pool_->allocatable());
  }
  std::size_t Pmr_resource::allocatable() {
    auto cap = capacity();
    if (used > cap)
      return 0;
    return cap - used;
  }

  std::size_t Pmr_resource::allocated() {
    return used;
  }

  Pmr_resource::Pool_ptr Pmr_resource::pool() {
    return pool_;
  }

  void* Pmr_resource::do_allocate(std::size_t size, std::size_t align) {
    auto cap = capacity();
    if (UNLIKELY(size + used > cap)) {
      throw std::bad_alloc();
    }

    try
    {
      void* buf = pool_->allocate(size, align);
      used += size;
      allocs++;
      return buf;
    }
    catch(const std::bad_alloc&)
    {
      //printf("Pool returned bad alloc, resource: used=%zu reported_cap=%zu allocatable=%zu\n",
      //  used, cap, allocatable());
      throw;
    }
  }

  void Pmr_resource::do_deallocate(void* ptr, std::size_t s, std::size_t a) {
    Expects(s != 0); // POSIX malloc will allow size 0, but return nullptr.
    bool trigger_non_full = UNLIKELY(full() and non_full != nullptr);
    bool trigger_avail_thresh = UNLIKELY(allocatable() < avail_thresh
                                         and allocatable() + s >= avail_thresh
                                         and avail != nullptr);

    pool_->deallocate(ptr,s,a);
    deallocs++;
    used -= s;

    if (UNLIKELY(trigger_avail_thresh)) {
      Ensures(allocatable() >= avail_thresh);
      Ensures(avail != nullptr);
      avail(*this);
    }

    if (UNLIKELY(trigger_non_full)) {
      Ensures(!full());
      Ensures(non_full != nullptr);
      non_full(*this);
    }
  }

  bool Pmr_resource::do_is_equal(const std::pmr::memory_resource& other) const noexcept {
    if (const auto* other_ptr = dynamic_cast<const Pmr_resource*>(&other)) {
      return this == other_ptr;
    }
    return false;
  }

  bool Pmr_resource::full() {
    return used >= capacity();
  }

  bool Pmr_resource::empty() {
    return used == 0;
  }
}

#endif
<|endoftext|>


<commit_before>/*
*
*      Filename: set.cpp
*
*        Author: Haibo Hao
*        Email : haohaibo@ncic.ac.cn
*   Description: ---
*        Create: 2017-07-04 23:36:16
* Last Modified: 2017-07-04 23:43:02
**/
#include <iostream>
#include <set>

int main(int argc, char* argv[])
{
    std::set<int> s1;
    std::set<int , std::greater<int> > s2;

    for(int i = 1; i < 6; ++i)
    {
        s1.insert(i);
        s2.insert(i);
    }

    std::set<int>::const_iterator it = s1.begin();
    for(; it != s1.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
    it = s2.begin();
    for(; it != s2.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
    return 0;
}

<commit_msg>added cpp-primer unordered_set in set.cpp<commit_after>/*
*
*      Filename: set.cpp
*
*        Author: Haibo Hao
*        Email : haohaibo@ncic.ac.cn
*   Description: ---
*        Create: 2017-07-04 23:36:16
* Last Modified: 2017-07-05 00:24:40
**/
#include <iostream>
#include <set>
#include <unordered_set>

int main(int argc, char* argv[])
{
    std::set<int> s1;
    std::set<int , std::greater<int> > s2;
    std::unordered_set<int> s3;
    for(int i = 1; i < 6; ++i)
    {
        s1.insert(i);
        s2.insert(i);
        s3.insert(i);
    }

    std::set<int>::const_iterator it = s1.begin();
    for(; it != s1.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
    it = s2.begin();
    for(; it != s2.end(); ++it)
    {
        std::cout << *it << std::endl;
    }

    std::unordered_set<int>::const_iterator uit = s3.begin();
    for(; uit != s3.end(); ++uit)
    {
        std::cout << *uit << std::endl;
    }
    return 0;
}

<|endoftext|>


<commit_before>/*
 * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by the
 * Free Software Foundation; either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/* ScriptData
SDName: Boss_Grilek
SD%Complete: 100
SDComment:
SDCategory: Zul'Gurub
EndScriptData */

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulgurub.h"

enum Spells
{
    SPELL_AVATAR                    = 24646, // Enrage Spell
    SPELL_GROUND_TREMOR             = 6524,
    SPELL_ENTANGLING_ROOTS          = 24648
};

enum Events
{
    EVENT_AVATAR                    = 1,
    EVENT_GROUND_TREMOR             = 2,
    EVENT_START_PURSUIT             = 3,
    EVENT_STOP_PURSUIT              = 4,
    EVENT_ENTANGLING_ROOTS          = 5
};

class boss_grilek : public CreatureScript // grilek
{
public:
    boss_grilek() : CreatureScript("boss_grilek") { }

    struct boss_grilekAI : public BossAI
    {
        boss_grilekAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS)
        {
        }

        void Reset() override
        {
            _pursuitTargetGUID.Clear();
            BossAI::Reset();
        }

        void EnterCombat(Unit* /*who*/) override
        {
            _EnterCombat();
            events.ScheduleEvent(EVENT_AVATAR, 20s, 30s);
            events.ScheduleEvent(EVENT_GROUND_TREMOR, 15s, 25s);
            events.ScheduleEvent(EVENT_ENTANGLING_ROOTS, 5s, 15s);
        }

        void UpdateAI(uint32 diff) override
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);

            if (me->HasUnitState(UNIT_STATE_CASTING))
                return;

            while (uint32 eventId = events.ExecuteEvent())
            {
                switch (eventId)
                {
                    case EVENT_AVATAR:
                        if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
                        {
                            _pursuitTargetGUID = target->GetGUID();
                        }
                        DoCast(me, SPELL_AVATAR);
                        me->SetReactState(REACT_PASSIVE);
                        DoResetThreat();
                        events.ScheduleEvent(EVENT_START_PURSUIT, 2s);
                        events.ScheduleEvent(EVENT_STOP_PURSUIT, 15s);
                        events.ScheduleEvent(EVENT_AVATAR, 45s, 50s);
                        break;
                    case EVENT_GROUND_TREMOR:
                        DoCastVictim(SPELL_GROUND_TREMOR, true);
                        events.ScheduleEvent(EVENT_GROUND_TREMOR, 12s, 16s);
                        break;
                    case EVENT_START_PURSUIT:
                        me->SetReactState(REACT_AGGRESSIVE);
                        if (Unit* pursuitTarget = ObjectAccessor::GetUnit(*me, _pursuitTargetGUID))
                        {
                            me->GetThreatMgr().addThreat(pursuitTarget, 1000000.f);
                        }
                        break;
                    case EVENT_STOP_PURSUIT:
                        if (Unit* pursuitTarget = ObjectAccessor::GetUnit(*me, _pursuitTargetGUID))
                        {
                            _pursuitTargetGUID.Clear();
                            me->GetThreatMgr().addThreat(pursuitTarget, -1000000.f);
                        }
                        break;
                    case EVENT_ENTANGLING_ROOTS:
                        DoCastVictim(SPELL_ENTANGLING_ROOTS);
                        events.ScheduleEvent(EVENT_ENTANGLING_ROOTS, 10s, 20s);
                        break;
                    default:
                        break;
                }
            }

            DoMeleeAttackIfReady();
        }

    private:
        ObjectGuid _pursuitTargetGUID;
    };

    CreatureAI* GetAI(Creature* creature) const override
    {
        return GetZulGurubAI<boss_grilekAI>(creature);
    }
};

void AddSC_boss_grilek()
{
    new boss_grilek();
}
<commit_msg>fix(Scripts/ZulGurub): Added Sweeping Strikes to Gri'lek encounter (#12328)<commit_after>/*
 * This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Affero General Public License as published by the
 * Free Software Foundation; either version 3 of the License, or (at your
 * option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/* ScriptData
SDName: Boss_Grilek
SD%Complete: 100
SDComment:
SDCategory: Zul'Gurub
EndScriptData */

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "zulgurub.h"

enum Spells
{
    SPELL_AVATAR                    = 24646, // Enrage Spell
    SPELL_GROUND_TREMOR             = 6524,
    SPELL_ENTANGLING_ROOTS          = 24648,
    SPELL_SWEEPING_STRIKES          = 18765
};

enum Events
{
    EVENT_AVATAR                    = 1,
    EVENT_GROUND_TREMOR             = 2,
    EVENT_START_PURSUIT             = 3,
    EVENT_STOP_PURSUIT              = 4,
    EVENT_ENTANGLING_ROOTS          = 5,
    EVENT_SWEEPING_STRIKES          = 6
};

class boss_grilek : public CreatureScript // grilek
{
public:
    boss_grilek() : CreatureScript("boss_grilek") { }

    struct boss_grilekAI : public BossAI
    {
        boss_grilekAI(Creature* creature) : BossAI(creature, DATA_EDGE_OF_MADNESS)
        {
        }

        void Reset() override
        {
            _pursuitTargetGUID.Clear();
            BossAI::Reset();
        }

        void EnterCombat(Unit* /*who*/) override
        {
            _EnterCombat();
            events.ScheduleEvent(EVENT_AVATAR, 20s, 30s);
            events.ScheduleEvent(EVENT_GROUND_TREMOR, 15s, 25s);
            events.ScheduleEvent(EVENT_ENTANGLING_ROOTS, 5s, 15s);
            events.ScheduleEvent(EVENT_SWEEPING_STRIKES, 30s);
        }

        void UpdateAI(uint32 diff) override
        {
            if (!UpdateVictim())
                return;

            events.Update(diff);

            if (me->HasUnitState(UNIT_STATE_CASTING))
                return;

            while (uint32 eventId = events.ExecuteEvent())
            {
                switch (eventId)
                {
                    case EVENT_AVATAR:
                        if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
                        {
                            _pursuitTargetGUID = target->GetGUID();
                        }
                        DoCast(me, SPELL_AVATAR);
                        me->SetReactState(REACT_PASSIVE);
                        DoResetThreat();
                        events.ScheduleEvent(EVENT_START_PURSUIT, 2s);
                        events.ScheduleEvent(EVENT_STOP_PURSUIT, 15s);
                        events.ScheduleEvent(EVENT_AVATAR, 45s, 50s);
                        break;
                    case EVENT_GROUND_TREMOR:
                        DoCastVictim(SPELL_GROUND_TREMOR, true);
                        events.ScheduleEvent(EVENT_GROUND_TREMOR, 12s, 16s);
                        break;
                    case EVENT_START_PURSUIT:
                        me->SetReactState(REACT_AGGRESSIVE);
                        if (Unit* pursuitTarget = ObjectAccessor::GetUnit(*me, _pursuitTargetGUID))
                        {
                            me->GetThreatMgr().addThreat(pursuitTarget, 1000000.f);
                        }
                        break;
                    case EVENT_STOP_PURSUIT:
                        if (Unit* pursuitTarget = ObjectAccessor::GetUnit(*me, _pursuitTargetGUID))
                        {
                            _pursuitTargetGUID.Clear();
                            me->GetThreatMgr().addThreat(pursuitTarget, -1000000.f);
                        }
                        break;
                    case EVENT_ENTANGLING_ROOTS:
                        DoCastVictim(SPELL_ENTANGLING_ROOTS);
                        events.ScheduleEvent(EVENT_ENTANGLING_ROOTS, 10s, 20s);
                        break;
                    case EVENT_SWEEPING_STRIKES:
                        DoCastSelf(SPELL_SWEEPING_STRIKES, true);
                        events.ScheduleEvent(EVENT_SWEEPING_STRIKES, 30s);
                        break;
                    default:
                        break;
                }
            }

            DoMeleeAttackIfReady();
        }

    private:
        ObjectGuid _pursuitTargetGUID;
    };

    CreatureAI* GetAI(Creature* creature) const override
    {
        return GetZulGurubAI<boss_grilekAI>(creature);
    }
};

void AddSC_boss_grilek()
{
    new boss_grilek();
}
<|endoftext|>


<commit_before>/*
 *  Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011-2014, Willow Garage, Inc.
 *  Copyright (c) 2014-2016, Open Source Robotics Foundation
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Open Source Robotics Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/** \author Karsten Knese <Karsten.Knese@googlemail.com> */

#include <gtest/gtest.h>

#include "fcl/math/constants.h"
#include "fcl/collision.h"
#include "fcl/shape/geometric_shapes.h"
#include "fcl/narrowphase/narrowphase.h"

#include <cmath>
using namespace fcl;

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_origin)
{

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform;
  Transform3f transform2;
  transform2 = Transform3f(Vec3f(20.1, 0,0));

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  EXPECT_TRUE(std::abs(dist - 10.1) < 0.001);
  EXPECT_TRUE(res);

}

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_transformXY)
{

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform;
  Transform3f transform2;
  transform2 = Transform3f(Vec3f(20, 20,0));

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  FCL_REAL expected = std::sqrt(FCL_REAL(800)) - 10;
  EXPECT_TRUE(std::abs(expected-dist) < 0.01);
  EXPECT_TRUE(res);

}

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_transformZ)
{

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform;
  Transform3f transform2;
  transform2 = Transform3f(Vec3f(0,0,20.1));

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  EXPECT_TRUE(std::abs(dist - 0.1) < 0.001);
  EXPECT_TRUE(res);

}

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_transformZ2)
{
  const FCL_REAL Pi = constants::pi;

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform;
  Transform3f transform2;
  transform2 = Transform3f(Vec3f(0,0,25.1));
  Matrix3f rot2;

  rot2.setEulerZYX(0,Pi/2,0);
  transform2.setRotation(rot2);

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "applied transformation of two caps: " << transform.linear() << " & " << transform2.linear() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  EXPECT_TRUE(std::abs(dist - 5.1) < 0.001);
  EXPECT_TRUE(res);

}

//==============================================================================
int main(int argc, char* argv[])
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Pass test_fcl_capsule_capsule<commit_after>/*
 *  Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011-2014, Willow Garage, Inc.
 *  Copyright (c) 2014-2016, Open Source Robotics Foundation
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Open Source Robotics Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/** \author Karsten Knese <Karsten.Knese@googlemail.com> */

#include <gtest/gtest.h>

#include "fcl/math/constants.h"
#include "fcl/collision.h"
#include "fcl/shape/geometric_shapes.h"
#include "fcl/narrowphase/narrowphase.h"

#include <cmath>
using namespace fcl;

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_origin)
{

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform = Transform3f::Identity();
  Transform3f transform2 = Transform3f::Identity();
  transform2.translation() = Vec3f(20.1, 0,0);

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  EXPECT_TRUE(std::abs(dist - 10.1) < 0.001);
  EXPECT_TRUE(res);

}

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_transformXY)
{

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform = Transform3f::Identity();
  Transform3f transform2 = Transform3f::Identity();
  transform2.translation() = Vec3f(20, 20,0);

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  FCL_REAL expected = std::sqrt(FCL_REAL(800)) - 10;
  EXPECT_TRUE(std::abs(expected-dist) < 0.01);
  EXPECT_TRUE(res);

}

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_transformZ)
{

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform = Transform3f::Identity();
  Transform3f transform2 = Transform3f::Identity();
  transform2.translation() = Vec3f(0,0,20.1);

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  EXPECT_TRUE(std::abs(dist - 0.1) < 0.001);
  EXPECT_TRUE(res);

}

GTEST_TEST(FCL_CAPSULE_CAPSULE, distance_capsulecapsule_transformZ2)
{
  const FCL_REAL Pi = constants::pi;

  GJKSolver_indep solver;
  Capsule s1(5, 10);
  Capsule s2(5, 10);

  Vec3f closest_p1, closest_p2;

  Transform3f transform = Transform3f::Identity();
  Transform3f transform2 = Transform3f::Identity();
  transform2.translation() = Vec3f(0,0,25.1);
  Matrix3f rot2(
        Eigen::AngleAxisd(0, Vec3f::UnitX())
        * Eigen::AngleAxisd(Pi/2, Vec3f::UnitY())
        * Eigen::AngleAxisd(0, Vec3f::UnitZ()));
  transform2.linear() = rot2;

  bool res;
  FCL_REAL dist;

  res = solver.shapeDistance<Capsule, Capsule>(s1, transform, s2, transform2, &dist, &closest_p1, &closest_p2);
  std::cerr << "applied transformation of two caps: " << transform.translation() << " & " << transform2.translation() << std::endl;
  std::cerr << "applied transformation of two caps: " << transform.linear() << " & " << transform2.linear() << std::endl;
  std::cerr << "computed points in caps to caps" << closest_p1 << " & " << closest_p2 << "with dist: " << dist << std::endl;

  EXPECT_TRUE(std::abs(dist - 5.1) < 0.001);
  EXPECT_TRUE(res);

}

//==============================================================================
int main(int argc, char* argv[])
{
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>// Time:  O(n^3)
// Space: O(1)

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &nums, int target) {
        int len = nums.size();
        int left, right, sum;
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        for (int i = 0; i < len - 3; ++i) {
            if (i && nums[i] == nums[i - 1]) {
                continue;
            }
            for (int j = i + 1; j < len - 2; ++j) {
                if (j != i + 1 && nums[j] == nums[j - 1]) {
                    continue;
                }
                sum = target - nums[i] - nums[j];
                left = j + 1, right = len - 1;
                while (left < right) {
                    if (nums[left] + nums[right] == sum) {
                        res.emplace_back(move(vector<int>{nums[i], nums[j], nums[left], nums[right]}));
                        ++left, --right;
                        while (left < right && nums[left] == nums[left - 1]) {
                            ++left;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            --right;
                        }
                    } else {
                        if (nums[left] + nums[right] > sum) {
                            --right;
                        } else {
                            ++left;
                        }
                    }
                }
            }
        }
        return res;
    }
};

// Time:  O(n^2 * p), p is max number of the same two sum pairs.
// Space: O(n^2 * p)
class Solution2 {
public:
    /**
     * @param numbers: Give an array numbersbers of n integer
     * @param target: you need to find four elements that's sum of target
     * @return: Find all unique quadruplets in the array which gives the sum of
     *          zero.
     */
    vector<vector<int>> fourSum(vector<int> nums, int target) {
        sort(nums.begin(), nums.end()); // Make sure quadruplets are in non-descending orders.
        unordered_map<int, vector<vector<size_t>>> two_sum; // two_sum saves "sum to (i, j) pairs, which i < j."
        for (size_t i = 0; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                bool have_duplicate = false;
                for (const auto& vec : two_sum[nums[i] + nums[j]]) {
                    if (nums[vec.front()] == nums[i]) {  // Duplicated.
                        have_duplicate = true;
                        break;
                    }
                }
                if (!have_duplicate) {  // Not duplicated
                    vector<size_t> new_vec = {i, j};
                    two_sum[nums[i] + nums[j]].emplace_back(move(new_vec));
                }
            }
        }

        unordered_set<string> answers; // Use hash to filter duplicated.
        vector<vector<int>> res;
        for (size_t i = 2; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                auto it = two_sum.find(target - nums[i] - nums[j]);
                if (it != two_sum.end()) {
                    for (const auto& vec : it->second) {
                        if (i > vec.back()) {  // {vec.front() < vec.back() < i < j}
                            vector<int> candidate = {nums[vec.front()], nums[vec.back()], nums[i], nums[j]};
                            if (answers.emplace(join_vector(candidate)).second) {  // Not duplicated.
                                res.emplace_back(move(candidate)); // Add to answers.
                            }
                        }
                    }
                }
            }
        }
        return res;
    }

    // Hash vector to string.
    string join_vector(const vector<int>& nums) {
        string ret;
        for (int n : nums) {
            ret += to_string(n);
            ret += ' ';
        }
        return ret;
    }
};
<commit_msg>Update 4-sum.cpp<commit_after>// Time:  O(n^3)
// Space: O(1)

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &nums, int target) {
        int len = nums.size();
        int left, right, sum;
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        for (int i = 0; i < len - 3; ++i) {
            if (i && nums[i] == nums[i - 1]) {
                continue;
            }
            for (int j = i + 1; j < len - 2; ++j) {
                if (j != i + 1 && nums[j] == nums[j - 1]) {
                    continue;
                }
                sum = target - nums[i] - nums[j];
                left = j + 1, right = len - 1;
                while (left < right) {
                    if (nums[left] + nums[right] == sum) {
                        res.emplace_back(move(vector<int>{nums[i], nums[j], nums[left], nums[right]}));
                        ++left, --right;
                        while (left < right && nums[left] == nums[left - 1]) {
                            ++left;
                        }
                        while (left < right && nums[right] == nums[right + 1]) {
                            --right;
                        }
                    } else {
                        if (nums[left] + nums[right] > sum) {
                            --right;
                        } else {
                            ++left;
                        }
                    }
                }
            }
        }
        return res;
    }
};

// Time:  O(n^2 * p), p is max number of the same two sum pairs.
// Space: O(n^2 * p)
class Solution2 {
public:
    /**
     * @param numbers: Give an array numbersbers of n integer
     * @param target: you need to find four elements that's sum of target
     * @return: Find all unique quadruplets in the array which gives the sum of
     *          zero.
     */
    vector<vector<int>> fourSum(vector<int> nums, int target) {
        sort(nums.begin(), nums.end()); // Make sure quadruplets are in non-descending orders.
        unordered_map<int, vector<vector<size_t>>> two_sum; // two_sum saves "sum to (i, j) pairs, which i < j."
        for (size_t i = 0; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                bool have_duplicate = false;
                for (const auto& vec : two_sum[nums[i] + nums[j]]) {
                    if (nums[vec.front()] == nums[i]) {  // Duplicated.
                        have_duplicate = true;
                        break;
                    }
                }
                if (!have_duplicate) {  // Not duplicated
                    vector<size_t> new_vec = {i, j};
                    two_sum[nums[i] + nums[j]].emplace_back(move(new_vec));
                }
            }
        }

        unordered_set<string> answers; // Use hash to filter duplicated.
        vector<vector<int>> res;
        for (size_t i = 2; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                auto it = two_sum.find(target - nums[i] - nums[j]);
                if (it == two_sum.end()) {
                    continue;
                }
                for (const auto& vec : it->second) {
                    if (vec.back() >= i) {
                        continue;
                    }
                    // {vec.front() < vec.back() < i < j}
                    vector<int> candidate = {nums[vec.front()], nums[vec.back()], nums[i], nums[j]};
                    if (answers.emplace(join_vector(candidate)).second) {  // Not duplicated.
                        res.emplace_back(move(candidate)); // Add to answers.
                    }
                }
            }
        }
        return res;
    }

    // Hash vector to string.
    string join_vector(const vector<int>& nums) {
        string ret;
        for (int n : nums) {
            ret += to_string(n);
            ret += ' ';
        }
        return ret;
    }
};
<|endoftext|>