text:
//
//  Copyright (c) 2015, Novartis Institutes for BioMedical Research Inc.
//  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 Novartis Institutues for BioMedical Research Inc.
//       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.
//
#include <boost/python.hpp>
#include <RDBoost/Wrap.h>
#include <GraphMol/ChemReactions/Enumerate/RandomSample.h>
#include <GraphMol/ChemReactions/Enumerate/RandomSampleAllBBs.h>
#include <GraphMol/ChemReactions/Enumerate/EvenSamplePairs.h>
#include <GraphMol/ChemReactions/Enumerate/Enumerate.h>
#include <boost/python/stl_iterator.hpp>
#include <cstdint>

namespace python = boost::python;

namespace RDKit {

template<class T>
std::vector<RDKit::MOL_SPTR_VECT> ConvertToVect(T bbs) {
  std::vector<RDKit::MOL_SPTR_VECT> vect;
  size_t num_bbs = python::extract<unsigned int>(bbs.attr("__len__")());
  vect.resize(num_bbs);
  for(size_t i=0; i<num_bbs; ++i) {
    unsigned int len1 = python::extract<unsigned int>(bbs[i].attr("__len__")());
    RDKit::MOL_SPTR_VECT &reacts = vect[i];
    reacts.reserve(len1);
    for(unsigned int j=0;j<len1;++j){
      RDKit::ROMOL_SPTR mol = python::extract<RDKit::ROMOL_SPTR>(bbs[i][j]);
      if (mol) {
        reacts.push_back(mol);
      } else {
        throw_value_error("reaction called with non molecule reactant");
      }
    }
  }
  return vect;
}

bool EnumerateLibraryBase__nonzero__(RDKit::EnumerateLibraryBase *base) {
  return static_cast<bool>(*base);
}
bool EnumerationStrategyBase__nonzero__(RDKit::EnumerationStrategyBase *base) {
  return static_cast<bool>(*base);
}

inline python::object pass_through(python::object const& o) { return o; }

PyObject *EnumerateLibraryBase__next__(RDKit::EnumerateLibraryBase *base) {
  if (!static_cast<bool>(*base)) {
    PyErr_SetString(PyExc_StopIteration, "Enumerations exhausted");
    boost::python::throw_error_already_set();
  }
  std::vector<RDKit::MOL_SPTR_VECT> mols;
  {
    NOGIL gil;
    mols = base->next();
  }
  PyObject *res=PyTuple_New(mols.size());

  for(unsigned int i=0;i<mols.size();++i){
    PyObject *lTpl =PyTuple_New(mols[i].size());
    for(unsigned int j=0;j<mols[i].size();++j){
      PyTuple_SetItem(lTpl,j,
                      python::converter::shared_ptr_to_python(mols[i][j]));
    }
    PyTuple_SetItem(res,i,lTpl);
  }
  return res;
}

python::object EnumerateLibraryBase_Serialize(const EnumerateLibraryBase &en) {
  std::string res = en.Serialize();
  python::object retval = python::object(
      python::handle<>(PyBytes_FromStringAndSize(res.c_str(), res.length())));
  return retval;
}

class EnumerateLibraryWrap : public RDKit::EnumerateLibrary {
public:
  EnumerateLibraryWrap() : RDKit::EnumerateLibrary() {}
  EnumerateLibraryWrap(const RDKit::ChemicalReaction &rxn, python::list ob,
                       const EnumerationParams & params = EnumerationParams()
                       ) :
      RDKit::EnumerateLibrary(rxn, ConvertToVect(ob), params) {
  }

  EnumerateLibraryWrap(const RDKit::ChemicalReaction &rxn, python::tuple ob,
                       const EnumerationParams & params = EnumerationParams()
                       ) :
      RDKit::EnumerateLibrary(rxn, ConvertToVect(ob), params) {
  }

  EnumerateLibraryWrap(const RDKit::ChemicalReaction &rxn, python::list ob,
                       const EnumerationStrategyBase &enumerator,
                       const EnumerationParams & params = EnumerationParams()
                       ) :
      RDKit::EnumerateLibrary(rxn, ConvertToVect(ob), enumerator, params) {
  }

