// 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