point_dimension.h

Back to Point

pastel/sys/point/

// Description: Dimension of a point
// DocumentationOf: point_concept.h

#ifndef PASTELSYS_POINT_DIMENSION_H
#define PASTELSYS_POINT_DIMENSION_H

#include "pastel/sys/point/point_concept.h"
#include "pastel/sys/real/real_ring_concept.h"
#include <array>

namespace Pastel
{

    // Dimension by having member .pointDimension().

    template <typename T>
    concept Point_HasMemberDimension__ = requires(T t) {
        {t.pointDimension()} -> std::convertible_to<integer>;
    };

    template <typename T>
    concept Point_HasMemberDimension_ = 
        Point_HasMemberDimension__<RemoveCvRef<T>>;

    template <typename Type>
    using Point_HasMemberDimension = 
        std::bool_constant<Point_HasMemberDimension_<Type>>;

    template <Point_HasMemberDimension_ Point>
    decltype(auto) dimension(Point&& point)
    {
        return std::forward<Point>(point).pointDimension();
    }

}

namespace Pastel
{

    // Dimension by having member .size().

    template <typename T>
    concept Point_HasMemberSize__ = requires(T t) {
        {addConst(t).size()} -> std::convertible_to<integer>;
    };

    template <typename T>
    concept Point_HasMemberSize_ = 
        Point_HasMemberSize__<RemoveCvRef<T>>;

    template <typename Type>
    using Point_HasMemberSize = 
        std::bool_constant<Point_HasMemberSize_<Type>>;

    template <Point_HasMemberSize_ Point>
    requires (!Point_HasMemberDimension<Point>::value)
    integer dimension(const Point& point)
    {
        return point.size();
    }

}

namespace Pastel
{

    // Dimension by being a number.

    template <Real_Ring_Concept Point>
    requires
        (!Point_HasMemberSize<Point>::value &&
        !Point_HasMemberDimension<Point>::value)
    integer dimension(const Point& point)
    {
        return 1;
    }

}

namespace Pastel
{

    template <Real_Ring_Concept Point>
    IntegerConstant<1> pointN(const Point* point);

    template <typename Real, std::size_t N>
    IntegerConstant<N> pointN(const std::array<Real, N>* point);

    namespace Point_
    {

        template <
            typename Type,
            typename Result = decltype(pointN((const Type*)nullptr))>
        struct Point_N_ 
        {
            using type = Result;
        };

    }

    template <typename Point>
    using Point_N = typename Compute<IntegerConstant<Dynamic>, Point_::Point_N_, Point>::type;

}

namespace Pastel
{

    template <typename Point>
    using Point_Dimension = 
        Point_N<Point>;

}

#endif