// Copyright (C) 2007 Trustees of Indiana University

// Authors: Douglas Gregor
//          Andrew Lumsdaine

// 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)

/** @file group.hpp
 *
 *  This header defines the @c group class, which allows one to
 *  manipulate and query groups of processes.
 */
#ifndef BOOST_MPI_GROUP_HPP
#define BOOST_MPI_GROUP_HPP

#include <boost/mpi/exception.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
#include <vector>

namespace boost { namespace mpi {

/**
 * @brief A @c group is a representation of a subset of the processes
 * within a @c communicator.
 *
 * The @c group class allows one to create arbitrary subsets of the
 * processes within a communicator. One can compute the union,
 * intersection, or difference of two groups, or create new groups by
 * specifically including or excluding certain processes. Given a
 * group, one can create a new communicator containing only the
 * processes in that group.
 */
class BOOST_MPI_DECL group
{
public:
  /**
   * @brief Constructs an empty group.
   */
  group() : group_ptr() { }

  /**
   * @brief Constructs a group from an @c MPI_Group.
   *
   * This routine allows one to construct a Boost.MPI @c group from a
   * C @c MPI_Group. The @c group object can (optionally) adopt the @c
   * MPI_Group, after which point the @c group object becomes
   * responsible for freeing the @c MPI_Group when the last copy of @c
   * group disappears.
   *
   * @param in_group The @c MPI_Group used to construct this @c group.
   *
   * @param adopt Whether the @c group should adopt the @c
   * MPI_Group. When true, the @c group object (or one of its copies)
   * will free the group (via @c MPI_Comm_free) when the last copy is
   * destroyed. Otherwise, the user is responsible for calling @c
   * MPI_Group_free.
   */
  group(const MPI_Group& in_group, bool adopt);

  /**
   * @brief Determine the rank of the calling process in the group.
   * 
   * This routine is equivalent to @c MPI_Group_rank.
   *
   * @returns The rank of the calling process in the group, which will
   * be a value in [0, size()). If the calling process is not in the
   * group, returns an empty value.
   */
  optional<int> rank() const;

  /**
   * @brief Determine the number of processes in the group.
   *
   * This routine is equivalent to @c MPI_Group_size.
   *
   * @returns The number of processes in the group.
   */
  int size() const;

  /**
   * @brief Translates the ranks from one group into the ranks of the
   * same processes in another group.
   *
   * This routine translates each of the integer rank values in the
   * iterator range @c [first, last) from the current group into rank
   * values of the corresponding processes in @p to_group. The
   * corresponding rank values are written via the output iterator @c
   * out. When there is no correspondence between a rank in the
   * current group and a rank in @c to_group, the value @c
   * MPI_UNDEFINED is written to the output iterator.
   *
   * @param first Beginning of the iterator range of ranks in the
   * current group.
   *
   * @param last Past the end of the iterator range of ranks in the
   * current group.
   *
   * @param to_group The group that we are translating ranks to.
   *
   * @param out The output iterator to which the translated ranks will
   * be written.
   *
   * @returns the output iterator, which points one step past the last
   * rank written.
   */
  template<typename InputIterator, typename OutputIterator>
  OutputIterator translate_ranks(InputIterator first, InputIterator last,
                                 const group& to_group, OutputIterator out);

  /**
   * @brief Determines whether the group is non-empty.
   *
   * @returns True if the group is not empty, false if it is empty.
   */
  operator bool() const { return (bool)group_ptr; }

  /**
   * @brief Retrieves the underlying @c MPI_Group associated with this
   * group.
   *
   * @returns The @c MPI_Group handle manipulated by this object. If
   * this object represents the empty group, returns @c
   * MPI_GROUP_EMPTY.
   */
  operator MPI_Group() const
  {
    if (group_ptr)
      return *group_ptr;
    else
      return MPI_GROUP_EMPTY;
  }

  /**
   *  @brief Creates a new group including a subset of the processes
   *  in the current group.
   *
   *  This routine creates a new @c group which includes only those
   *  processes in the current group that are listed in the integer
   *  iterator range @c [first, last). Equivalent to @c
   *  MPI_Group_incl.
   *
   *  @c first The beginning of the iterator range of ranks to include.
   *
   *  @c last Past the end of the iterator range of ranks to include.
   *
   *  @returns A new group containing those processes with ranks @c
   *  [first, last) in the current group.
   */
  template<typename InputIterator>
  group include(InputIterator first, InputIterator last);

  /**
   *  @brief Creates a new group from all of the processes in the
   *  current group, exluding a specific subset of the processes.
   *
   *  This routine creates a new @c group which includes all of the
   *  processes in the current group except those whose ranks are
   *  listed in the integer iterator range @c [first,
   *  last). Equivalent to @c MPI_Group_excl.
   *
   *  @c first The beginning of the iterator range of ranks to exclude.
   *
   *  @c last Past the end of the iterator range of ranks to exclude.
   *
   *  @returns A new group containing all of the processes in the
   *  current group except those processes with ranks @c [first, last)
   *  in the current group. 
   */
  template<typename InputIterator>
  group exclude(InputIterator first, InputIterator last);
  

protected:
  /**
   * INTERNAL ONLY
   *
   * Function object that frees an MPI group and deletes the
   * memory associated with it. Intended to be used as a deleter with
   * shared_ptr.
   */
  struct group_free
  {
    void operator()(MPI_Group* comm) const
    {
      int finalized;
      BOOST_MPI_CHECK_RESULT(MPI_Finalized, (&finalized));
      if (!finalized)
        BOOST_MPI_CHECK_RESULT(MPI_Group_free, (comm));
      delete comm;
    }
  };

