product_distance.h

Back to Distances

pastel/math/distance/

// Description: Product distance
// Documentation: distances.txt

#ifndef PASTELMATH_PRODUCT_DISTANCE_H
#define PASTELMATH_PRODUCT_DISTANCE_H

#include "pastel/sys/mytypes.h"
#include "pastel/math/distance/distance_concept.h"
#include "pastel/math/distance/distance_base.h"

#include <algorithm>

namespace Pastel
{

    template <
        typename Real,
        typename XDistance,
        typename YDistance
    >
    class Product_Distance
    : public DistanceBase<Product_Distance<Real, XDistance, YDistance>, Real>
    {
    public:
        using Real_ = Real;

        explicit Product_Distance(integer nx = 0)
        : nx_(nx)
        , x_()
        , y_()
        {}

        explicit Product_Distance(const Real& y)
        : nx_(0)
        , x_()
        , y_(y)
        {}

        Product_Distance(
            integer nx,
            const XDistance& x, 
            const YDistance& y)
        : nx_(nx)
        , x_(x)
        , y_(y)
        {}

        Product_Distance(Distance_Native, const Real& y)
        : nx_(0)
        , x_()
        , y_(abs(y))
        {}

        Product_Distance(const Product_Distance&) = default;
        Product_Distance(Product_Distance&&) = default;
        Product_Distance& operator=(const Product_Distance&) = default;

        explicit operator Real() const {
            using std::max;
            return max((Real)x_, (Real)y_);
        }

        Real operator~() const {
            using std::max;
            return max(~x_, ~y_);
        }

        decltype(auto) replace(integer axis, const Real& from, const Real& to) {
            if (axis < nx_)
                x_.replace(axis, from, to);
            else
                y_.replace(axis - nx_, from, to);
            return *this;
        }

        decltype(auto) operator*=(const Real& amount) {
            x_ *= amount;
            y_ *= amount;
            return *this;
        }

        const XDistance& x() const {
            return x_;
        }

        const XDistance& y() const {
            return y_;
        }

    private:
        integer nx_;
        XDistance x_;
        YDistance y_;
    };

    template <
        typename Real,
        typename... Args
    >
    auto productDistance(Args&&... args)
    {
        return Product_Distance<Real, Args...>(std::forward<Args>(args)...);
    }

}

#endif