// Autogenerated by tools\build\make_containers.py
// from tools\build\container_templates\core\classname_predicates.h
// Do not edit - any changes will be lost!

/**
 *  \file IMP/core/singleton_predicates.h
 *  \brief Define some predicates.
 *
 *  Copyright 2007-2021 IMP Inventors. All rights reserved.
 */

#ifndef IMPCORE_SINGLETON_PREDICATES_H
#define IMPCORE_SINGLETON_PREDICATES_H

#include <IMP/core/core_config.h>
#include <IMP/core/Typed.h>
#include <IMP/SingletonPredicate.h>
#include <IMP/singleton_macros.h>
#include <boost/random.hpp>
#include "internal/container_helpers.h"

IMPCORE_BEGIN_NAMESPACE

/** Always return a constant value.
 */
class IMPCOREEXPORT ConstantSingletonPredicate : public SingletonPredicate {
  int v_;

 public:
  ConstantSingletonPredicate(int v,
                             std::string name = "ConstSingletonPredicate%1%");
  virtual int get_value_index(Model *, ParticleIndex) const
      IMP_OVERRIDE {
    return v_;
  }
  virtual ModelObjectsTemp do_get_inputs(
      Model *, const ParticleIndexes &) const IMP_OVERRIDE {
    return ModelObjectsTemp();
  }
  IMP_SINGLETON_PREDICATE_METHODS(ConstantSingletonPredicate);
  IMP_OBJECT_METHODS(ConstantSingletonPredicate);
};

/** Return a unique predicate value for each unordered set of
   ParticleTypes
    (see Typed).
*/

class IMPCOREEXPORT UnorderedTypeSingletonPredicate
    : public SingletonPredicate {
 public:
  UnorderedTypeSingletonPredicate(std::string name =
                                      "UnorderedTypeSingletonPredicate%1%");
  virtual int get_value_index(Model *m, ParticleIndex pi) const
      IMP_OVERRIDE {
    return internal::get_type_hash(m, pi);
  }
  virtual ModelObjectsTemp do_get_inputs(
      Model *m, const ParticleIndexes &pis) const IMP_OVERRIDE {
    ModelObjectsTemp ret;
    ret += IMP::get_particles(m, pis);
    return ret;
  }
  IMP_SINGLETON_PREDICATE_METHODS(UnorderedTypeSingletonPredicate);
  IMP_OBJECT_METHODS(UnorderedTypeSingletonPredicate);
};

/** Return a unique predicate value for each ordered singleton of
    ParticleTypes (see Typed).
*/
class IMPCOREEXPORT OrderedTypeSingletonPredicate : public SingletonPredicate {
 private:
  mutable int const* cached_particle_type_ids_table_;
  mutable int cached_n_particle_types_;
 public:
  OrderedTypeSingletonPredicate(std::string name =
                                    "OrderedTypeSingletonPredicate%1%");
  //! Compute the predicate for specified types
  int get_value(const core::ParticleTypes &types) {
    return internal::get_ordered_type_hash(types);
  }
  //! Compute the predicate for types of specific pi
  virtual int get_value_index(Model *m, ParticleIndex pi) const
      IMP_OVERRIDE {
    return internal::get_ordered_type_hash(m, pi);
  }

  //! Setup for a batch of calls to get_value_index_in_batch()
  //! (used for improving performance)
  virtual void setup_for_get_value_index_in_batch(Model* m) const
  IMP_OVERRIDE{
    cached_particle_type_ids_table_=
      m->IMP::internal::IntAttributeTable::access_attribute_data(Typed::get_type_key());
    cached_n_particle_types_= ParticleType::get_number_unique();
  };

  //! Same as get_value_index, but with optimizations
  //! for a batch of calls. Call setup_for_get_value_index_in_batch()
  //! right before calling a batch of those, otherwise unexpected behavior.
  virtual int get_value_index_in_batch(Model* m, ParticleIndex pi) const
  IMP_OVERRIDE{
    IMP_UNUSED(m);
    return internal::get_ordered_type_hash( pi,
                                            cached_particle_type_ids_table_,
                                            cached_n_particle_types_);
  }

  virtual ModelObjectsTemp do_get_inputs(
      Model *m, const ParticleIndexes &pis) const IMP_OVERRIDE {
    ModelObjectsTemp ret;
    ret += IMP::get_particles(m, pis);
    return ret;
  }
  IMP_SINGLETON_PREDICATE_METHODS(OrderedTypeSingletonPredicate);
  IMP_OBJECT_METHODS(OrderedTypeSingletonPredicate);
};

/** Return true if all members of the tuple are the same. */
class IMPCOREEXPORT AllSameSingletonPredicate : public SingletonPredicate {
 public:
  AllSameSingletonPredicate(std::string name = "AllSameSingletonPredicate%1%");
  virtual int get_value_index(Model *m, ParticleIndex pi) const
      IMP_OVERRIDE {
    return internal::get_all_same(m, pi);
  }
  virtual ModelObjectsTemp do_get_inputs(
      Model *, const ParticleIndexes &) const IMP_OVERRIDE {
    return ModelObjectsTemp();
  }
  IMP_SINGLETON_PREDICATE_METHODS(AllSameSingletonPredicate);
  IMP_OBJECT_METHODS(AllSameSingletonPredicate);
};

/** Return true with a fixed probability. */
class IMPCOREEXPORT CoinFlipSingletonPredicate : public SingletonPredicate {
  double p_;
  mutable boost::uniform_real<double> rng_;

 public:
  CoinFlipSingletonPredicate(double p, std::string name =
                                           "CoinFlipSingletonPredicate%1%");
  virtual int get_value_index(Model *, ParticleIndex) const
      IMP_OVERRIDE {
    if (rng_(random_number_generator) < p_)
      return 1;
    else
      return 0;
  }
  virtual ModelObjectsTemp do_get_inputs(
      Model *, const ParticleIndexes &) const IMP_OVERRIDE {
    return ModelObjectsTemp();
  }
  IMP_SINGLETON_PREDICATE_METHODS(CoinFlipSingletonPredicate);
  IMP_OBJECT_METHODS(CoinFlipSingletonPredicate);
};

IMPCORE_END_NAMESPACE

#endif /* IMPCORE_SINGLETON_PREDICATES_H */
