HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Expression template to compute the Euclidean distance

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
expressiontemplatethecomputeeuclideandistance

Problem

I was writing some geometry-related code again and had a closer look at my function supposed to compute the Euclidean distance between two points (N-dimensional points by the way, hence the N template parameter). Here is a simplified version:

template
auto distance(const Point& lhs, const Point& rhs)
    -> T
{
    T res{};
    for (std::size_t i = 0 ; i < N ; ++i)
    {
        auto tmp = std::abs(lhs[i] - rhs[i]);
        res += tmp * tmp;
    }
    return std::sqrt(res);
}


So far, so good. However, one very common operation is to compare the distances. Generally speaking, when comparing the distances, the sqrt is optimized away and the sum of the squares is compared instead of the distance itself. Therefore, I tried to create some kind of expression template to represent the distance between two points, so that users will benefit from both the ease of use and the "get rid of sqrt optimization" when comparing distances. Basically, the call of sqrt is not done until the exact value of the distance is needed. Here is the class:

template
struct DistanceExpression
{
    explicit constexpr DistanceExpression(T data):
        _data(data)
    {}

    operator T() const
    {
        return std::sqrt(_data);
    }

    bool operator==(const DistanceExpression& other) const
    {
        return _data == other._data;
    }

    bool operator!=(const DistanceExpression& other) const
    {
        return !(*this == other);
    }

private:

    T _data;
};


My new distance function is implemented as such:

template
auto distance(const Point& lhs, const Point& rhs)
    -> DistanceExpression
{
    T res{};
    for (std::size_t i = 0 ; i {res};
}


Here is a minimal working code at Coliru. Is such a design reasonable or is it overkill to elegantly solve this problem?

Solution

My concern now is that you make multiple calls to get the actual distance.

Every-time you do that then you incur the expense of the sqrt() operation.

I suppose it depends on the exact use case of your application which happens more often. But if this is for general code that could be used a lot in either capacity. I would add another two fields to indicate if it was dirty or not and cache the result so you don't have to recompute the actual value each time.

But that has the side affect of adding a conditional branch into the get which can also be expensive when looking at micro optimizations.

Context

StackExchange Code Review Q#44589, answer score: 8

Revisions (0)

No revisions yet.