  EnumerateLibraryWrap(const RDKit::ChemicalReaction &rxn, python::tuple ob,
                       const EnumerationStrategyBase &enumerator,
                       const EnumerationParams & params = EnumerationParams()) :
      RDKit::EnumerateLibrary(rxn, ConvertToVect(ob), enumerator, params) {
  }

};

namespace {
  template< typename T >
  inline
  std::vector< T > to_std_vector( const python::object& iterable )
  {
    return std::vector< T >( python::stl_input_iterator< T >( iterable ),
                             python::stl_input_iterator< T >( ) );
  }
}

void ToBBS(EnumerationStrategyBase &rgroup, ChemicalReaction &rxn, python::list ob) {
  rgroup.initialize(rxn, ConvertToVect(ob));
}

typedef std::vector<boost::uint64_t> VectSizeT;
typedef std::vector<std::vector<std::string> > VectStringVect;
typedef std::vector<MOL_SPTR_VECT > VectMolVect;

struct enumeration_wrapper {
  static void wrap() {
    std::string docString;
    python::class_<VectStringVect>("VectorOfStringVectors")
      .def(python::vector_indexing_suite<VectStringVect, false>() );

    python::class_<VectSizeT>("VectSizeT")
      .def(python::vector_indexing_suite<VectSizeT, false>() );

    python::class_<VectMolVect>("VectMolVect")
      .def(python::vector_indexing_suite<VectMolVect, false>() );

    python::class_<RDKit::EnumerateLibraryBase, RDKit::EnumerateLibraryBase *,
                   RDKit::EnumerateLibraryBase &, boost::noncopyable>(
        "EnumerateLibraryBase", python::no_init)
        .def("__nonzero__", &EnumerateLibraryBase__nonzero__)
        .def("__bool__", &EnumerateLibraryBase__nonzero__)
        .def("__iter__", &pass_through)
        .def("next", &EnumerateLibraryBase__next__,
             "Return the next molecule from the enumeration.")
        .def("__next__", &EnumerateLibraryBase__next__,
             "Return the next molecule from the enumeration.")
        .def("nextSmiles", &RDKit::EnumerateLibraryBase::nextSmiles,
             "Return the next smiles string from the enumeration.")
        .def("Serialize", &EnumerateLibraryBase_Serialize,
             "Serialize the library to a binary string.\n"
             "Note that the position in the library is serialized as well.  Care should\n"
             "be taken when serializing.  See GetState/SetState for position manipulation.")
        .def("InitFromString", &RDKit::EnumerateLibraryBase::initFromString,
             python::arg("data"),
             "Inititialize the library from a binary string")
        .def("GetPosition", &RDKit::EnumerateLibraryBase::getPosition,
             "Returns the current enumeration position into the reagent vectors",
             python::return_internal_reference<
             1, python::with_custodian_and_ward_postcall<0, 1> >())
        .def("GetState", &RDKit::EnumerateLibraryBase::getState,
             "Returns the current enumeration state (position) of the library.\n"
             "This position can be used to restart the library from a known position")
        .def("SetState", &RDKit::EnumerateLibraryBase::setState,
             python::arg("state"),
             "Sets the enumeration state (position) of the library.")
        .def("ResetState", &RDKit::EnumerateLibraryBase::resetState,
             "Returns the current enumeration state (position) of the library to the start.")
        .def("GetReaction", &RDKit::EnumerateLibraryBase::getReaction,
             "Returns the chemical reaction for this library",
             python::return_internal_reference<
             1, python::with_custodian_and_ward_postcall<0, 1> >())
        .def("GetEnumerator", &RDKit::EnumerateLibraryBase::getEnumerator,
             "Returns the enumation strategy for the current library",
             python::return_internal_reference<
             1, python::with_custodian_and_ward_postcall<0, 1> >());

    docString = \
"EnumerationParams\n\
Controls some aspects of how the enumeration is performed.\n\
Options:\n\
  reagentMaxMatchCount [ default Infinite ]\n\
    This specifies how many times the reactant template can match a reagent.\n\
\n\
  sanePartialProducts [default false]\n\
    If true, forces all products of the reagent plus the product templates\n\
     pass chemical sanitization.  Note that if the product template itself\n\
     does not pass sanitization, then none of the products will.\n\
";

    python::class_<RDKit::EnumerationParams,
                   RDKit::EnumerationParams*,
                   RDKit::EnumerationParams&>("EnumerationParams",
                                              docString.c_str(),
                                              python::init<>())
        .def_readwrite("reagentMaxMatchCount",
                    &RDKit::EnumerationParams::reagentMaxMatchCount)
        .def_readwrite("sanePartialProducts",
                    &RDKit::EnumerationParams::sanePartialProducts);

    docString = \
"EnumerateLibrary\n\
This class allows easy enumeration of reactions.  Simply provide a reaction\n\
and a set of reagents and you are off the races.\n\
\n\
Note that this functionality should be considered beta and that the API may\n\
change in a future release.\n\
\n\
EnumerateLibrary follows the python enumerator protocol, for example:\n\
\n\
library = EnumerateLibrary(rxn, bbs)\n\
for products in library:\n\
   ... do something with the product\n\
\n\
It is useful to sanitize reactions before hand:\n\
\n\
SanitizeRxn(rxn)\n\
library = EnumerateLibrary(rxn, bbs)\n\
\n\
If ChemDraw style reaction semantics are prefereed, you can apply\n\
the ChemDraw parameters:\n\
\n\
SanitizeRxn(rxn, params=GetChemDrawRxnAdjustParams())\n\
\n\
For one, this enforces only matching RGroups and assumes all atoms\n\
have fully satisfied valences.\n\
\n\
Each product has the same output as applying a set of reagents to\n\
the libraries reaction.\n\
\n\
This can be a bit confusing as each product can have multiple molecules\n\
generated.  The returned data structure is as follows:\n\
\n\
   [ [products1], [products2],... ]\n\
Where products1 are the molecule products for the reactions first product\n\
template and products2 are the molecule products for the second product\n\
template.  Since each reactant can match more than once, there may be\n\
multiple product molecules for each template.\n\
\n\
for products in library:\n\
    for results_for_product_template in products:\n\
        for mol in results_for_product_template:\n\
            Chem.MolToSmiles(mol) # finally have a molecule!\n\
\n\
For sufficiently large libraries, using this iteration strategy is not\n\
recommended as the library may contain more products than atoms in the\n\
universe.  To help with this, you can supply an enumeration strategy.\n\
The default strategy is a CartesianProductStrategy which enumerates\n\
everything.  RandomSampleStrategy randomly samples the products but\n\
this strategy never terminates, however, python supplies itertools:\n\
\n\
import itertools\n\
library = EnumerateLibrary(rxn, bbs, rdChemReactions.RandomSampleStrategy())\n\
for result in itertools.islice(library, 1000):\n\
    # do something with the first 1000 samples\n\
\n\
for result in itertools.islice(library, 1000):\n\
    # do something with the next 1000 samples\n\
\n\
Libraries are also serializable, including their current state:\n\
\n\
s = library.Serialize()\n\
library2 = EnumerateLibrary()\n\
library2.InitFromString(s)\n\
for result in itertools.islice(libary2, 1000):\n\
    # do something with the next 1000 samples\n\
";
    python::class_<EnumerateLibraryWrap,
                   EnumerateLibraryWrap*,EnumerateLibraryWrap&,
                   python::bases<RDKit::EnumerateLibraryBase> >(
                       "EnumerateLibrary", docString.c_str(),
                       python::init<>())
      .def(python::init<
           const RDKit::ChemicalReaction &,
           python::list,
           python::optional<const RDKit::EnumerationParams&>
           >(python::args("rxn", "reagents", "params")))
      .def(python::init<
           const RDKit::ChemicalReaction &,
           python::tuple,
           python::optional<const RDKit::EnumerationParams&>
           >(python::args("rxn", "reagents", "params")))

      .def(python::init<const RDKit::ChemicalReaction &,
           python::list,
           const RDKit::EnumerationStrategyBase &,
           python::optional<const RDKit::EnumerationParams&>
           >(python::args(
               "rxn", "reagents", "enumerator", "params")))
      .def(python::init<const RDKit::ChemicalReaction &,
           python::tuple,
           const RDKit::EnumerationStrategyBase &,
           python::optional<const RDKit::EnumerationParams&>
           >(python::args(
               "rxn", "reagents", "enumerator", "params")))

      .def("GetReagents", &RDKit::EnumerateLibrary::getReagents,
           "Return the reagents used in this library.",
           python::return_internal_reference<
           1, python::with_custodian_and_ward_postcall<0, 1> >())
      ;

    //iterator_wrappers<EnumerateLibrary>().wrap("EnumerateLibraryIterator");

    python::class_<RDKit::EnumerationStrategyBase,
                   RDKit::EnumerationStrategyBase *,
                   RDKit::EnumerationStrategyBase &, boost::noncopyable>(
        "EnumerationStrategyBase", python::no_init)
        .def("__nonzero__", &EnumerationStrategyBase__nonzero__)
        .def("__bool__", &EnumerationStrategyBase__nonzero__)
        .def("Type", &EnumerationStrategyBase::type,
             "Returns the enumeration strategy type as a string.")
        .def("Skip", &EnumerationStrategyBase::skip,
             python::args("skipCount"),
             "Skip the next Nth results. note: this may be an expensive "
             "operation\n"
             "depending on the enumeration strategy used. It is recommended to "
             "use\n"
             "the enumerator state to advance to a known position")
        .def("__copy__", python::pure_virtual(&EnumerationStrategyBase::copy),
             python::return_value_policy<python::manage_new_object>())
        .def("GetNumPermutations", &EnumerationStrategyBase::getNumPermutations,
             "Returns the total number of results for this enumeration strategy.\n"
             "Note that some strategies are effectively infinite.")
        .def("GetPosition", &EnumerationStrategyBase::getPosition,
             "Return the current indices into the arrays of reagents",
             python::return_internal_reference<
                 1, python::with_custodian_and_ward_postcall<0, 1> >())
        .def("next", python::pure_virtual(&EnumerationStrategyBase::next),
             "Return the next indices into the arrays of reagents",
             python::return_internal_reference<
                 1, python::with_custodian_and_ward_postcall<0, 1> >())
        .def("__next__", python::pure_virtual(&EnumerationStrategyBase::next),
             "Return the next indices into the arrays of reagents",
             python::return_internal_reference<
                 1, python::with_custodian_and_ward_postcall<0, 1> >())
        .def("Initialize", ToBBS);

    docString = "CartesianProductStrategy produces a standard walk through all possible\n"
        "reagent combinations:\n"
        "\n"
        "(0,0,0), (1,0,0), (2,0,0) ...\n";

    python::class_<RDKit::CartesianProductStrategy,
                   RDKit::CartesianProductStrategy*,
                   RDKit::CartesianProductStrategy&,
                   python::bases<EnumerationStrategyBase> >("CartesianProductStrategy",
                                                            docString.c_str(),
                                                            python::init<>())
        .def("__copy__", &RDKit::CartesianProductStrategy::copy,
             python::return_value_policy<python::manage_new_object>())
      ;

    docString = "RandomSampleStrategy simply randomly samples from the reagent sets.\n"
        "Note that this strategy never halts and can produce duplicates.";
    python::class_<RDKit::RandomSampleStrategy,
                   RDKit::RandomSampleStrategy*,
                   RDKit::RandomSampleStrategy&,
                   python::bases<EnumerationStrategyBase> >("RandomSampleStrategy",
                                                            docString.c_str(),
                                                            python::init<>())
        .def("__copy__", &RDKit::RandomSampleStrategy::copy,
             python::return_value_policy<python::manage_new_object>())
      ;

    docString = "RandomSampleAllBBsStrategy randomly samples from the reagent sets\n"
        "with the constraint that all building blocks are samples as early as possible.\n"
        "Note that this strategy never halts and can produce duplicates.";
    python::class_<RDKit::RandomSampleAllBBsStrategy,
                   RDKit::RandomSampleAllBBsStrategy*,
                   RDKit::RandomSampleAllBBsStrategy&,
                   python::bases<EnumerationStrategyBase> >("RandomSampleAllBBsStrategy",
                                                            docString.c_str(),
                                                            python::init<>())
        .def("__copy__", &RDKit::RandomSampleAllBBsStrategy::copy,
             python::return_value_policy<python::manage_new_object>())
      ;

    docString = "Randomly sample Pairs evenly from a collection of building blocks\n"
        "This is a good strategy for choosing a relatively small selection\n"
        "of building blocks from a larger set.  As the amount of work needed\n"
        "to retrieve the next evenly sample building block grows with the\n"
        "number of samples, this method performs progressively worse as the\n"
        "number of samples gets larger.\n"
        "See EnumerationStrategyBase for more details.\n";

    python::class_<RDKit::EvenSamplePairsStrategy,
                   RDKit::EvenSamplePairsStrategy*,
                   RDKit::EvenSamplePairsStrategy&,
                   python::bases<EnumerationStrategyBase> >("EvenSamplePairsStrategy",
                                                            docString.c_str(),
                                                            python::init<>())
        .def("__copy__", &RDKit::EvenSamplePairsStrategy::copy,
             python::return_value_policy<python::manage_new_object>())
        .def("Stats", &RDKit::EvenSamplePairsStrategy::stats,
             "Return the statistics log of the pairs used in the current enumeration.")
      ;

    python::def("EnumerateLibraryCanSerialize", EnumerateLibraryCanSerialize,
                "Returns True if the EnumerateLibrary is serializable "
                "(requires boost serialization");

  }
};

}// end of namespace

void wrap_enumeration() {
  RDKit::enumeration_wrapper::wrap();
}

max_stars_repo_name: chcltchunk/rdkit

max_issues_repo_name: chcltchunk/rdkit

max_forks_repo_name: chcltchunk/rdkit


text:
#include "dynamic_renderer.hpp"

#include <boost/container/small_vector.hpp>
#include <libefl/basic_vector.hpp>
#include <libefl/initialise_library.hpp>
#include <libefl/vector_functions.hpp>
#include <vector>

#include "bear/api.hpp"
#include "config_impl.hpp"
#include "constructor_thread.hpp"
#include "utils.hpp"