  /**
   * The underlying MPI group. This is a shared pointer, so the actual
   * MPI group which will be shared among all related instances of the
   * @c group class. When there are no more such instances, the group
   * will be automatically freed.
   */
  shared_ptr<MPI_Group> group_ptr;
};

/**
 * @brief Determines whether two process groups are identical.
 *
 * Equivalent to calling @c MPI_Group_compare and checking whether the
 * result is @c MPI_IDENT.
 *
 * @returns True when the two process groups contain the same
 * processes in the same order.
 */
BOOST_MPI_DECL bool operator==(const group& g1, const group& g2);

/**
 * @brief Determines whether two process groups are not identical.
 *
 * Equivalent to calling @c MPI_Group_compare and checking whether the
 * result is not @c MPI_IDENT.
 *
 * @returns False when the two process groups contain the same
 * processes in the same order.
 */
inline bool operator!=(const group& g1, const group& g2)
{ 
  return !(g1 == g2);
}

/**
 * @brief Computes the union of two process groups.
 *
 * This routine returns a new @c group that contains all processes
 * that are either in group @c g1 or in group @c g2 (or both). The
 * processes that are in @c g1 will be first in the resulting group,
 * followed by the processes from @c g2 (but not also in @c
 * g1). Equivalent to @c MPI_Group_union.
 */
BOOST_MPI_DECL group operator|(const group& g1, const group& g2);

/**
 * @brief Computes the intersection of two process groups.
 *
 * This routine returns a new @c group that contains all processes
 * that are in group @c g1 and in group @c g2, ordered in the same way
 * as @c g1. Equivalent to @c MPI_Group_intersection.
 */
BOOST_MPI_DECL group operator&(const group& g1, const group& g2);

/**
 * @brief Computes the difference between two process groups.
 *
 * This routine returns a new @c group that contains all processes
 * that are in group @c g1 but not in group @c g2, ordered in the same way
 * as @c g1. Equivalent to @c MPI_Group_difference.
 */
BOOST_MPI_DECL group operator-(const group& g1, const group& g2);

/************************************************************************
 * Implementation details                                               *
 ************************************************************************/
template<typename InputIterator, typename OutputIterator>
OutputIterator 
group::translate_ranks(InputIterator first, InputIterator last,
                       const group& to_group, OutputIterator out)
{
  std::vector<int> in_array(first, last);
  if (in_array.empty())
    return out;

  std::vector<int> out_array(in_array.size());
  BOOST_MPI_CHECK_RESULT(MPI_Group_translate_ranks,
                         ((MPI_Group)*this,
                          in_array.size(),
                          &in_array[0],
                          (MPI_Group)to_group,
                          &out_array[0]));

  for (std::vector<int>::size_type i = 0, n = out_array.size(); i < n; ++i)
    *out++ = out_array[i];
  return out;
}

/**
 * INTERNAL ONLY
 * 
 * Specialization of translate_ranks that handles the one case where
 * we can avoid any memory allocation or copying.
 */
template<> 
BOOST_MPI_DECL int*
group::translate_ranks(int* first, int* last, const group& to_group, int* out);

template<typename InputIterator>
group group::include(InputIterator first, InputIterator last)
{
  if (first == last)
    return group();

  std::vector<int> ranks(first, last);
  MPI_Group result;
  BOOST_MPI_CHECK_RESULT(MPI_Group_incl,
                         ((MPI_Group)*this, ranks.size(), &ranks[0], &result));
  return group(result, /*adopt=*/true);
}

/**
 * INTERNAL ONLY
 * 
 * Specialization of group::include that handles the one case where we
 * can avoid any memory allocation or copying before creating the
 * group.
 */
template<> BOOST_MPI_DECL group group::include(int* first, int* last);

template<typename InputIterator>
group group::exclude(InputIterator first, InputIterator last)
{
  if (first == last)
    return group();

  std::vector<int> ranks(first, last);
  MPI_Group result;
  BOOST_MPI_CHECK_RESULT(MPI_Group_excl,
                         ((MPI_Group)*this, ranks.size(), &ranks[0], &result));
  return group(result, /*adopt=*/true);
}

/**
 * INTERNAL ONLY
 * 
 * Specialization of group::exclude that handles the one case where we
 * can avoid any memory allocation or copying before creating the
 * group.
 */
template<> BOOST_MPI_DECL group group::exclude(int* first, int* last);

} } // end namespace boost::mpi

#endif // BOOST_MPI_GROUP_HPP
