<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2022 <NAME>, <NAME>, <NAME>

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA



#ifndef LIBMESH_INT_RANGE_H
#define LIBMESH_INT_RANGE_H

#include "libmesh/libmesh_common.h" // cast_int

// C++ includes
#include <vector>

namespace libMesh
{

// Forward declarations
template <typename T> class DenseSubVector;
template <typename T> class DenseVector;
template <typename T> class NumericVector;

/**
 * The \p IntRange templated class is intended to make it easy to
 * loop over integers which are indices of a container.
 *
 * In cases where such a range is defined by the result of a virtual
 * function call, this allows range-based for loops to be easily
 * written which make only a single such call, rather than a new call
 * for each iteration.
 *
 * We perform a cast_int operation (no-op in opt mode, test+assert in
 * debug) at construction time to make sure that the given range
 * bounds are representable by the given range type.
 *
 * \author  <NAME>
 */

template <typename T>
class IntRange
{
public:
  class iterator {
  public:
    iterator (T i) : _i(i) {}

    T operator* () const { return _i; }

    const iterator & operator++ () {
      ++_i;
      return *this;
    }

    iterator operator++ (int) {
      iterator returnval(*this);
      ++_i;
      return returnval;
    }

    bool operator== (const iterator & j) const {
      return ( _i == j._i );
    }

    bool operator!= (const iterator & j) const {
      return !(*this == j);
    }

  private:
    T _i;
  };

  template <typename U, typename V>
  IntRange(U begin, V end) :
    _begin(cast_int<T>(begin)),
    _end(cast_int<T>(end))
  {}

  iterator begin() const { return _begin; }

  iterator end () const { return _end; }

private:
  iterator _begin, _end;
};



/**
 * Helper function that returns an IntRange<std::size_t> representing
 * all the indices of the passed-in vector.
 */
template <typename T>
IntRange<std::size_t> index_range(const std::vector<T> & vec)
{
  return IntRange<std::size_t>(0, vec.size());
}


/**
 * Same thing but for DenseVector
 */
template <typename T>
IntRange<unsigned int> index_range(const DenseVector<T> & vec)
{
  return {0, vec.size()};
}


/**
 * Same thing but for DenseSubVector
 */
template <typename T>
IntRange<unsigned int> index_range(const DenseSubVector<T> & vec)
{
  return {0, vec.size()};
}



/**
 * Same thing but for NumericVector. Returns a range (first_local_index, last_local_index).
 */
template <typename T>
IntRange<numeric_index_type> index_range(const NumericVector<T> & vec)
{
  return {vec.first_local_index(), vec.last_local_index()};
}



/**
 * The 2-parameter make_range() helper function returns an IntRange<T>
 * when both input parameters are of type T. This saves a bit of
 * typing over calling the IntRange<T> constructor directly.
 */
template <typename T>
IntRange<T> make_range(T beg, T end)
{
  return {beg, end};
}



/**
 * The 1-parameter version of make_range() saves even more typing in
 * the common case of a 0 starting point. Example usage:
 *
 * for (auto i : make_range(10))<commit_msg>More generic index_range (#3377)<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2022 <NAME>, <NAME>, <NAME>

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA



#ifndef LIBMESH_INT_RANGE_H
#define LIBMESH_INT_RANGE_H

#include "libmesh/libmesh_common.h" // cast_int

// C++ includes
#include <vector>

namespace libMesh
{

// Forward declarations
template <typename T> class DenseSubVector;
template <typename T> class DenseVector;
template <typename T> class NumericVector;

/**
 * The \p IntRange templated class is intended to make it easy to
 * loop over integers which are indices of a container.
 *
 * In cases where such a range is defined by the result of a virtual
 * function call, this allows range-based for loops to be easily
 * written which make only a single such call, rather than a new call
 * for each iteration.
 *
 * We perform a cast_int operation (no-op in opt mode, test+assert in
 * debug) at construction time to make sure that the given range
 * bounds are representable by the given range type.
 *
 * \author  <NAME>
 */

template <typename T>
class IntRange
{
public:
  class iterator {
  public:
    iterator (T i) : _i(i) {}

    T operator* () const { return _i; }

    const iterator & operator++ () {
      ++_i;
      return *this;
    }

    iterator operator++ (int) {
      iterator returnval(*this);
      ++_i;
      return returnval;
    }

    bool operator== (const iterator & j) const {
      return ( _i == j._i );
    }

    bool operator!= (const iterator & j) const {
      return !(*this == j);
    }

  private:
    T _i;
  };

  template <typename U, typename V>
  IntRange(U begin, V end) :
    _begin(cast_int<T>(begin)),
    _end(cast_int<T>(end))
  {}

  iterator begin() const { return _begin; }

  iterator end () const { return _end; }

private:
  iterator _begin, _end;
};



/**
 * Helper function that returns an IntRange<std::size_t> representing
 * all the indices of the passed-in vector-like object (i.e. any type that
 * has a size() member).
 */
template <typename T>
auto index_range(const T & sizable)
{
  return IntRange<decltype(sizable.size())>(0, sizable.size());
}


/**
 * Same thing but for NumericVector. Returns a range (first_local_index, last_local_index).
 */
template <typename T>
IntRange<numeric_index_type> index_range(const NumericVector<T> & vec)
{
  return {vec.first_local_index(), vec.last_local_index()};
}



/**
 * The 2-parameter make_range() helper function returns an IntRange<T>
 * when both input parameters are of type T. This saves a bit of
 * typing over calling the IntRange<T> constructor directly.
 */
template <typename T>
IntRange<T> make_range(T beg, T end)
{
  return {beg, end};
}



/**
 * The 1-parameter version of make_range() saves even more typing in
 * the common case of a 0 starting point. Example usage:
 *
 * for (auto i : make_range(10))
{'fraction_non_alphanumeric': 0.10304259634888438, 'fraction_numerical': 0.008924949290060852, 'mean_word_length': 3.5042630937880634, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4593522', 'n_tokens_mistral': 2287, 'n_tokens_neox': 2193, 'n_words': 915}