namespace bear {

template <typename T, int N>
class MetadataBuffer {
 public:
  MetadataBuffer(size_t max_size) { data.reserve(max_size); }

  void push(size_t channel, const T &channel_data)
  {
    if (channel >= data.size()) data.resize(channel + 1);

    if (data[channel].size() == N) data[channel].erase(data[channel].begin());

    data[channel].push_back(channel_data);
  }

  std::vector<boost::container::small_vector<T, N>> data;
};

/// controller for DynamicRendererImpl, implementing fade up, fade down, waiting and preroll logic
class StateMachine {
 public:
  StateMachine(size_t period_size)
      : num_preroll_frames(static_cast<int>(std::ceil((double)num_preroll_samples / period_size)))
  {
  }

  // state transitions

  // call when reconfiguration is started
  void start_config()
  {
    if (state == State::RUNNING || state == State::FADE_DOWN)
      set_state(State::FADE_DOWN);
    else
      set_state(State::WAIT);
  }

  // call when reconfiguration is finished (after start_config) and we have a
  // renderer again
  void config_finished()
  {
    bear_assert(state != State::START, "unexpected state");
    bear_assert(state != State::RUNNING, "unexpected state");

    if (state == State::WAIT) {
      set_state(State::PREROLL);
      preroll_frames_left = num_preroll_frames;
    }
  }

  void set_config_blocking() { set_state(State::RUNNING); }

  // call at the end of each process call
  void process_done()
  {
    if (state == State::FADE_DOWN)
      set_state(State::WAIT);
    else if (state == State::PREROLL) {
      preroll_frames_left--;
      if (preroll_frames_left == 0) set_state(State::FADE_UP);
    } else if (state == State::FADE_UP)
      set_state(State::RUNNING);
  }

  // externally-visible state

  // should the output be faded down?
  bool should_fade_down() { return state == State::FADE_DOWN; }

  // should the output be faded up?
  bool should_fade_up() { return state == State::FADE_UP; }

  // should the output be cleared?
  bool should_clear_output()
  {
    // preroll, or when !should_render
    return state == State::START || state == State::WAIT || state == State::PREROLL;
  }

  // should the real renderer process function be called?
  bool should_render()
  {
    return state == State::RUNNING || state == State::FADE_DOWN || state == State::PREROLL ||
           state == State::FADE_UP;
  }

  // should the renderer be swapped with the configuration result?
  bool should_swap() { return state == State::START || state == State::WAIT; }

  bool is_running() { return state == State::RUNNING; }

 private:
  // generally, refers to what should be done in the next frame
  enum class State { START, FADE_DOWN, WAIT, PREROLL, FADE_UP, RUNNING };

  State state = State::START;
  int preroll_frames_left = 0;

  void set_state(State s)
  {
    state = s;
    // const char *names[] = {"START", "FADE_DOWN", "WAIT", "PREROLL", "FADE_UP", "RUNNING"};
    // std::cout << "state: " << names[(int)state] << "\n";
  }

  static constexpr int num_preroll_samples = 2976   // brir length
                                             + 128  // decorrelation filters
                                             + 38   // max delays
                                             + 3;   // delay implementation
  const int num_preroll_frames;
};

class TypeAdapter {
};

struct ObjectsTypeAdapter {
  static bool input_fits(const ConfigImpl &config, size_t channel, const ObjectsInput &metadata)
  {
    return channel < config.num_objects_channels;
  }

  static bool add_block(Renderer &renderer, size_t channel, ObjectsInput metadata)
  {
    return renderer.add_objects_block(channel, std::move(metadata));
  }

  using InputType = ObjectsInput;
};

struct DirectSpeakersTypeAdapter {
  static bool input_fits(const ConfigImpl &config, size_t channel, const DirectSpeakersInput &metadata)
  {
    return channel < config.num_direct_speakers_channels;
  }

  static bool add_block(Renderer &renderer, size_t channel, DirectSpeakersInput metadata)
  {
    return renderer.add_direct_speakers_block(channel, std::move(metadata));
  }

  using InputType = DirectSpeakersInput;
};

struct HOATypeAdapter {
  static bool input_fits(const ConfigImpl &config, size_t stream, const HOAInput &metadata)
  {
    for (size_t channel : metadata.channels)
      if (channel >= config.num_hoa_channels) return false;
    return true;
  }

  static bool add_block(Renderer &renderer, size_t channel, HOAInput metadata)
  {
    return renderer.add_hoa_block(channel, std::move(metadata));
  }

  using InputType = HOAInput;
};

class DynamicRendererImpl {
 public:
  DynamicRendererImpl(size_t _block_size, size_t max_size)
      : block_size(_block_size),
        objects_buffer(max_size),
        direct_speakers_buffer(max_size),
        hoa_buffer(max_size),
        state(block_size),
        ramp_up(block_size, 0),
        ramp_down(block_size, 0),
        zeros(block_size, 0)
  {
    visr::efl::vectorRamp<Sample>(ramp_up.data(), block_size, 0.0, 1.0, true, false);
    visr::efl::vectorRamp<Sample>(ramp_down.data(), block_size, 1.0, 0.0, true, false);
    visr::efl::vectorZero(zeros.data(), block_size);

    next_render_config.num_objects_channels = 0;
    next_render_config.num_direct_speakers_channels = 0;
    next_render_config.num_hoa_channels = 0;
  }

  void set_config_common(const Config &config)
  {
    sample_rate = config.get_sample_rate();
    bear_assert(config.get_period_size() == block_size, "config has incorrect period size");

    next_render_config = config.get_impl();
  }

  void set_config(const Config &config)
  {
    set_config_common(config);

    if (!constructor_thread.start(config)) next_config = config.get_impl();

    state.start_config();
  }

  void set_config_blocking(const Config &config)
  {
    renderer = Renderer(config);

    set_config_common(config);
    current_render_config = next_render_config;
    initialise_renderer();
    state.set_config_blocking();
  }

  std::exception_ptr get_error() { return constructor_thread.get_construction_error(); }
  bool is_running() { return state.is_running(); }

  bool add_objects_block(size_t channel, ObjectsInput metadata)
  {
    return add_block<ObjectsTypeAdapter>(objects_buffer, channel, metadata);
  }

  bool add_direct_speakers_block(size_t channel, DirectSpeakersInput metadata)
  {
    return add_block<DirectSpeakersTypeAdapter>(direct_speakers_buffer, channel, metadata);
  }

  bool add_hoa_block(size_t channel, HOAInput metadata)
  {
    return add_block<HOATypeAdapter>(hoa_buffer, channel, metadata);
  }

  void process(size_t num_objects_channels,
               const Sample *const *objects_input,
               size_t num_direct_speakers_channels,
               const Sample *const *direct_speakers_input,
               size_t num_hoa_channels,
               const Sample *const *hoa_input,
               Sample *const *output)
  {
    if (next_config) {
      constructor_thread.get_result();
      if (constructor_thread.start(*next_config)) next_config = boost::none;
    }

    maybe_swap();

    if (state.should_render()) {
      bear_assert(renderer.has_value(), "expected renderer to be set");

      fill_temp_pointers(
          current_render_config.num_objects_channels, temp_objects, num_objects_channels, objects_input);
      fill_temp_pointers(current_render_config.num_direct_speakers_channels,
                         temp_direct_speakers,
                         num_direct_speakers_channels,
                         direct_speakers_input);
      fill_temp_pointers(current_render_config.num_hoa_channels, temp_hoa, num_hoa_channels, hoa_input);
      renderer->process(temp_objects.data(), temp_direct_speakers.data(), temp_hoa.data(), output);
    }

    if (state.should_fade_down())
      for (size_t i = 0; i < 2; i++)
        visr::efl::vectorMultiplyInplace(ramp_down.data(), output[i], block_size);
    if (state.should_fade_up())
      for (size_t i = 0; i < 2; i++) visr::efl::vectorMultiplyInplace(ramp_up.data(), output[i], block_size);
    if (state.should_clear_output())
      for (size_t i = 0; i < 2; i++) visr::efl::vectorZero(output[i], block_size);

    state.process_done();
    num_blocks_processed++;
  }

  void set_block_start_time(const Time &time)
  {
    // get_raw_time() - time_offset == time
    time_offset = get_raw_block_start_time() - time;
  }

  Time get_block_start_time() const { return get_raw_block_start_time() - time_offset; }

  void set_listener(const Listener &l, const boost::optional<Time> &interpolation_time)
  {
    if (renderer) renderer->set_listener(l, interpolation_time);

    last_listener = l;
    last_listener_interpolation_time = interpolation_time;
  }

 private:
  template <typename Adapter, typename Buffer>
  bool add_block(Buffer &buffer, size_t channel, typename Adapter::InputType metadata)
  {
    if (!Adapter::input_fits(next_render_config, channel, metadata))
      throw std::invalid_argument("not enough channels configured to add block");

    if (metadata.rtime) *metadata.rtime += time_offset;

    if (!metadata.rtime || *metadata.rtime < get_raw_next_block_start_time()) {
      // always buffer so that when the renderer reconfiguration is finished we
      // can feed it metadata for all channels
      buffer.push(channel, metadata);
      // only push metadata to the renderer when we will actually be calling
      // the process function, otherwise our notion of time and the renderer's
      // may get out of sync (plus it's wasted effort)
      if (state.should_render() && Adapter::input_fits(current_render_config, channel, metadata)) {
        bear_assert(renderer.has_value(), "expected renderer to be set");
        bear_assert(Adapter::add_block(*renderer, channel, metadata), "could not push");
      }
      return true;
    } else
      return false;
  }

