00001 #ifndef CCTBX_MATH_LOOP_N_FROM_M_H
00002 #define CCTBX_MATH_LOOP_N_FROM_M_H
00003
00004 #include <algorithm>
00005 #include <cstddef>
00006 #include <cctbx/error.h>
00007
00008 namespace cctbx { namespace math {
00009
00010 template <std::size_t MaxN>
00011 class loop_n_from_m
00012 {
00013 public:
00014 loop_n_from_m()
00015 : m_(0), n_(0), over_(1)
00016 {}
00017
00018 loop_n_from_m(std::size_t m, std::size_t n)
00019 : m_(m), n_(n), over_(0)
00020 {
00021 CCTBX_ASSERT(m_ >= n_);
00022 CCTBX_ASSERT(MaxN >= n_);
00023 for(std::size_t i=0;i<n_;i++) current_[i] = i;
00024 }
00025
00026 bool incr()
00027 {
00028 if (n_ > 0) {
00029 std::size_t p, l;
00030 p = l = n_ - 1;
00031 for (;;) {
00032 current_[p]++;
00033 if (current_[p] + l == m_ + p) {
00034 if (p == 0) break;
00035 p--;
00036 }
00037 else if (p < l) {
00038 current_[p + 1] = current_[p];
00039 p++;
00040 }
00041 else {
00042 return true;
00043 }
00044 }
00045 }
00046 over_++;
00047 return false;
00048 }
00049
00050 std::size_t m() const { return m_; }
00051
00052 std::size_t n() const { return n_; }
00053
00054 std::size_t operator[](std::size_t i) const { return current_[i]; }
00055
00056 std::size_t over() const { return over_; }
00057
00058 protected:
00059 std::size_t m_;
00060 std::size_t n_;
00061 std::size_t current_[MaxN];
00062 std::size_t over_;
00063 };
00064
00065 }}
00066
00067 #endif // CCTBX_MATH_LOOP_N_FROM_M_H