Maxime Charrière
Maxime Charrière

Reputation: 775

Does Eigen have arange function like numpy.arange() in Python

Do you know if Eigen has its own arange function, and if not, why?

For now, I have written my own arange function using Eigen::VectorXd::LinSpaced()

/*
* Return evenly spaced values within a given interval.  
* Values are generated within the half-open interval [start, stop) 
* (in other words, the interval including start but excluding stop).
*/
template <typename Scalar>
Eigen::VectorXd arange(const Scalar start, const Scalar stop, const Scalar step) {
  if(step == 0)
    throw std::domain_error("Arange's step cannot be 0");
  Scalar delta = stop - start;
  size_t size = ceil(delta / step);
  return Eigen::VectorXd::LinSpaced(size, start, start+(size-1)*step);
}

Upvotes: 0

Views: 1121

Answers (3)

Buzz
Buzz

Reputation: 1422

Easier implementation from previous answers: calculate N and then use Eigen::LinSpaced:

typedef Eigen::VectorXd vec;

vec arange(double low, double high, double step, bool with_last = false)
{
    high -= (with_last) ? 0 : step;
    int N = static_cast<int>(std::floor((high - low) / step) + 1);
    return vec::LinSpaced(N, low, high);
}

You can then enhance with some validity check over the parameters passed

Upvotes: 0

dvorak4tzx
dvorak4tzx

Reputation: 543

A dummy implementation:

Eigen::VectorXd arange(double low, double high, double step, bool with_last=false)
{
    int N = static_cast<int>(std::floor((high - low) / step) + 1);
    Eigen::VectorXi V(N);
    std::iota(V.data(), V.data() + N, 0);
    Eigen::VectorXd ret = V.cast<double>();
    ret.array() *= step;
    ret.array() += low;
    if (with_last && ret[N - 1] != high) {
        ret.conservativeResize(N + 1);
        ret[N] = high;
    }
    return ret;
}

test:

ASSERT_EQ(arange(0, 1, 0.25), (Eigen::VectorXd(4) << 0, 0.25, 0.5, 0.75, 1.0).finished());
ASSERT_EQ(arange(0, 1, 0.25 - 1e-3).size(), 5);
ASSERT_EQ(arange(0, 1, 0.25 - 1e-3, true).size(), 6);
ASSERT_EQ(arange(1, 0, -0.25), (Eigen::VectorXd(4) << 1, 0.75, 0.5, 0.25, 0.0).finished());

Upvotes: 0

J&#233;r&#244;me Richard
J&#233;r&#244;me Richard

Reputation: 50826

There is indeed LinSpaced currently available for such an operation, but apparently no direct equivalent of arange in Eigen. There are working notes related to this (eg. range and iota) but so far nothing appear to be included in the code for that. In the new Eigen 3.4 with a recent C++ version, you can use std::iota since Eigen now support STL iterators. Thus, there is no real need for a feature like arange to be added in Eigen (in fact LinSpaced is often good enough for most users).

Upvotes: 1

Related Questions