  void maybe_swap()
  {
    if (state.should_swap()) {
      if (constructor_thread.try_swap_result(renderer)) {
        current_render_config = next_render_config;

        initialise_renderer();

        state.config_finished();
      }
    }
  }

  /// initialise the newly-created renderer: set up time, listener, and push
  /// metadata from queues
  void initialise_renderer()
  {
    renderer->set_block_start_time({block_size * num_blocks_processed, sample_rate});
    renderer->set_listener(last_listener, last_listener_interpolation_time);

    push_data_from_buffer<ObjectsTypeAdapter>(objects_buffer);
    push_data_from_buffer<DirectSpeakersTypeAdapter>(direct_speakers_buffer);
    push_data_from_buffer<HOATypeAdapter>(hoa_buffer);
  }

  template <typename Adapter, typename Buffer>
  void push_data_from_buffer(const Buffer &buffer)
  {
    for (size_t i = 0; i < buffer.data.size(); i++)
      for (size_t j = 0; j < buffer.data[i].size(); j++) {
        const auto &metadata = buffer.data[i][j];
        if (Adapter::input_fits(current_render_config, i, metadata))
          bear_assert(Adapter::add_block(*renderer, i, metadata), "could not push");
      }
  }

  void fill_temp_pointers(size_t num_out,
                          std::vector<const Sample *> &out,
                          size_t num_in,
                          const Sample *const *in)
  {
    out.resize(num_out);
    for (size_t i = 0; i < num_out; i++) {
      out[i] = (i < num_in) ? in[i] : zeros.data();
    }
  }

  Time get_raw_block_start_time() const { return {num_blocks_processed * block_size, sample_rate}; }

  Time get_raw_next_block_start_time() const
  {
    return {(num_blocks_processed + 1) * block_size, sample_rate};
  }

  size_t block_size;
  size_t num_blocks_processed = 0;
  size_t sample_rate = 0;

  /// metadata buffers for each input type; these are used when starting up a
  /// new renderer
  MetadataBuffer<ObjectsInput, 2> objects_buffer;
  MetadataBuffer<DirectSpeakersInput, 1> direct_speakers_buffer;
  MetadataBuffer<HOAInput, 1> hoa_buffer;

  boost::optional<Renderer> renderer;

  /// the next configuration to pass to the constructor thread, set if the
  /// thread is busy when set_config is called
  boost::optional<ConfigImpl> next_config;

  /// the configuration of renderer, if it exists
  ConfigImpl current_render_config;
  /// the externally-visible configuration, set by set_config, and starting
  /// with zero input channels
  ConfigImpl next_render_config;

  ConstructorThread constructor_thread;

  StateMachine state;

  visr::efl::BasicVector<Sample> ramp_up;
  visr::efl::BasicVector<Sample> ramp_down;
  visr::efl::BasicVector<Sample> zeros;

  std::vector<const Sample *> temp_objects;
  std::vector<const Sample *> temp_direct_speakers;
  std::vector<const Sample *> temp_hoa;

  Time time_offset;

  // non-optional is fine, as the renderer start condition is the same as the
  // default-constructed listener
  Listener last_listener;
  boost::optional<Time> last_listener_interpolation_time;
};

DynamicRenderer::DynamicRenderer() {}

DynamicRenderer::DynamicRenderer(size_t block_size, size_t max_size)
{
  visr::efl::initialiseLibrary();

  impl = std::make_unique<DynamicRendererImpl>(block_size, max_size);
}

DynamicRenderer::DynamicRenderer(DynamicRenderer &&r) = default;

DynamicRenderer &DynamicRenderer::operator=(DynamicRenderer &&r) = default;

void DynamicRenderer::set_config(const Config &config) { impl->set_config(config); }

void DynamicRenderer::set_config_blocking(const Config &config) { impl->set_config_blocking(config); }

std::exception_ptr DynamicRenderer::get_error() { return impl->get_error(); }
bool DynamicRenderer::is_running() { return impl->is_running(); }

void DynamicRenderer::process(size_t num_objects_channels,
                              const Sample *const *objects_input,
                              size_t num_direct_speakers_channels,
                              const Sample *const *direct_speakers_input,
                              size_t num_hoa_channels,
                              const Sample *const *hoa_input,
                              Sample *const *output)
{
  impl->process(num_objects_channels,
                objects_input,
                num_direct_speakers_channels,
                direct_speakers_input,
                num_hoa_channels,
                hoa_input,
                output);
}

bool DynamicRenderer::add_objects_block(size_t channel, ObjectsInput metadata)
{
  return impl->add_objects_block(channel, std::move(metadata));
}

bool DynamicRenderer::add_direct_speakers_block(size_t channel, DirectSpeakersInput metadata)
{
  return impl->add_direct_speakers_block(channel, std::move(metadata));
}

bool DynamicRenderer::add_hoa_block(size_t stream, HOAInput metadata)
{
  return impl->add_hoa_block(stream, std::move(metadata));
}

Time DynamicRenderer::get_block_start_time() const { return impl->get_block_start_time(); }

void DynamicRenderer::set_block_start_time(const Time &time) { impl->set_block_start_time(time); }

void DynamicRenderer::set_listener(const Listener &l, const boost::optional<Time> &interpolation_time)
{
  impl->set_listener(l, interpolation_time);
}

DynamicRenderer::~DynamicRenderer() = default;

}  // namespace bear

ext: cpp

max_stars_repo_name: ebu/bear

max_issues_repo_name: ebu/bear

max_forks_repo_name: ebu/bear


text:
#include <module_loader/directory_scanning_shared_library_factory.hpp>
#include <boost/filesystem.hpp>
#include <module_loader/counting_directory_scanning_shared_library_factory_observer.hpp>
#include <module_loader/directory_entry_filter.hpp>
#include <module_loader/whereami.hpp>
#include <cstddef>
#include <catch.hpp>

namespace module_loader {
namespace test {
namespace {

SCENARIO("module_loader::directory_scanning_shared_library_factory objects traverse all shared libraries in their managed directories","[module_loader][directory_scanning_shared_library_factory]") {
	counting_directory_scanning_shared_library_factory_observer o;
	directory_scanning_shared_library_factory scanner(o);
	GIVEN("A module_loader::directory_scanning_shared_library_factory which does not traverse any directories") {
		WHEN("module_loader::directory_scanning_shared_library_factory::next is invoked") {
			auto so = scanner.next();
			THEN("No boost::dll::shared_library is returned") {
				CHECK_FALSE(so);
			}
			THEN("No events are dispatched") {
				CHECK(o.begin_directory() == 0U);
				CHECK(o.end_directory() == 0U);
				CHECK(o.load() == 0U);
			}
		}
	}
	GIVEN("A module_loader::directory_scanning_shared_library_factory which traverses a directory which contains shared libraries") {
		auto path = current_executable_directory_path();
		auto result = scanner.add(path);
		CHECK(result);
		WHEN("module_loader::directory_scanning_shared_library_factory::next is invoked repeatedly") {
			std::size_t i(0);
			for (; scanner.next(); ++i);
			THEN("The correct number of boost::dll::shared_library objects are yielded") {
				CHECK(i == 6U);
			}
			THEN("The correct events are dispatched") {
				CHECK(o.begin_directory() == 1U);
				CHECK(o.end_directory() == 1U);
				CHECK(o.load() == 6U);
			}
		}
		WHEN("The same directory is added again") {
			path /= "./";
			result = scanner.add(path);
			CHECK_FALSE(result);
			WHEN("module_loader::directory_scanning_shared_library_factory::next is invoked repeatedly") {
				std::size_t i(0);
				for (; scanner.next(); ++i);
				THEN("The correct number of boost::dll::shared_library objects are yielded") {
					CHECK(i == 6U);
				}
				THEN("The correct events are dispatched") {
					CHECK(o.begin_directory() == 1U);
					CHECK(o.end_directory() == 1U);
					CHECK(o.load() == 6U);
				}
			}
		}
	}
}

SCENARIO("module_loader::directory_scanning_shared_library_factory objects accept a module_loader::directory_entry_filter which determines which files to include and which to exclude","[module_loader][directory_scanning_shared_library_factory]") {
	GIVEN("A module_loader::directory_scanning_shared_library_factory with a module_loader::directory_entry_filter which rejects all shared libraries and which scans a directory which contains shared libraries") {
		class : public directory_entry_filter {
			virtual bool check (const boost::filesystem::directory_entry &) override {
				return false;
			}
		} filter;
		//	The directory scanned is the same that we scan
		//	above and verify that it has 6
		directory_scanning_shared_library_factory scanner(filter);
		WHEN("module_loader::directory_scanning_shared_library_factory::next is invoked") {
			auto so = scanner.next();
			THEN("No boost::dll::shared_library is returned") {
				CHECK_FALSE(so);
			}
		}
	}
}

}
}
}

max_stars_repo_name: RobertLeahy/Module-Loader

