// 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/quad_predicates.h
 *  \brief Define some predicates.
 *
 *  Copyright 2007-2021 IMP Inventors. All rights reserved.
 */

#ifndef IMPCORE_QUAD_PREDICATES_H
#define IMPCORE_QUAD_PREDICATES_H

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

IMPCORE_BEGIN_NAMESPACE

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

 public:
  ConstantQuadPredicate(int v,
                             std::string name = "ConstQuadPredicate%1%");
  virtual int get_value_index(Model *, const ParticleIndexQuad&) const
      IMP_OVERRIDE {
    return v_;
  }
  virtual ModelObjectsTemp do_get_inputs(
      Model *, const ParticleIndexes &) const IMP_OVERRIDE {
    return ModelObjectsTemp();
  }
  IMP_QUAD_PREDICATE_METHODS(ConstantQuadPredicate);
  IMP_OBJECT_METHODS(ConstantQuadPredicate);
};

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

class IMPCOREEXPORT UnorderedTypeQuadPredicate
    : public QuadPredicate {
 public:
  UnorderedTypeQuadPredicate(std::string name =
                                      "UnorderedTypeQuadPredicate%1%");
  virtual int get_value_index(Model *m, const ParticleIndexQuad& 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_QUAD_PREDICATE_METHODS(UnorderedTypeQuadPredicate);
  IMP_OBJECT_METHODS(UnorderedTypeQuadPredicate);
};

/** Return a unique predicate value for each ordered quad of
    ParticleTypes (see Typed).
*/
class IMPCOREEXPORT OrderedTypeQuadPredicate : public QuadPredicate {
 private:
  mutable int const* cached_particle_type_ids_table_;
  mutable int cached_n_particle_types_;
 public:
  OrderedTypeQuadPredicate(std::string name =
                                    "OrderedTypeQuadPredicate%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, const ParticleIndexQuad& 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, const ParticleIndexQuad& 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_QUAD_PREDICATE_METHODS(OrderedTypeQuadPredicate);
  IMP_OBJECT_METHODS(OrderedTypeQuadPredicate);
};

/** Return true if all members of the tuple are the same. */
class IMPCOREEXPORT AllSameQuadPredicate : public QuadPredicate {
 public:
  AllSameQuadPredicate(std::string name = "AllSameQuadPredicate%1%");
  virtual int get_value_index(Model *m, const ParticleIndexQuad& 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_QUAD_PREDICATE_METHODS(AllSameQuadPredicate);
  IMP_OBJECT_METHODS(AllSameQuadPredicate);
};

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

 public:
  CoinFlipQuadPredicate(double p, std::string name =
                                           "CoinFlipQuadPredicate%1%");
  virtual int get_value_index(Model *, const ParticleIndexQuad&) 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_QUAD_PREDICATE_METHODS(CoinFlipQuadPredicate);
  IMP_OBJECT_METHODS(CoinFlipQuadPredicate);
};

IMPCORE_END_NAMESPACE

#endif /* IMPCORE_QUAD_PREDICATES_H */