max_issues_repo_name: RobertLeahy/Module-Loader

max_forks_repo_name: RobertLeahy/Module-Loader


text:
#include "tests.hpp"

#include <yamail/resource_pool/async/detail/pool_impl.hpp>

#include <boost/optional/optional_io.hpp>

namespace {

using namespace tests;
using namespace yamail::resource_pool;
using namespace yamail::resource_pool::async::detail;

struct mocked_queue {
    using list_iterator = std::list<detail::idle<resource>>::iterator;
    using value_type = list_iterator_handler<resource>;
    using queued_value_t = queued_value<value_type, mocked_io_context>;

    MOCK_CONST_METHOD3(push, bool (mocked_io_context&, time_traits::duration, const value_type&));
    MOCK_CONST_METHOD0(pop, boost::optional<queued_value_t> ());
    MOCK_CONST_METHOD0(size, std::size_t ());

    mocked_queue(std::size_t) {}
};

using resource_pool_impl = pool_impl<resource, std::mutex, mocked_io_context, mocked_queue>;
using resource_ptr_list_iterator = resource_pool_impl::list_iterator;
using queued_value_t = mocked_queue::queued_value_t;

auto make_queued_value(mocked_queue::value_type&& request, mocked_io_context& io) {
    return boost::optional<queued_value_t>(queued_value_t {std::move(request), io});
}

}

namespace yamail::resource_pool::async::detail {

template <class V, class I>
inline std::ostream& operator <<(std::ostream& stream, const queued_value<V, I>&) {
    return stream;
}

}

namespace boost {

inline std::ostream& operator <<(std::ostream& stream, resource_ptr_list_iterator res) {
    return stream << &*res;
}

}

namespace {

using boost::system::error_code;

struct mocked_callback {
    MOCK_CONST_METHOD2(call, void (const error_code&, resource_ptr_list_iterator));
};

using mocked_callback_ptr = std::shared_ptr<mocked_callback>;

struct async_resource_pool_impl : Test {
    StrictMock<executor_gmock> executor;
    mocked_executor executor_wrapper {&executor};
    mocked_io_context io {&executor_wrapper};

    std::function<void ()> on_get;
    std::function<void ()> on_first_get;
    std::function<void ()> on_second_get;

    mocked_queue::value_type on_get_res;
};

TEST_F(async_resource_pool_impl, create_with_zero_capacity_should_throw_exception) {
    EXPECT_THROW(resource_pool_impl(0, 0, time_traits::duration::max(), time_traits::duration::max()),
                 error::zero_pool_capacity);
}

TEST_F(async_resource_pool_impl, create_const_with_non_zero_capacity_then_check) {
    const resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());
    EXPECT_EQ(pool.capacity(), 1u);
}

TEST_F(async_resource_pool_impl, create_const_then_check_size_should_be_0) {
    const resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());
    EXPECT_EQ(pool.size(), 0u);
}

TEST_F(async_resource_pool_impl, create_const_then_check_available_should_be_0) {
    const resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());
    EXPECT_EQ(pool.available(), 0u);
}

TEST_F(async_resource_pool_impl, create_const_then_check_used_should_be_0) {
    const resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());
    EXPECT_EQ(pool.used(), 0u);
}

TEST_F(async_resource_pool_impl, create_const_with_range_len2_then_check_capacity_should_be_2) {
    std::vector<resource> res;
    res.emplace_back();
    res.emplace_back();
    const resource_pool_impl pool(
        std::make_move_iterator(std::begin(res)), std::make_move_iterator(std::end(res)),
        0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_EQ(pool.capacity(), 2u);
}

TEST_F(async_resource_pool_impl, create_const_with_range_len2_then_check_size_should_be_2) {
    std::vector<resource> res;
    res.emplace_back();
    res.emplace_back();
    const resource_pool_impl pool(
        std::make_move_iterator(std::begin(res)), std::make_move_iterator(std::end(res)),
        0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_EQ(pool.size(), 2u);
}

TEST_F(async_resource_pool_impl, create_const_with_range_len2_then_check_available_should_be_2) {
    std::vector<resource> res;
    res.emplace_back();
    res.emplace_back();
    const resource_pool_impl pool(
        std::make_move_iterator(std::begin(res)), std::make_move_iterator(std::end(res)),
        0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_EQ(pool.available(), 2u);
}

TEST_F(async_resource_pool_impl, create_const_with_generator_and_capacity_2_then_check_capacity_should_be_2) {
    const resource_pool_impl pool([]{ return resource{}; }, 2, 0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_EQ(pool.capacity(), 2u);
}

TEST_F(async_resource_pool_impl, create_const_with_generator_and_capacity_2_then_check_size_should_be_2) {
    const resource_pool_impl pool([]{ return resource{}; }, 2, 0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_EQ(pool.size(), 2u);
}

TEST_F(async_resource_pool_impl, create_const_with_generator_and_capacity_2_then_check_available_should_be_2) {
    const resource_pool_impl pool([]{ return resource{}; }, 2, 0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_EQ(pool.available(), 2u);
}

TEST_F(async_resource_pool_impl, create_const_then_check_stats_should_be_0_0_0_0) {
    const resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());
    const async::stats expected {0, 0, 0, 0};

    EXPECT_CALL(pool.queue(), size()).WillOnce(Return(0));

    const auto actual = pool.stats();

    EXPECT_EQ(actual.size, expected.size);
    EXPECT_EQ(actual.available, expected.available);
    EXPECT_EQ(actual.used, expected.used);
    EXPECT_EQ(actual.queue_size, expected.queue_size);
}

TEST_F(async_resource_pool_impl, create_const_then_call_queue_should_succeed) {
    const resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());
    EXPECT_NO_THROW(pool.queue());
}

class callback {
public:
    using result_type = void;

    callback() = default;

    callback(const callback&) = delete;

    callback(callback&&) = default;

    callback(const mocked_callback_ptr& impl) : impl(impl) {}

    callback& operator =(const callback&) = delete;

    callback& operator =(callback&&) = default;

    result_type operator ()(const error_code& err,
                            resource_ptr_list_iterator res) const {
        impl->call(err, res);
    }

private:
    mocked_callback_ptr impl;
};

class recycle_resource {
public:
    recycle_resource(resource_pool_impl& pool) : pool(pool) {}

    void operator ()(const error_code& err, resource_ptr_list_iterator res) const {
        EXPECT_EQ(err, error_code());
        pool.recycle(res);
    }

private:
    resource_pool_impl& pool;
};

class waste_resource {
public:
    waste_resource(resource_pool_impl& pool) : pool(pool) {}

    void operator ()(const error_code& err, resource_ptr_list_iterator res) const {
        EXPECT_EQ(err, error_code());
        pool.waste(res);
    }

private:
    resource_pool_impl& pool;
};

ACTION_P(SaveMoveArg2, ptr) {
    *ptr = std::move(const_cast<std::decay_t<decltype(arg2)>&>(arg2));
}

TEST_F(async_resource_pool_impl, get_one_should_call_callback) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    mocked_callback_ptr get = std::make_shared<mocked_callback>();

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_get));
    EXPECT_CALL(*get, call(_, _)).WillOnce(Return());

    pool.get(io, callback(get));
    on_get();
}

TEST_F(async_resource_pool_impl, get_one_and_recycle_should_make_one_available_resource) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));

    pool.get(io, recycle_resource(pool));
    on_get();

    EXPECT_EQ(pool.available(), 1u);
}

TEST_F(async_resource_pool_impl, get_one_and_waste_should_make_no_available_resources) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));

    pool.get(io, waste_resource(pool));
    on_get();

    EXPECT_EQ(pool.available(), 0u);
}

TEST_F(async_resource_pool_impl, get_twice_and_recycle_should_make_one_available_resource) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, recycle_resource(pool));
    on_first_get();

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, recycle_resource(pool), time_traits::duration(1));
    on_second_get();

    EXPECT_EQ(pool.available(), 1u);
}

TEST_F(async_resource_pool_impl, get_twice_and_recycle_should_use_queue_and_make_one_available_resource) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(DoAll(SaveMoveArg2(&on_get_res), Return(true)));
    pool.get(io, recycle_resource(pool));
    pool.get(io, recycle_resource(pool), time_traits::duration(1));

    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(make_queued_value(std::move(on_get_res), io))));
    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    on_first_get();
    on_second_get();

    EXPECT_EQ(pool.available(), 1u);
}

TEST_F(async_resource_pool_impl, get_twice_and_recycle_with_zero_idle_timeout_should_use_queue_and_make_one_available_resource) {
    resource_pool_impl pool(1, 0, time_traits::duration(0), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(DoAll(SaveMoveArg2(&on_get_res), Return(true)));
    pool.get(io, recycle_resource(pool));
    pool.get(io, recycle_resource(pool), time_traits::duration(1));

    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(make_queued_value(std::move(on_get_res), io))));
    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    on_first_get();
    on_second_get();

    EXPECT_EQ(pool.available(), 1u);
}

TEST_F(async_resource_pool_impl, get_twice_and_waste_then_get_should_use_queue) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(DoAll(SaveMoveArg2(&on_get_res), Return(true)));
    pool.get(io, waste_resource(pool));
    pool.get(io, waste_resource(pool), time_traits::duration(1));

    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(make_queued_value(std::move(on_get_res), io))));
    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    on_first_get();
    on_second_get();

    EXPECT_EQ(pool.available(), 0u);
}

class check_error {
public:
    check_error(const error_code& error) : error(error) {}
    check_error(const error::code& error) : error(make_error_code(error)) {}

    void operator ()(const error_code& err, resource_ptr_list_iterator) const {
        EXPECT_EQ(err, error);
    }

private:
    const error_code error;
};

struct check_no_error : check_error {
    check_no_error() : check_error(error_code()) {}
};

TEST_F(async_resource_pool_impl, get_with_queue_zero_capacity_use_should_return_error) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(Return(false));
    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));

    pool.get(io, recycle_resource(pool));
    pool.get(io, check_error(error::request_queue_overflow), time_traits::duration(1));
    on_first_get();
    on_second_get();

    EXPECT_EQ(pool.available(), 1u);
}

TEST_F(async_resource_pool_impl, get_with_queue_use_and_timer_timeout_should_return_error) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(DoAll(SaveMoveArg2(&on_get_res), Return(true)));

    pool.get(io, check_no_error());
    pool.get(io, check_error(error::get_resource_timeout), time_traits::duration(1));
    on_first_get();
    on_get_res(make_error_code(error::get_resource_timeout));
}

TEST_F(async_resource_pool_impl, get_with_queue_use_with_zero_wait_duration_should_return_error) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));

    pool.get(io, recycle_resource(pool));
    pool.get(io, check_error(error::get_resource_timeout), time_traits::duration(0));
    on_first_get();
    on_second_get();

    EXPECT_EQ(pool.available(), 1u);
}

TEST_F(async_resource_pool_impl, get_after_disable_returns_error) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    EXPECT_CALL(executor, dispatch(_)).WillOnce(SaveArg<0>(&on_get));

    pool.disable();
    pool.get(io, check_error(error::disabled));
    on_get();
}

TEST_F(async_resource_pool_impl, get_recycled_after_disable_returns_error) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(DoAll(SaveMoveArg2(&on_get_res), Return(true)));
    pool.get(io, recycle_resource(pool));
    pool.get(io, check_error(error::disabled), time_traits::duration(1));

    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(make_queued_value(std::move(on_get_res), io))));
    EXPECT_CALL(executor, dispatch(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.disable();
    on_first_get();
    on_second_get();
}

class set_and_recycle_resource {
public:
    set_and_recycle_resource(resource_pool_impl& pool) : pool(pool) {}

    void operator ()(const error_code& err, resource_ptr_list_iterator res) const {
        EXPECT_EQ(err, error_code());
        res->value = resource {};
        res->reset_time = time_traits::now();
        pool.recycle(res);
    }

private:
    resource_pool_impl& pool;
};

struct assert_empty {
public:
    assert_empty(resource_pool_impl& pool) : pool(pool) {}

    void operator ()(const error_code& err, resource_ptr_list_iterator res) const {
        EXPECT_EQ(err, error_code());
        EXPECT_FALSE(res->value);
        pool.waste(res);
    }

private:
    resource_pool_impl& pool;
};

TEST_F(async_resource_pool_impl, get_one_set_and_recycle_with_zero_idle_timeout_then_get_should_return_empty) {
    resource_pool_impl pool(1, 0, time_traits::duration(0), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, set_and_recycle_resource(pool));
    on_first_get();

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, assert_empty(pool), time_traits::duration(1));
    on_second_get();
}

TEST_F(async_resource_pool_impl, should_waste_resource_when_lifespan_ends) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration(0));

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, set_and_recycle_resource(pool));
    on_first_get();

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, assert_empty(pool), time_traits::duration(1));
    on_second_get();
}

TEST_F(async_resource_pool_impl, should_waste_resource_when_lifespan_ends_and_queue_is_not_empty) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration(0));

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(DoAll(SaveMoveArg2(&on_get_res), Return(true)));
    pool.get(io, set_and_recycle_resource(pool));
    pool.get(io, assert_empty(pool), time_traits::duration(1));

    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(make_queued_value(std::move(on_get_res), io))));
    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    on_first_get();
    on_second_get();
}

TEST_F(async_resource_pool_impl, should_waste_used_resource_after_invalidate) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, set_and_recycle_resource(pool));
    pool.invalidate();
    on_first_get();

    EXPECT_EQ(pool.available(), 0u);

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, assert_empty(pool), time_traits::duration(1));
    on_second_get();
}

TEST_F(async_resource_pool_impl, should_waste_available_resource_after_invalidate) {
    resource_pool_impl pool([]{ return resource{}; }, 1, 0, time_traits::duration::max(), time_traits::duration::max());

    pool.invalidate();

    EXPECT_EQ(pool.available(), 0u);
}

TEST_F(async_resource_pool_impl, should_restore_wasted_cell) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, set_and_recycle_resource(pool));
    pool.invalidate();
    on_first_get();

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    pool.get(io, set_and_recycle_resource(pool), time_traits::duration(1));
    on_second_get();

    EXPECT_EQ(pool.available(), 1u);
}

TEST_F(async_resource_pool_impl, should_waste_used_resource_after_invalidate_when_queue_is_not_empty) {
    resource_pool_impl pool(1, 0, time_traits::duration::max(), time_traits::duration::max());

    InSequence s;

    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_first_get));
    EXPECT_CALL(pool.queue(), push(_, _, _)).WillOnce(DoAll(SaveMoveArg2(&on_get_res), Return(true)));
    pool.get(io, set_and_recycle_resource(pool));
    pool.get(io, assert_empty(pool), time_traits::duration(1));
    pool.invalidate();

    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(make_queued_value(std::move(on_get_res), io))));
    EXPECT_CALL(executor, post(_)).WillOnce(SaveArg<0>(&on_second_get));
    EXPECT_CALL(pool.queue(), pop()).WillOnce(Return(ByMove(boost::none)));
    on_first_get();
    on_second_get();
}

}

ext: cc


text:
// Boost.Geometry (aka GGL, Generic Geometry Library)
// This file is manually converted from PROJ4

// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.

// This file was modified by Oracle on 2018.
// Modifications copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// This file is converted from PROJ4, http://trac.osgeo.org/proj
// PROJ4 is originally written by Gerald Evenden (then of the USGS)
// PROJ4 is maintained by Frank Warmerdam
// PROJ4 is converted to Geometry Library by Barend Gehrels (Geodan, Amsterdam)

// Original copyright notice:

// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#ifndef BOOST_GEOMETRY_PROJECTIONS_IMPL_AASINCOS_HPP
#define BOOST_GEOMETRY_PROJECTIONS_IMPL_AASINCOS_HPP

#include <cmath>

#include <boost/geometry/srs/projections/exception.hpp>
#include <boost/geometry/srs/projections/impl/pj_strerrno.hpp>
#include <boost/geometry/util/math.hpp>

namespace boost { namespace geometry { namespace projections
{

namespace detail
{

namespace aasincos
{
    template <typename T>
    inline T ONE_TOL() { return 1.00000000000001; }
    //template <typename T>
    //inline T TOL() { return 0.000000001; }
    template <typename T>
    inline T ATOL() { return 1e-50; }
}

template <typename T>
inline T aasin(T const& v)
{
    T av = 0;

    if ((av = geometry::math::abs(v)) >= 1.0)
    {
        if (av > aasincos::ONE_TOL<T>())
        {
            BOOST_THROW_EXCEPTION( projection_exception(error_acos_asin_arg_too_large) );
        }
        return (v < 0.0 ? -geometry::math::half_pi<T>() : geometry::math::half_pi<T>());
    }

    return asin(v);
}

template <typename T>
inline T aacos(T const& v)
{
    T av = 0;

    if ((av = geometry::math::abs(v)) >= 1.0)
    {
        if (av > aasincos::ONE_TOL<T>())
        {
            BOOST_THROW_EXCEPTION( projection_exception(error_acos_asin_arg_too_large) );
        }
        return (v < 0.0 ? geometry::math::pi<T>() : 0.0);
    }

    return acos(v);
}

template <typename T>
inline T asqrt(T const& v)
{
    return ((v <= 0) ? 0 : sqrt(v));
}

template <typename T>
inline T aatan2(T const& n, T const& d)
{
    return ((geometry::math::abs(n) < aasincos::ATOL<T>()
        && geometry::math::abs(d) < aasincos::ATOL<T>()) ? 0.0 : atan2(n, d));
}

} // namespace detail

}}} // namespace boost::geometry::projections

#endif // BOOST_GEOMETRY_PROJECTIONS_IMPL_AASINCOS_HPP

ext: hpp


text:
#include "ZambeziManager.h"
#include <common/PropSharedLock.h>
#include "../zambezi-tokenizer/ZambeziTokenizer.h"
#include <boost/utility.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <math.h>
#include <algorithm>
#include <iostream>

using namespace sf1r;

ZambeziManager::ZambeziManager(
        const ZambeziConfig& config)
    : config_(config)
    , zambeziTokenizer_(NULL)
{
    init();

    if (!config_.hasAttrtoken)
        buildTokenizeDic();
}

ZambeziManager::~ZambeziManager()
{
    if (zambeziTokenizer_)
        delete zambeziTokenizer_;

    for (unsigned int i = 0; i < propertyList_.size(); ++i)
    {
        if (property_index_map_[propertyList_[i]] != NULL)
            delete property_index_map_[propertyList_[i]];
    }
}

void ZambeziManager::init()
{
    for (std::vector<ZambeziProperty>::const_iterator i = config_.properties.begin(); i != config_.properties.end(); ++i)
    {
        if (i->isTokenizer)
        {
            propertyList_.push_back(i->name);
            ZambeziIndexBase* zambeziIndex = NULL;
            createZambeziIndex_(zambeziIndex, i->poolSize);
            property_index_map_.insert(std::make_pair(i->name, zambeziIndex));
        }
    }

    for (std::vector<ZambeziVirtualProperty>::const_iterator i = config_.virtualPropeties.begin(); i != config_.virtualPropeties.end(); ++i)
    {
        propertyList_.push_back(i->name);
        ZambeziIndexBase* zambeziIndex = NULL;
        createZambeziIndex_(zambeziIndex, i->poolSize);
        property_index_map_.insert(std::make_pair(i->name, zambeziIndex));
    }
}

void ZambeziManager::createZambeziIndex_(ZambeziIndexBase* &zambeziIndex, unsigned int poolSize)
{
    if (config_.indexType_ == ZambeziIndexType::DefultIndexType)
    {
        zambeziIndex = new AttrIndex(poolSize, config_.poolCount, config_.vocabSize, config_.reverse);
    }
    else if (config_.indexType_ == ZambeziIndexType::PostionIndexType)
    {
        zambeziIndex = new PositionalIndex(izenelib::ir::Zambezi::NON_POSITIONAL, poolSize, config_.poolCount, config_.vocabSize, config_.reverse);
    }
}

void ZambeziManager::buildTokenizeDic()
{
    boost::filesystem::path cma_index_dic(config_.system_resource_path_);
    cma_index_dic /= boost::filesystem::path("dict");
    cma_index_dic /= boost::filesystem::path(config_.tokenPath);

    ZambeziTokenizer::TokenizerType type = ZambeziTokenizer::CMA_MAXPRE;

    zambeziTokenizer_ = new ZambeziTokenizer();
    zambeziTokenizer_->initWithCMA_(type, cma_index_dic.c_str());
    zambeziTokenizer_->setItemUnique(config_.indexType_ == ZambeziIndexType::DefultIndexType);
}

ZambeziTokenizer* ZambeziManager::getTokenizer()
{
    return zambeziTokenizer_;
}

bool ZambeziManager::open()
{
    const std::string& basePath = config_.indexFilePath; //not init

    for (std::vector<std::string>::iterator i = propertyList_.begin(); i != propertyList_.end(); ++i)
    {

        LOG(INFO) << "index BASE PATH: " << basePath << std::endl;
        std::string path = basePath + "_" + *i; // index.bin_Title
        std::ifstream ifs(path.c_str(), std::ios_base::binary);

        if (!ifs)
        {
            LOG(WARNING) << "NEW zambezi or add new property!";
            return true; // nothing to load, if add new property, that need to rebuild;
        }

        LOG(INFO) << "loading zambezi index for propery: " << *i << ", path" << path;

        try
        {
            property_index_map_[*i]->load(ifs);
        }
        catch (const std::exception& e)
        {
            LOG(ERROR) << "exception in read file: " << e.what()
                   << ", path: " << path;
            return false;
        }
    }

    LOG(INFO) << "Finished open zambezi index";

    return true;
}

void ZambeziManager::search(
        izenelib::ir::Zambezi::Algorithm algorithm,
        const std::vector<std::pair<std::string, int> >& tokens,
        const std::vector<std::string>& propertyList,
        const ZambeziFilterBase* filter,
        uint32_t limit,
        std::vector<docid_t>& docids,
        std::vector<float>& scores)
{
    if (config_.indexType_ == ZambeziIndexType::DefultIndexType)
    {
        if (algorithm != izenelib::ir::Zambezi::SVS)
        {
           algorithm = izenelib::ir::Zambezi::SVS;
           LOG(WARNING) << "The AttrInvertedInde only use SVS algorithm !!!";
        }
    }

    LOG(INFO) << "[ZambeziManager::search] Search tokens: ";
    for (unsigned int i = 0; i < tokens.size(); ++i)
    {
        std::cout << tokens[i].first <<" , ";
    }
    std::cout << std::endl;

    izenelib::util::ClockTimer timer;
    // in one property
    if (propertyList.size() == 1)
    {
        property_index_map_[propertyList[0]]->retrieve(algorithm, tokens, filter, limit, docids, scores);
        LOG(INFO) << "Search property:" << propertyList[0]
                  << " ,zambezi returns docid num: " << docids.size()
                  << ", costs :" << timer.elapsed() << " seconds";
        return;
    }

    // only one property
    if (propertyList_.size() == 1)
    {
        property_index_map_[propertyList_[0]]->retrieve(algorithm, tokens, filter, limit, docids, scores);
        LOG(INFO) << "zambezi returns docid num: " << docids.size()
                  << ", costs :" << timer.elapsed() << " seconds";
        return;
    }

    std::vector<std::string> searchPropertyList = propertyList;
    if (searchPropertyList.empty())
        searchPropertyList = propertyList_;

    std::vector<std::vector<docid_t> > docidsList;
    docidsList.resize(searchPropertyList.size());
    std::vector<std::vector<float> > scoresList;
    scoresList.resize(searchPropertyList.size());

    std::vector<float> weightList;
    for (unsigned int i = 0; i < searchPropertyList.size(); ++i)
    {
        property_index_map_[searchPropertyList[i]]->retrieve(algorithm, tokens, filter, limit, docidsList[i], scoresList[i]);
        weightList.push_back(config_.getWeight(searchPropertyList[i]));
    }

    izenelib::util::ClockTimer timer_merge;

    for (unsigned int i = 0; i < docidsList.size(); ++i)
    {
        if (docidsList[i].size() != scoresList[i].size())
        {
            LOG(WARNING) << "[WARNING] dismatch doclist size:("<< docidsList[i].size() << ") and scorelist size:(" << scoresList.size() << ")" ;
            if (config_.indexType_ == ZambeziIndexType::DefultIndexType)
                return;
            else
                scoresList[i].resize(docidsList[i].size(), 0);
        }
    }

    //set weightList of preproty;
    merge_(docidsList, scoresList, weightList, docids, scores);

    LOG(INFO) << "zambezi merge " << docidsList.size()
              << " properties, costs :" << timer_merge.elapsed() << " seconds";

    LOG(INFO) << "zambezi returns docid num: " << docids.size()
              << ", costs :" << timer.elapsed() << " seconds";
}

// to do, add weight to each posting
void ZambeziManager::merge_(
        const std::vector<std::vector<docid_t> >& docidsList,
        const std::vector<std::vector<float> >& scoresList,
        const std::vector<float>& weightList,
        std::vector<docid_t>& docids,
        std::vector<float>& scores)
{
    // init
    unsigned int docidsListSize = docidsList.size();
    int totalCount = 0;
    int docCount = 0;

    std::list<pair<int, unsigned int> > existingList;
    for (unsigned int i = 0; i < docidsListSize; ++i)
    {
        if (docidsList[i].size() != 0)
        {
            totalCount += docidsList[i].size();
            existingList.push_back(std::make_pair(i, 0));
        }
    }
    docids.resize(totalCount);
    scores.resize(totalCount);

    // count
    std::vector<std::list<pair<int, unsigned int> >::iterator> minDocList;

    unsigned int min = -1;
    while(existingList.size() > 1)
    {
        if (config_.reverse)
            min = 0;
        else
            min = -1;

        for (std::list<pair<int, unsigned int> >::iterator i = existingList.begin(); i != existingList.end(); ++i)
        {
            if ((config_.reverse && min < docidsList[i->first][i->second]) ||
                (!config_.reverse && min > docidsList[i->first][i->second]))
            {
                min = docidsList[i->first][i->second];
                minDocList.clear();
                minDocList.push_back(i);
                continue;
            }
            if (min == docidsList[i->first][i->second])
                minDocList.push_back(i);
        }

        for (unsigned int i = 0; i < minDocList.size(); ++i)
        {
            int k = minDocList[i]->first;
            int j = minDocList[i]->second++;
            if (minDocList[i]->second == docidsList[k].size())
                existingList.erase(minDocList[i]);

            docids[docCount] = docidsList[k][j];
            scores[docCount] += scoresList[k][j]*weightList[k];
        }
        docCount++;
    }

    if (existingList.size() == 1)
    {
        int k = existingList.begin()->first;
        for (unsigned int i = existingList.begin()->second; i < docidsList[k].size(); ++i)
        {
            docids[docCount] = docidsList[k][i];
            scores[docCount++] = scoresList[k][i]*weightList[k];
        }
    }
    docids.resize(docCount);
    scores.resize(docCount);
}


text:
#include <boost/test/unit_test.hpp>
#include "test_utils.hpp"

#include <templ/solvers/temporal/point_algebra/TimePoint.hpp>
#include <templ/solvers/temporal/point_algebra/QualitativeTimePoint.hpp>

using namespace templ::solvers::temporal::point_algebra;

BOOST_AUTO_TEST_SUITE(timepoint)

BOOST_AUTO_TEST_CASE(equality)
{
    {
        TimePoint::Ptr tp0(new TimePoint(0,10));
        TimePoint::Ptr tp0Dup(new TimePoint(0,10));
        TimePoint::Ptr tp1(new TimePoint(0,11));

        BOOST_REQUIRE_MESSAGE(tp0->equals(tp0Dup), tp0->toString() << " equals " << tp0Dup->toString());
        BOOST_REQUIRE_MESSAGE(!tp0->equals(tp1), tp0->toString() << " does not equal " << tp1->toString());
    }

    {
        TimePoint::Ptr tp0 = TimePoint::create("tp0");
        TimePoint::Ptr tp0Dup = TimePoint::create("tp0");
        TimePoint::Ptr tp1 = TimePoint::create("tp1");

        BOOST_REQUIRE_MESSAGE(tp0->equals(tp0Dup), tp0->toString() << " equals " << tp0Dup->toString());
        BOOST_REQUIRE_MESSAGE(!tp0->equals(tp1), tp0->toString() << " does not equal " << tp1->toString());

        QualitativeTimePoint::Ptr qtp = templ::dynamic_pointer_cast<QualitativeTimePoint>(tp1);
        qtp->addAlias("tp0");

        BOOST_REQUIRE_MESSAGE(tp0->equals(tp1), tp0->toString() << " equals (through alias) " << tp1->toString());
    }
}

BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: tomcreutz/planning-templ

max_issues_repo_name: tomcreutz/planning-templ

max_forks_repo_name: tomcreutz/planning-templ


text:
/*
 Copyright (C) 2016 Quaternion Risk Management Ltd
 All rights reserved.

 This file is part of ORE, a free-software/open-source library
 for transparent pricing and risk analysis - http://opensourcerisk.org

 ORE is free software: you can redistribute it and/or modify it
 under the terms of the Modified BSD License.  You should have received a
 copy of the license along with this program.
 The license is also available online at <http://opensourcerisk.org>

 This program is distributed on the basis that it will form a useful
 contribution to risk analytics and model standardisation, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

/*! \file portfolio/builders/swap.hpp
    \brief
    \ingroup builders
*/

#pragma once

#include <ored/portfolio/builders/cachingenginebuilder.hpp>
#include <ored/portfolio/enginefactory.hpp>
#include <ored/utilities/log.hpp>

#include <qle/models/lgm.hpp>

#include <boost/make_shared.hpp>

namespace ore {
namespace data {

//! European Swaption Engine Builder
/*! European Swaptions are priced with Black or Bachelier pricing engines,
 *  depending on the volatility type provided by Market (if it is normal, this
 *  builder returns a Bachelier engine, if it is lognormal (or lognormal shiffed)
 *  it will be a Black engine.
 *
 *  Engines are cached based on currency

    \ingroup builders
 */
class EuropeanSwaptionEngineBuilder : public CachingPricingEngineBuilder<string, const Currency&> {
public:
    EuropeanSwaptionEngineBuilder()
        : CachingEngineBuilder("BlackBachelier", "BlackBachelierSwaptionEngine", {"EuropeanSwaption"}) {}

protected:
    virtual string keyImpl(const Currency& ccy) override { return ccy.code(); }

    virtual boost::shared_ptr<PricingEngine> engineImpl(const Currency& ccy) override;
};

//! Abstract BermudanSwaptionEngineBuilder class
/*! This defines the interface for Bermudan Swaption Builders
 *  Pricing Engines are cached by trade id

    \ingroup builders
 */
class BermudanSwaptionEngineBuilder
    : public CachingPricingEngineBuilder<string, const string&, const bool, const string&, const std::vector<Date>&,
                                         const Date&, const std::vector<Real>&> {
public:
    BermudanSwaptionEngineBuilder(const string& model, const string& engine)
        : CachingEngineBuilder(model, engine, {"BermudanSwaption"}) {}

protected:
    virtual string keyImpl(const string& id, const bool isNonStandard, const string& ccy,
                           const std::vector<Date>& dates, const Date& maturity,
                           const std::vector<Real>& strikes) override {
        return id;
    }
};

//! Abstract LGMBermudanSwaptionEngineBuilder class
/*! This defines the interface for LGM Bermudan Swaption Builders

\ingroup builders
*/
class LGMBermudanSwaptionEngineBuilder : public BermudanSwaptionEngineBuilder {
public:
    LGMBermudanSwaptionEngineBuilder(const string& engine) : BermudanSwaptionEngineBuilder("LGM", engine) {}

protected:
    boost::shared_ptr<QuantExt::LGM> model(const string& id, bool isNonStandard, const string& ccy,
                                           const std::vector<Date>& dates, const Date& maturity,
                                           const std::vector<Real>& strikes);
};

//! Implementation of BermudanSwaptionEngineBuilder using LGM Grid pricer
/*! \ingroup builders
 */
class LGMGridBermudanSwaptionEngineBuilder : public LGMBermudanSwaptionEngineBuilder {
public:
    LGMGridBermudanSwaptionEngineBuilder() : LGMBermudanSwaptionEngineBuilder("Grid") {}

protected:
    virtual boost::shared_ptr<PricingEngine> engineImpl(
        //! a unique (trade) id, for caching
        const string& id,
        //! is this a standard swaption
        const bool isNonStandard,
        //! the currency
        const string& ccy,
        //! Excercise dates
        const std::vector<Date>& dates,
        //! maturity of the underlying
        const Date& maturity,
        //! Fixed rate (null means ATM)
        const std::vector<Real>& strikes) override;
};

} // namespace data
} // namespace ore

max_stars_repo_name: PiotrSiejda/Engine

max_issues_repo_name: PiotrSiejda/Engine

max_forks_repo_name: PiotrSiejda/Engine


text:
////////////////////////////////////////////////////////////////////////
// fast online configuration file
//
// Manuel Martinez (manuel.martinez@kit.edu)
//
// license: LGPLv3
//
// GCC-FLAGS: -Ofast -std=c++0x `pkg-config opencv --cflags` `pkg-config opencv --libs`

#pragma once
#include <iostream>
#include <boost/property_tree/json_parser.hpp>
#include <boost/filesystem/operations.hpp>
#include <chrono>

namespace uSnippets {
struct Configuration {

	std::string configFileName;
	uint64_t    lastCheckTime;
	std::time_t lastConfigTime;
	boost::property_tree::ptree pTree;
	bool updated;

	Configuration(std::string configFileName) : configFileName(configFileName), lastConfigTime(0) {}

	static uint64_t now() {	return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); }

	void update() {

		boost::filesystem::path p( configFileName ) ;
		if ( not lastConfigTime or lastCheckTime < now()-1000000) {

			lastCheckTime = now();
			if ( boost::filesystem::exists( p ) and boost::filesystem::last_write_time( p ) != lastConfigTime ) {

				lastConfigTime = boost::filesystem::last_write_time( p ) ;
				boost::property_tree::json_parser::read_json( configFileName, pTree );
				updated = true;
			} else {

				updated = false;
			}
		}
	}

	template <typename T>
	inline T operator()(const std::string &key, const T def) {

		update();

		std::string pkey = std::string("base.")+key;
		auto child = pTree.get_child_optional(pkey);
		if (child)
			return child->get_value<T>();

		pTree.put(pkey, def);
		boost::property_tree::json_parser::write_json( configFileName, pTree );

		return def;
	}

	template <typename T>
	inline void set(const std::string &key, const T val) {

		update();

		std::string pkey = std::string("base.")+key;
		auto child = pTree.get_child_optional(pkey);
		if (child and child->get_value<T>()==val)
			return;

		pTree.put(pkey, val);
		boost::property_tree::json_parser::write_json( configFileName, pTree );
	}
};
}

max_stars_repo_name: MartinezTorres/uSnippets

max_issues_repo_name: MartinezTorres/uSnippets

max_forks_repo_name: MartinezTorres/uSnippets


text:
// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland

// This file was modified by Oracle on 2013-2018.
// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.

// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle

// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP

#include <cstddef>

#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tags.hpp>

#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
#include <boost/geometry/strategies/disjoint.hpp>

namespace boost { namespace geometry
{

#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace disjoint
{

/*!
    \brief Internal utility function to detect if point/box are disjoint
 */
template <typename Point, typename Box, typename Strategy>
inline bool disjoint_point_box(Point const& point, Box const& box, Strategy const& )
{
    // ! covered_by(point, box)
    return ! Strategy::apply(point, box);
}

}} // namespace detail::disjoint
#endif // DOXYGEN_NO_DETAIL

#ifndef DOXYGEN_NO_DISPATCH
namespace dispatch
{

template <typename Point, typename Box, std::size_t DimensionCount>
struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, false>
{
    template <typename Strategy>
    static inline bool apply(Point const& point, Box const& box, Strategy const& )
    {
        // ! covered_by(point, box)
        return ! Strategy::apply(point, box);
    }
};

} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_BOX_HPP

max_stars_repo_name: cpp-pm/boost

max_issues_repo_name: cpp-pm/boost

max_forks_repo_name: cpp-pm/boost