Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
#define BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED("<boost/geometry/util/type_traits.hpp>")
#include <boost/geometry/util/type_traits.hpp>
#endif // BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
+287
View File
@@ -0,0 +1,287 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
#define BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// Other implementations can be found in the history of this file.
// The discussion and benchmarks can be found here:
// https://github.com/boostorg/geometry/pull/827
// O(logN) version 2
template <std::size_t N>
struct for_each_index_impl2
{
static const std::size_t N1 = N / 2;
static const std::size_t N2 = N - N1;
template <std::size_t Offset, typename UnaryFunction>
constexpr static inline void apply(UnaryFunction& function)
{
for_each_index_impl2<N1>::template apply<Offset>(function);
for_each_index_impl2<N2>::template apply<Offset + N1>(function);
}
};
template <>
struct for_each_index_impl2<3>
{
template <std::size_t Offset, typename UnaryFunction>
constexpr static inline void apply(UnaryFunction& function)
{
function(util::index_constant<Offset>());
function(util::index_constant<Offset + 1>());
function(util::index_constant<Offset + 2>());
}
};
template <>
struct for_each_index_impl2<2>
{
template <std::size_t Offset, typename UnaryFunction>
constexpr static inline void apply(UnaryFunction& function)
{
function(util::index_constant<Offset>());
function(util::index_constant<Offset + 1>());
}
};
template <>
struct for_each_index_impl2<1>
{
template <std::size_t Offset, typename UnaryFunction>
constexpr static inline void apply(UnaryFunction& function)
{
function(util::index_constant<Offset>());
}
};
template <>
struct for_each_index_impl2<0>
{
template <std::size_t Offset, typename UnaryFunction>
constexpr static inline void apply(UnaryFunction& )
{}
};
// Interface
template <std::size_t N, typename UnaryFunction>
constexpr inline UnaryFunction for_each_index(UnaryFunction function)
{
for_each_index_impl2
<
N
>::template apply<0>(function);
return function;
}
template <typename Geometry, typename UnaryFunction>
constexpr inline UnaryFunction for_each_dimension(UnaryFunction function)
{
for_each_index_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(function);
return function;
}
// ----------------------------------------------------------------------------
// O(logN) version 2
template <std::size_t N>
struct all_indexes_of_impl2
{
static const std::size_t N1 = N / 2;
static const std::size_t N2 = N - N1;
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return all_indexes_of_impl2<N1>::template apply<Offset>(predicate)
&& all_indexes_of_impl2<N2>::template apply<Offset + N1>(predicate);
}
};
template <>
struct all_indexes_of_impl2<3>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
&& predicate(util::index_constant<Offset + 1>())
&& predicate(util::index_constant<Offset + 2>());
}
};
template <>
struct all_indexes_of_impl2<2>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
&& predicate(util::index_constant<Offset + 1>());
}
};
template <>
struct all_indexes_of_impl2<1>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>());
}
};
template <>
struct all_indexes_of_impl2<0>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& )
{
return true;
}
};
// Interface
template <std::size_t N, typename UnaryPredicate>
constexpr inline bool all_indexes_of(UnaryPredicate predicate)
{
return all_indexes_of_impl2<N>::template apply<0>(predicate);
}
template <typename Geometry, typename UnaryPredicate>
constexpr inline bool all_dimensions_of(UnaryPredicate predicate)
{
return all_indexes_of_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(predicate);
}
// ----------------------------------------------------------------------------
// O(logN) version 2
template <std::size_t N>
struct any_index_of_impl2
{
static const std::size_t N1 = N / 2;
static const std::size_t N2 = N - N1;
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return any_index_of_impl2<N1>::template apply<Offset>(predicate)
|| any_index_of_impl2<N2>::template apply<Offset + N1>(predicate);
}
};
template <>
struct any_index_of_impl2<3>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
|| predicate(util::index_constant<Offset + 1>())
|| predicate(util::index_constant<Offset + 2>());
}
};
template <>
struct any_index_of_impl2<2>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>())
|| predicate(util::index_constant<Offset + 1>());
}
};
template <>
struct any_index_of_impl2<1>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& predicate)
{
return predicate(util::index_constant<Offset>());
}
};
template <>
struct any_index_of_impl2<0>
{
template <std::size_t Offset, typename UnaryPredicate>
constexpr static inline bool apply(UnaryPredicate& )
{
return false;
}
};
// Interface
template <std::size_t N, typename UnaryPredicate>
constexpr inline bool any_index_of(UnaryPredicate predicate)
{
return any_index_of_impl2<N>::template apply<0>(predicate);
}
template <typename Geometry, typename UnaryPredicate>
constexpr inline bool any_dimension_of(UnaryPredicate predicate)
{
return any_index_of_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(predicate);
}
template <std::size_t N, typename UnaryPredicate>
constexpr inline bool none_index_of(UnaryPredicate predicate)
{
return ! any_index_of_impl2<N>::template apply<0>(predicate);
}
template <typename Geometry, typename UnaryPredicate>
constexpr inline bool none_dimension_of(UnaryPredicate predicate)
{
return ! any_index_of_impl2
<
geometry::dimension<Geometry>::value
>::template apply<0>(predicate);
}
// ----------------------------------------------------------------------------
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_ALGORITHM_HPP
+25
View File
@@ -0,0 +1,25 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2012 Bruno Lalande, Paris, France.
// Copyright (c) 2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED("<boost/geometry/util/type_traits.hpp>")
#include <boost/geometry/util/type_traits.hpp>
#endif // BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
+176
View File
@@ -0,0 +1,176 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2012 Bruno Lalande, Paris, France.
// Copyright (c) 2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
#include <boost/static_assert.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace util
{
namespace detail
{
struct default_integral
{
typedef long long type;
};
/*!
\details Selects the most appropriate:
- if calculation type is specified (not void), that one is used
- else if type is non-fundamental (user defined e.g. Boost.Multiprecision), that one
- else if type is floating point, the specified default FP is used
- else it is integral and the specified default integral is used
*/
template
<
typename Type,
typename CalculationType,
typename DefaultFloatingPointCalculationType,
typename DefaultIntegralCalculationType
>
struct calculation_type
{
BOOST_STATIC_ASSERT((
std::is_fundamental
<
DefaultFloatingPointCalculationType
>::value
));
BOOST_STATIC_ASSERT((
std::is_fundamental
<
DefaultIntegralCalculationType
>::value
));
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
std::conditional_t
<
std::is_floating_point<Type>::value,
typename select_most_precise
<
DefaultFloatingPointCalculationType,
Type
>::type,
typename select_most_precise
<
DefaultIntegralCalculationType,
Type
>::type
>,
CalculationType
> type;
};
} // namespace detail
namespace calculation_type
{
namespace geometric
{
template
<
typename Geometry,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct unary
{
typedef typename detail::calculation_type
<
typename geometry::coordinate_type<Geometry>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
template
<
typename Geometry1,
typename Geometry2,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct binary
{
typedef typename detail::calculation_type
<
typename select_coordinate_type<Geometry1, Geometry2>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
/*!
\brief calculation type (ternary, for three geometry types)
*/
template
<
typename Geometry1,
typename Geometry2,
typename Geometry3,
typename CalculationType,
typename DefaultFloatingPointCalculationType = double,
typename DefaultIntegralCalculationType = detail::default_integral::type
>
struct ternary
{
typedef typename detail::calculation_type
<
typename select_most_precise
<
typename coordinate_type<Geometry1>::type,
typename select_coordinate_type
<
Geometry2,
Geometry3
>::type
>::type,
CalculationType,
DefaultFloatingPointCalculationType,
DefaultIntegralCalculationType
>::type type;
};
}} // namespace calculation_type::geometric
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
+46
View File
@@ -0,0 +1,46 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
#define BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
#include <boost/geometry/core/closure.hpp>
namespace boost { namespace geometry
{
template<closure_selector Closure>
struct closure_as_bool
{};
template<>
struct closure_as_bool<closed>
{
static const bool value = true;
};
template<>
struct closure_as_bool<open>
{
static const bool value = false;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
+98
View File
@@ -0,0 +1,98 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2014-2015 Samuel Debionne, Grenoble, France.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP
#define BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_ALLOW_DEPRECATED_HEADERS)
BOOST_PRAGMA_MESSAGE("This header is deprecated.")
#endif
#include <boost/mpl/bind.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/set.hpp>
namespace boost { namespace geometry
{
namespace util
{
/*!
\brief Meta-function to generate all the combination of pairs of types
from a given sequence Sequence except those that does not satisfy the
predicate Pred
\ingroup utility
\par Example
\code
typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<1> > types;
typedef combine_if<types, types, always<true_> >::type combinations;
typedef boost::mpl::vector<
pair<boost::mpl::int_<1>, boost::mpl::int_<1> >,
pair<boost::mpl::int_<1>, boost::mpl::int_<0> >,
pair<boost::mpl::int_<0>, boost::mpl::int_<1> >,
pair<boost::mpl::int_<0>, boost::mpl::int_<0> >
> result_types;
BOOST_MPL_ASSERT(( boost::mpl::equal<combinations, result_types> ));
\endcode
*/
template <typename Sequence1, typename Sequence2, typename Pred>
struct combine_if
{
struct combine
{
template <typename Result, typename T>
struct apply
{
typedef typename boost::mpl::fold<Sequence2, Result,
boost::mpl::if_
<
boost::mpl::bind
<
typename boost::mpl::lambda<Pred>::type,
T,
boost::mpl::_2
>,
boost::mpl::insert
<
boost::mpl::_1, boost::mpl::pair<T, boost::mpl::_2>
>,
boost::mpl::_1
>
>::type type;
};
};
typedef typename boost::mpl::fold
<
Sequence1, boost::mpl::set0<>, combine
>::type type;
};
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_COMBINE_IF_HPP
+111
View File
@@ -0,0 +1,111 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP
#define BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_ALLOW_DEPRECATED_HEADERS)
BOOST_PRAGMA_MESSAGE("This header is deprecated.")
#endif
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/set.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/variant/variant_fwd.hpp>
namespace boost { namespace geometry
{
namespace detail
{
template <typename Variant>
struct unique_types:
boost::mpl::fold<
typename boost::mpl::reverse_fold<
typename Variant::types,
boost::mpl::set<>,
boost::mpl::insert<
boost::mpl::placeholders::_1,
boost::mpl::placeholders::_2
>
>::type,
boost::mpl::vector<>,
boost::mpl::push_back
<
boost::mpl::placeholders::_1, boost::mpl::placeholders::_2
>
>
{};
template <typename Types>
struct variant_or_single:
boost::mpl::if_<
boost::mpl::equal_to<
boost::mpl::size<Types>,
boost::mpl::int_<1>
>,
typename boost::mpl::front<Types>::type,
typename make_variant_over<Types>::type
>
{};
} // namespace detail
/*!
\brief Meta-function that takes a boost::variant type and tries to minimize
it by doing the following:
- if there's any duplicate types, remove them
- if the result is a variant of one type, turn it into just that type
\ingroup utility
\par Example
\code
typedef variant<int, float, int, long> variant_type;
typedef compress_variant<variant_type>::type compressed;
typedef boost::mpl::vector<int, float, long> result_types;
BOOST_MPL_ASSERT(( boost::mpl::equal<compressed::types, result_types> ));
typedef variant<int, int, int> one_type_variant_type;
typedef compress_variant<one_type_variant_type>::type single_type;
BOOST_MPL_ASSERT(( boost::equals<single_type, int> ));
\endcode
*/
template <typename Variant>
struct compress_variant:
detail::variant_or_single<
typename detail::unique_types<Variant>::type
>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_COMPRESS_VARIANT_HPP
+44
View File
@@ -0,0 +1,44 @@
// Boost.Geometry
// Copyright (c) 2015 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_CONDITION_HPP
#define BOOST_GEOMETRY_UTIL_CONDITION_HPP
#include <boost/config.hpp>
// The macro defined in this file allows to suppress the MSVC
// compiler warning C4127: conditional expression is constant
#ifdef BOOST_MSVC
// NOTE: The code commented out below contains an alternative implementation
// of a macro using a free function. It was left here in case if in the future
// version of MSVC for the code currently used in the macro implementation
// the warning was generated.
//#ifndef DOXYGEN_NO_DETAIL
//namespace boost { namespace geometry { namespace detail {
//BOOST_FORCEINLINE bool condition(bool const b) { return b; }
//}}} // boost::geometry::detail
//#endif // DOXYGEN_NO_DETAIL
//#define BOOST_GEOMETRY_CONDITION(CONDITION) boost::geometry::detail::condition(CONDITION)
#define BOOST_GEOMETRY_CONDITION(CONDITION) ((void)0, (CONDITION))
#else
#define BOOST_GEOMETRY_CONDITION(CONDITION) (CONDITION)
#endif
#endif // BOOST_GEOMETRY_UTIL_CONDITION_HPP
+27
View File
@@ -0,0 +1,27 @@
// Boost.Geometry
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_CONSTEXPR_HPP
#define BOOST_GEOMETRY_UTIL_CONSTEXPR_HPP
#include <boost/geometry/util/condition.hpp>
#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
#define BOOST_GEOMETRY_CONSTEXPR(CONDITION) constexpr (CONDITION)
#else
#define BOOST_GEOMETRY_CONSTEXPR(CONDITION) (BOOST_GEOMETRY_CONDITION(CONDITION))
#endif
#endif // BOOST_GEOMETRY_UTIL_CONSTEXPR_HPP
+54
View File
@@ -0,0 +1,54 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
#define BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
#include <cstdlib>
#include <string>
#include <boost/lexical_cast.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
/*!
\brief cast coordinates from a string to a coordinate type
\detail By default it uses lexical_cast. However, lexical_cast seems not to support
See also "define_pi" where the same issue is solved
*/
template <typename CoordinateType>
struct coordinate_cast
{
static inline CoordinateType apply(std::string const& source)
{
#if defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
return atof(source.c_str());
#else
return boost::lexical_cast<CoordinateType>(source);
#endif
}
};
} // namespace detail
#endif
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
+82
View File
@@ -0,0 +1,82 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
#include <boost/concept/requires.hpp>
#include <boost/geometry/geometries/concepts/point_concept.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename Point,
int Dimension = 0,
int DimensionCount = dimension<Point>::value
>
struct coordinates_scanner
{
template <typename Op>
static inline Op apply(Point& point, Op operation)
{
operation.template apply<Point, Dimension>(point);
return coordinates_scanner
<
Point,
Dimension + 1
>::apply(point, operation);
}
};
template <typename Point, int DimensionCount>
struct coordinates_scanner<Point, DimensionCount, DimensionCount>
{
template <typename Op>
static inline Op apply(Point& , Op operation)
{
return operation;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point, typename Op>
inline void for_each_coordinate(Point& point, Op operation)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
detail::coordinates_scanner<Point>::apply(point, operation);
}
template <typename Point, typename Op>
inline Op for_each_coordinate(Point const& point, Op operation)
{
BOOST_CONCEPT_ASSERT( (concepts::ConstPoint<Point>) );
return detail::coordinates_scanner<Point const>::apply(point, operation);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
+49
View File
@@ -0,0 +1,49 @@
// Boost.Geometry
// Copyright (c) 2023 Barend Gehrels, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
#define BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size_type.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// Utility function to implement a Kotlin like range based for loop
template <typename Container, typename Function>
inline void for_each_with_index(Container const& container, Function func)
{
typename boost::range_size<Container>::type index = 0;
for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
{
func(index, *it);
}
}
template <typename Container, typename Function>
inline void for_each_with_index(Container& container, Function func)
{
typename boost::range_size<Container>::type index = 0;
for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
{
func(index, *it);
}
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
+56
View File
@@ -0,0 +1,56 @@
// Boost.Geometry
// Copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP
#include <type_traits>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct isinf
{
template <typename T>
static inline bool apply(T const& t)
{
return boost::math::isinf(t);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point>
bool has_infinite_coordinate(Point const& point)
{
return detail::has_coordinate_with_property
<
Point,
detail::isinf,
std::is_floating_point
<
typename coordinate_type<Point>::type
>::value
>::apply(point);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_HAS_INFINITE_COORDINATE_HPP
+98
View File
@@ -0,0 +1,98 @@
// Boost.Geometry
// Copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP
#include <cstddef>
#include <type_traits>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct isnan
{
template <typename T>
static inline bool apply(T const& t)
{
return boost::math::isnan(t);
}
};
template
<
typename Point,
typename Predicate,
bool Enable,
std::size_t I = 0,
std::size_t N = geometry::dimension<Point>::value
>
struct has_coordinate_with_property
{
static bool apply(Point const& point)
{
return Predicate::apply(geometry::get<I>(point))
|| has_coordinate_with_property
<
Point, Predicate, Enable, I+1, N
>::apply(point);
}
};
template <typename Point, typename Predicate, std::size_t I, std::size_t N>
struct has_coordinate_with_property<Point, Predicate, false, I, N>
{
static inline bool apply(Point const&)
{
return false;
}
};
template <typename Point, typename Predicate, std::size_t N>
struct has_coordinate_with_property<Point, Predicate, true, N, N>
{
static bool apply(Point const& )
{
return false;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point>
bool has_nan_coordinate(Point const& point)
{
return detail::has_coordinate_with_property
<
Point,
detail::isnan,
std::is_floating_point
<
typename coordinate_type<Point>::type
>::value
>::apply(point);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_HAS_NAN_COORDINATE_HPP
+56
View File
@@ -0,0 +1,56 @@
// Boost.Geometry
// Copyright (c) 2015-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP
#define BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP
#include <type_traits>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
struct is_not_finite
{
template <typename T>
static inline bool apply(T const& t)
{
return ! boost::math::isfinite(t);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Point>
bool has_non_finite_coordinate(Point const& point)
{
return detail::has_coordinate_with_property
<
Point,
detail::is_not_finite,
std::is_floating_point
<
typename coordinate_type<Point>::type
>::value
>::apply(point);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_HAS_NON_FINITE_COORDINATE_HPP
@@ -0,0 +1,48 @@
// Boost.Geometry
// Copyright (c) 2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP
#define BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
template<class CT>
struct bounds
{
static CT lowest () { return boost::numeric::bounds<CT>::lowest(); }
static CT highest () { return boost::numeric::bounds<CT>::highest(); }
};
template <typename Box>
bool is_inverse_spheroidal_coordinates(Box const& box)
{
typedef typename point_type<Box>::type point_type;
typedef typename coordinate_type<point_type>::type bound_type;
bound_type high = bounds<bound_type>::highest();
bound_type low = bounds<bound_type>::lowest();
return (geometry::get<0, 0>(box) == high) &&
(geometry::get<0, 1>(box) == high) &&
(geometry::get<1, 0>(box) == low) &&
(geometry::get<1, 1>(box) == low);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_IS_INVERSE_SPHEROIDAL_COORDINATES_HPP
+966
View File
@@ -0,0 +1,966 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2022.
// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
#define BOOST_GEOMETRY_UTIL_MATH_HPP
#include <cmath>
#include <limits>
#include <type_traits>
#include <boost/core/ignore_unused.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
//#include <boost/math/special_functions/round.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace math
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename T>
inline T const& greatest(T const& v1, T const& v2)
{
return (std::max)(v1, v2);
}
template <typename T>
inline T const& greatest(T const& v1, T const& v2, T const& v3)
{
return (std::max)(greatest(v1, v2), v3);
}
template <typename T>
inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4)
{
return (std::max)(greatest(v1, v2, v3), v4);
}
template <typename T>
inline T const& greatest(T const& v1, T const& v2, T const& v3, T const& v4, T const& v5)
{
return (std::max)(greatest(v1, v2, v3, v4), v5);
}
template <typename T>
inline T bounded(T const& v, T const& lower, T const& upper)
{
return (std::min)((std::max)(v, lower), upper);
}
template <typename T>
inline T bounded(T const& v, T const& lower)
{
return (std::max)(v, lower);
}
template <typename T,
bool IsFloatingPoint = std::is_floating_point<T>::value>
struct abs
{
static inline T apply(T const& value)
{
T const zero = T();
return value < zero ? -value : value;
}
};
template <typename T>
struct abs<T, true>
{
static inline T apply(T const& value)
{
using ::fabs;
using std::fabs; // for long double
return fabs(value);
}
};
struct equals_default_policy
{
template <typename T>
static inline T apply(T const& a, T const& b)
{
// See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
return greatest(abs<T>::apply(a), abs<T>::apply(b), T(1));
}
};
template <typename T,
bool IsFloatingPoint = std::is_floating_point<T>::value>
struct equals_factor_policy
{
equals_factor_policy()
: factor(1) {}
explicit equals_factor_policy(T const& v)
: factor(greatest(abs<T>::apply(v), T(1)))
{}
equals_factor_policy(T const& v0, T const& v1, T const& v2, T const& v3)
: factor(greatest(abs<T>::apply(v0), abs<T>::apply(v1),
abs<T>::apply(v2), abs<T>::apply(v3),
T(1)))
{}
T const& apply(T const&, T const&) const
{
return factor;
}
template <typename E>
void multiply_epsilon(E const& multiplier)
{
factor *= multiplier;
}
T factor;
};
template <typename T>
struct equals_factor_policy<T, false>
{
equals_factor_policy() {}
explicit equals_factor_policy(T const&) {}
equals_factor_policy(T const& , T const& , T const& , T const& ) {}
static inline T apply(T const&, T const&)
{
return T(1);
}
void multiply_epsilon(T const& ) {}
};
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct equals
{
template <typename Policy>
static inline bool apply(Type const& a, Type const& b, Policy const&)
{
return a == b;
}
};
template <typename Type>
struct equals<Type, true>
{
template <typename Policy>
static inline bool apply(Type const& a, Type const& b, Policy const& policy)
{
boost::ignore_unused(policy);
if (a == b)
{
return true;
}
if (boost::math::isfinite(a) && boost::math::isfinite(b))
{
// If a is INF and b is e.g. 0, the expression below returns true
// but the values are obviously not equal, hence the condition
return abs<Type>::apply(a - b)
<= std::numeric_limits<Type>::epsilon() * policy.apply(a, b);
}
else
{
return a == b;
}
}
};
template <typename T1, typename T2, typename Policy>
inline bool equals_by_policy(T1 const& a, T2 const& b, Policy const& policy)
{
return detail::equals
<
typename select_most_precise<T1, T2>::type
>::apply(a, b, policy);
}
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct smaller
{
static inline bool apply(Type const& a, Type const& b)
{
return a < b;
}
};
template <typename Type>
struct smaller<Type, true>
{
static inline bool apply(Type const& a, Type const& b)
{
if (!(a < b)) // a >= b
{
return false;
}
return ! equals<Type, true>::apply(b, a, equals_default_policy());
}
};
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct smaller_or_equals
{
static inline bool apply(Type const& a, Type const& b)
{
return a <= b;
}
};
template <typename Type>
struct smaller_or_equals<Type, true>
{
static inline bool apply(Type const& a, Type const& b)
{
if (a <= b)
{
return true;
}
return equals<Type, true>::apply(a, b, equals_default_policy());
}
};
template <typename Type,
bool IsFloatingPoint = std::is_floating_point<Type>::value>
struct equals_with_epsilon
: public equals<Type, IsFloatingPoint>
{};
template
<
typename T,
bool IsFundemantal = std::is_fundamental<T>::value /* false */
>
struct square_root
{
typedef T return_type;
static inline T apply(T const& value)
{
// for non-fundamental number types assume that sqrt is
// defined either:
// 1) at T's scope, or
// 2) at global scope, or
// 3) in namespace std
using ::sqrt;
using std::sqrt;
return sqrt(value);
}
};
template <typename FundamentalFP>
struct square_root_for_fundamental_fp
{
typedef FundamentalFP return_type;
static inline FundamentalFP apply(FundamentalFP const& value)
{
#ifdef BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
// This is a workaround for some 32-bit platforms.
// For some of those platforms it has been reported that
// std::sqrt(nan) and/or std::sqrt(-nan) returns a finite value.
// For those platforms we need to define the macro
// BOOST_GEOMETRY_SQRT_CHECK_FINITENESS so that the argument
// to std::sqrt is checked appropriately before passed to std::sqrt
if (boost::math::isfinite(value))
{
return std::sqrt(value);
}
else if (boost::math::isinf(value) && value < 0)
{
return -std::numeric_limits<FundamentalFP>::quiet_NaN();
}
return value;
#else
// for fundamental floating point numbers use std::sqrt
return std::sqrt(value);
#endif // BOOST_GEOMETRY_SQRT_CHECK_FINITENESS
}
};
template <>
struct square_root<float, true>
: square_root_for_fundamental_fp<float>
{
};
template <>
struct square_root<double, true>
: square_root_for_fundamental_fp<double>
{
};
template <>
struct square_root<long double, true>
: square_root_for_fundamental_fp<long double>
{
};
template <typename T>
struct square_root<T, true>
{
typedef double return_type;
static inline double apply(T const& value)
{
// for all other fundamental number types use also std::sqrt
//
// Note: in C++98 the only other possibility is double;
// in C++11 there are also overloads for integral types;
// this specialization works for those as well.
return square_root_for_fundamental_fp
<
double
>::apply(boost::numeric_cast<double>(value));
}
};
template
<
typename T,
bool IsFundemantal = std::is_fundamental<T>::value /* false */
>
struct modulo
{
typedef T return_type;
static inline T apply(T const& value1, T const& value2)
{
// for non-fundamental number types assume that a free
// function mod() is defined either:
// 1) at T's scope, or
// 2) at global scope
return mod(value1, value2);
}
};
template
<
typename Fundamental,
bool IsIntegral = std::is_integral<Fundamental>::value
>
struct modulo_for_fundamental
{
typedef Fundamental return_type;
static inline Fundamental apply(Fundamental const& value1,
Fundamental const& value2)
{
return value1 % value2;
}
};
// specialization for floating-point numbers
template <typename Fundamental>
struct modulo_for_fundamental<Fundamental, false>
{
typedef Fundamental return_type;
static inline Fundamental apply(Fundamental const& value1,
Fundamental const& value2)
{
return std::fmod(value1, value2);
}
};
// specialization for fundamental number type
template <typename Fundamental>
struct modulo<Fundamental, true>
: modulo_for_fundamental<Fundamental>
{};
/*!
\brief Short constructs to enable partial specialization for PI, 2*PI
and PI/2, currently not possible in Math.
*/
template <typename T>
struct define_pi
{
static inline T apply()
{
// Default calls Boost.Math
return boost::math::constants::pi<T>();
}
};
template <typename T>
struct define_two_pi
{
static inline T apply()
{
// Default calls Boost.Math
return boost::math::constants::two_pi<T>();
}
};
template <typename T>
struct define_half_pi
{
static inline T apply()
{
// Default calls Boost.Math
return boost::math::constants::half_pi<T>();
}
};
template <typename T>
struct relaxed_epsilon
{
static inline T apply(T const& factor)
{
return factor * std::numeric_limits<T>::epsilon();
}
};
// This must be consistent with math::equals.
// By default math::equals() scales the error by epsilon using the greater of
// compared values but here is only one value, though it should work the same way.
// (a-a) <= max(a, a) * EPS -> 0 <= a*EPS
// (a+da-a) <= max(a+da, a) * EPS -> da <= (a+da)*EPS
template <typename T, bool IsIntegral = std::is_integral<T>::value>
struct scaled_epsilon
{
static inline T apply(T const& val)
{
return (std::max)(abs<T>::apply(val), T(1))
* std::numeric_limits<T>::epsilon();
}
static inline T apply(T const& val, T const& eps)
{
return (std::max)(abs<T>::apply(val), T(1))
* eps;
}
};
template <typename T>
struct scaled_epsilon<T, true>
{
static inline T apply(T const&)
{
return T(0);
}
static inline T apply(T const&, T const&)
{
return T(0);
}
};
// ItoF ItoI FtoF
template <typename Result, typename Source,
bool ResultIsInteger = std::numeric_limits<Result>::is_integer,
bool SourceIsInteger = std::numeric_limits<Source>::is_integer>
struct rounding_cast
{
static inline Result apply(Source const& v)
{
return boost::numeric_cast<Result>(v);
}
};
// TtoT
template <typename Source, bool ResultIsInteger, bool SourceIsInteger>
struct rounding_cast<Source, Source, ResultIsInteger, SourceIsInteger>
{
static inline Source apply(Source const& v)
{
return v;
}
};
// FtoI
template <typename Result, typename Source>
struct rounding_cast<Result, Source, true, false>
{
static inline Result apply(Source const& v)
{
return boost::numeric_cast<Result>(v < Source(0) ?
v - Source(0.5) :
v + Source(0.5));
}
};
template <typename T, bool IsIntegral = std::is_integral<T>::value>
struct divide
{
static inline T apply(T const& n, T const& d)
{
return n / d;
}
};
template <typename T>
struct divide<T, true>
{
static inline T apply(T const& n, T const& d)
{
return n == 0 ? 0
: n < 0
? (d < 0 ? (n + (-d + 1) / 2) / d + 1
: (n + ( d + 1) / 2) / d - 1 )
: (d < 0 ? (n - (-d + 1) / 2) / d - 1
: (n - ( d + 1) / 2) / d + 1 )
;
}
};
} // namespace detail
#endif
template <typename T>
inline T pi() { return detail::define_pi<T>::apply(); }
template <typename T>
inline T two_pi() { return detail::define_two_pi<T>::apply(); }
template <typename T>
inline T half_pi() { return detail::define_half_pi<T>::apply(); }
template <typename T>
inline T relaxed_epsilon(T const& factor)
{
return detail::relaxed_epsilon<T>::apply(factor);
}
template <typename T>
inline T scaled_epsilon(T const& value)
{
return detail::scaled_epsilon<T>::apply(value);
}
template <typename T>
inline T scaled_epsilon(T const& value, T const& eps)
{
return detail::scaled_epsilon<T>::apply(value, eps);
}
// Maybe replace this by boost equals or so
/*!
\brief returns true if both arguments are equal.
\ingroup utility
\param a first argument
\param b second argument
\return true if a == b
\note If both a and b are of an integral type, comparison is done by ==.
If one of the types is floating point, comparison is done by abs and
comparing with epsilon. If one of the types is non-fundamental, it might
be a high-precision number and comparison is done using the == operator
of that class.
*/
template <typename T1, typename T2>
inline bool equals(T1 const& a, T2 const& b)
{
return detail::equals
<
typename select_most_precise<T1, T2>::type
>::apply(a, b, detail::equals_default_policy());
}
template <typename T1, typename T2>
inline bool equals_with_epsilon(T1 const& a, T2 const& b)
{
return detail::equals_with_epsilon
<
typename select_most_precise<T1, T2>::type
>::apply(a, b, detail::equals_default_policy());
}
template <typename T1, typename T2>
inline bool smaller(T1 const& a, T2 const& b)
{
return detail::smaller
<
typename select_most_precise<T1, T2>::type
>::apply(a, b);
}
template <typename T1, typename T2>
inline bool larger(T1 const& a, T2 const& b)
{
return detail::smaller
<
typename select_most_precise<T1, T2>::type
>::apply(b, a);
}
template <typename T1, typename T2>
inline bool smaller_or_equals(T1 const& a, T2 const& b)
{
return detail::smaller_or_equals
<
typename select_most_precise<T1, T2>::type
>::apply(a, b);
}
template <typename T1, typename T2>
inline bool larger_or_equals(T1 const& a, T2 const& b)
{
return detail::smaller_or_equals
<
typename select_most_precise<T1, T2>::type
>::apply(b, a);
}
template <typename T>
inline T d2r()
{
static T const conversion_coefficient = geometry::math::pi<T>() / T(180.0);
return conversion_coefficient;
}
template <typename T>
inline T r2d()
{
static T const conversion_coefficient = T(180.0) / geometry::math::pi<T>();
return conversion_coefficient;
}
/*!
\brief Wraps an angle in the range [-pi, +pi] (both inclusive)
*/
template <typename T>
inline T wrap_azimuth_in_radian(T const& azimuth)
{
static T const pi = geometry::math::pi<T>();
static T const two_pi = geometry::math::two_pi<T>();
T result = azimuth;
while (result > pi) { result -= two_pi; }
while (result < -pi) { result += two_pi; }
return result;
};
#ifndef DOXYGEN_NO_DETAIL
namespace detail {
template <typename DegreeOrRadian>
struct as_radian
{
template <typename T>
static inline T apply(T const& value)
{
return value;
}
};
template <>
struct as_radian<degree>
{
template <typename T>
static inline T apply(T const& value)
{
return value * d2r<T>();
}
};
template <typename DegreeOrRadian>
struct from_radian
{
template <typename T>
static inline T apply(T const& value)
{
return value;
}
};
template <>
struct from_radian<degree>
{
template <typename T>
static inline T apply(T const& value)
{
return value * r2d<T>();
}
};
} // namespace detail
#endif
template <typename DegreeOrRadian, typename T>
inline T as_radian(T const& value)
{
return detail::as_radian<DegreeOrRadian>::apply(value);
}
template <typename DegreeOrRadian, typename T>
inline T from_radian(T const& value)
{
return detail::from_radian<DegreeOrRadian>::apply(value);
}
/*!
\brief Calculates the haversine of an angle
\ingroup utility
\note See http://en.wikipedia.org/wiki/Haversine_formula
haversin(alpha) = sin2(alpha/2)
*/
template <typename T>
inline T hav(T const& theta)
{
T const half = T(0.5);
T const sn = sin(half * theta);
return sn * sn;
}
/*!
\brief Short utility to return the square
\ingroup utility
\param value Value to calculate the square from
\return The squared value
*/
template <typename T>
inline T sqr(T const& value)
{
return value * value;
}
/*!
\brief Short utility to return the square root
\ingroup utility
\param value Value to calculate the square root from
\return The square root value
*/
template <typename T>
inline typename detail::square_root<T>::return_type
sqrt(T const& value)
{
return detail::square_root
<
T, std::is_fundamental<T>::value
>::apply(value);
}
/*!
\brief Short utility to return the modulo of two values
\ingroup utility
\param value1 First value
\param value2 Second value
\return The result of the modulo operation on the (ordered) pair
(value1, value2)
*/
template <typename T>
inline typename detail::modulo<T>::return_type
mod(T const& value1, T const& value2)
{
return detail::modulo
<
T, std::is_fundamental<T>::value
>::apply(value1, value2);
}
/*!
\brief Short utility to workaround gcc/clang problem that abs is converting to integer
and that older versions of MSVC does not support abs of long long...
\ingroup utility
*/
template<typename T>
inline T abs(T const& value)
{
return detail::abs<T>::apply(value);
}
/*!
\brief Short utility to calculate the sign of a number: -1 (negative), 0 (zero), 1 (positive)
\ingroup utility
*/
template <typename T>
inline int sign(T const& value)
{
T const zero = T();
return value > zero ? 1 : value < zero ? -1 : 0;
}
/*!
\brief Short utility to cast a value possibly rounding it to the nearest
integral value.
\ingroup utility
\note If the source T is NOT an integral type and Result is an integral type
the value is rounded towards the closest integral value. Otherwise it's
casted without rounding.
*/
template <typename Result, typename T>
inline Result rounding_cast(T const& v)
{
return detail::rounding_cast<Result, T>::apply(v);
}
/*
\brief Short utility to divide. If the division is integer, it rounds the division
to the nearest value, without using floating point calculations
\ingroup utility
*/
template <typename T>
inline T divide(T const& n, T const& d)
{
return detail::divide<T>::apply(n, d);
}
/*!
\brief Evaluate the sine and cosine function with the argument in degrees
\note The results obey exactly the elementary properties of the trigonometric
functions, e.g., sin 9&deg; = cos 81&deg; = &minus; sin 123456789&deg;.
If x = &minus;0, then \e sinx = &minus;0; this is the only case where
&minus;0 is returned.
*/
template<typename T>
inline void sin_cos_degrees(T const& x,
T & sinx,
T & cosx)
{
// In order to minimize round-off errors, this function exactly reduces
// the argument to the range [-45, 45] before converting it to radians.
T remainder = math::mod(x, T(360));
T const quotient = std::floor(remainder / T(90) + T(0.5));
remainder -= T(90) * quotient;
// Convert to radians.
remainder *= d2r<T>();
T const s = sin(remainder);
T const c = cos(remainder);
switch (unsigned(quotient) & 3U)
{
case 0U: sinx = s; cosx = c; break;
case 1U: sinx = c; cosx = -s; break;
case 2U: sinx = -s; cosx = -c; break;
default: sinx = -c; cosx = s; break; // case 3U
}
// Set sign of 0 results. -0 only produced for sin(-0).
if (x != 0)
{
sinx += T(0);
cosx += T(0);
}
}
/*!
\brief Round off a given angle
*/
template<typename T>
inline T round_angle(T const& x) {
static const T z = 1/T(16);
if (x == 0)
{
return 0;
}
T y = math::abs(x);
// z - (z - y) must not be simplified to y.
y = y < z ? z - (z - y) : y;
return x < 0 ? -y : y;
}
/*!
\brief Evaluate the polynomial in x using Horner's method.
*/
// TODO: adl1995 - Merge these functions with formulas/area_formulas.hpp
// i.e. place them in one file.
template <typename NT, typename IteratorType>
inline NT horner_evaluate(NT const& x,
IteratorType begin,
IteratorType end)
{
NT result(0);
IteratorType it = end;
do
{
result = result * x + *--it;
}
while (it != begin);
return result;
}
/*!
\brief Evaluate the polynomial.
*/
template<typename IteratorType, typename CT>
inline CT polyval(IteratorType first,
IteratorType last,
CT const& eps)
{
int N = std::distance(first, last) - 1;
int index = 0;
CT y = N < 0 ? 0 : *(first + (index++));
while (--N >= 0)
{
y = y * eps + *(first + (index++));
}
return y;
}
/*
\brief Short utility to calculate the power
\ingroup utility
*/
template <typename T1, typename T2>
inline T1 pow(T1 const& a, T2 const& b)
{
using std::pow;
return pow(a, b);
}
} // namespace math
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_MATH_HPP
@@ -0,0 +1,191 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
namespace boost { namespace geometry
{
namespace math
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Units, typename CoordinateType, bool IsEquatorial = true>
class normalize_spheroidal_box_coordinates
{
private:
typedef normalize_spheroidal_coordinates<Units, CoordinateType> normalize;
typedef constants_on_spheroid<CoordinateType, Units> constants;
static inline bool is_band(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
return math::larger_or_equals(math::abs(longitude1 - longitude2),
constants::period());
}
public:
static inline void apply(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2,
bool band)
{
normalize::apply(longitude1, latitude1, false);
normalize::apply(longitude2, latitude2, false);
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude1);
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude2);
if (math::equals(latitude1, constants::min_latitude())
&& math::equals(latitude2, constants::min_latitude()))
{
// box degenerates to the south pole
longitude1 = longitude2 = CoordinateType(0);
}
else if (math::equals(latitude1, constants::max_latitude())
&& math::equals(latitude2, constants::max_latitude()))
{
// box degenerates to the north pole
longitude1 = longitude2 = CoordinateType(0);
}
else if (band)
{
// the box is a band between two small circles (parallel
// to the equator) on the spheroid
longitude1 = constants::min_longitude();
longitude2 = constants::max_longitude();
}
else if (longitude1 > longitude2)
{
// the box crosses the antimeridian, so we need to adjust
// the longitudes
longitude2 += constants::period();
}
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude1);
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude2);
#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
BOOST_GEOMETRY_ASSERT(! math::larger(latitude1, latitude2));
BOOST_GEOMETRY_ASSERT(! math::smaller(latitude1, constants::min_latitude()));
BOOST_GEOMETRY_ASSERT(! math::larger(latitude2, constants::max_latitude()));
#endif
BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2));
BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude()));
BOOST_GEOMETRY_ASSERT(! math::larger(longitude2 - longitude1, constants::period()));
}
static inline void apply(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2)
{
bool const band = is_band(longitude1, longitude2);
apply(longitude1, latitude1, longitude2, latitude2, band);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Short utility to normalize the coordinates of a box on a spheroid
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Minimum longitude of the box
\param latitude1 Minimum latitude of the box
\param longitude2 Maximum longitude of the box
\param latitude2 Maximum latitude of the box
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType
>::apply(longitude1, latitude1, longitude2, latitude2);
}
template <typename Units, bool IsEquatorial, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType, IsEquatorial
>::apply(longitude1, latitude1, longitude2, latitude2);
}
/*!
\brief Short utility to normalize the coordinates of a box on a spheroid
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Minimum longitude of the box
\param latitude1 Minimum latitude of the box
\param longitude2 Maximum longitude of the box
\param latitude2 Maximum latitude of the box
\param band Indicates whether the box should be treated as a band or
not and avoid the computation done in the other version of the function
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2,
bool band)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType
>::apply(longitude1, latitude1, longitude2, latitude2, band);
}
template <typename Units, bool IsEquatorial, typename CoordinateType>
inline void normalize_spheroidal_box_coordinates(CoordinateType& longitude1,
CoordinateType& latitude1,
CoordinateType& longitude2,
CoordinateType& latitude2,
bool band)
{
detail::normalize_spheroidal_box_coordinates
<
Units, CoordinateType, IsEquatorial
>::apply(longitude1, latitude1, longitude2, latitude2, band);
}
} // namespace math
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_BOX_COORDINATES_HPP
@@ -0,0 +1,510 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2015-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace math
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// CoordinateType, radian, true
template <typename CoordinateType, typename Units, bool IsEquatorial = true>
struct constants_on_spheroid
{
static inline CoordinateType period()
{
return math::two_pi<CoordinateType>();
}
static inline CoordinateType half_period()
{
return math::pi<CoordinateType>();
}
static inline CoordinateType quarter_period()
{
static CoordinateType const
pi_half = math::pi<CoordinateType>() / CoordinateType(2);
return pi_half;
}
static inline CoordinateType min_longitude()
{
static CoordinateType const minus_pi = -math::pi<CoordinateType>();
return minus_pi;
}
static inline CoordinateType max_longitude()
{
return math::pi<CoordinateType>();
}
static inline CoordinateType min_latitude()
{
static CoordinateType const minus_half_pi
= -math::half_pi<CoordinateType>();
return minus_half_pi;
}
static inline CoordinateType max_latitude()
{
return math::half_pi<CoordinateType>();
}
};
template <typename CoordinateType>
struct constants_on_spheroid<CoordinateType, radian, false>
: constants_on_spheroid<CoordinateType, radian, true>
{
static inline CoordinateType min_latitude()
{
return CoordinateType(0);
}
static inline CoordinateType max_latitude()
{
return math::pi<CoordinateType>();
}
};
template <typename CoordinateType>
struct constants_on_spheroid<CoordinateType, degree, true>
{
static inline CoordinateType period()
{
return CoordinateType(360.0);
}
static inline CoordinateType half_period()
{
return CoordinateType(180.0);
}
static inline CoordinateType quarter_period()
{
return CoordinateType(90.0);
}
static inline CoordinateType min_longitude()
{
return CoordinateType(-180.0);
}
static inline CoordinateType max_longitude()
{
return CoordinateType(180.0);
}
static inline CoordinateType min_latitude()
{
return CoordinateType(-90.0);
}
static inline CoordinateType max_latitude()
{
return CoordinateType(90.0);
}
};
template <typename CoordinateType>
struct constants_on_spheroid<CoordinateType, degree, false>
: constants_on_spheroid<CoordinateType, degree, true>
{
static inline CoordinateType min_latitude()
{
return CoordinateType(0);
}
static inline CoordinateType max_latitude()
{
return CoordinateType(180.0);
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename Units, typename CoordinateType>
inline CoordinateType latitude_convert_ep(CoordinateType const& lat)
{
typedef math::detail::constants_on_spheroid
<
CoordinateType,
Units
> constants;
return constants::quarter_period() - lat;
}
template <typename Units, bool IsEquatorial, typename T>
static bool is_latitude_pole(T const& lat)
{
typedef math::detail::constants_on_spheroid
<
T,
Units
> constants;
return math::equals(math::abs(IsEquatorial
? lat
: math::latitude_convert_ep<Units>(lat)),
constants::quarter_period());
}
template <typename Units, typename T>
static bool is_longitude_antimeridian(T const& lon)
{
typedef math::detail::constants_on_spheroid
<
T,
Units
> constants;
return math::equals(math::abs(lon), constants::half_period());
}
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Units, bool IsEquatorial>
struct latitude_convert_if_polar
{
template <typename T>
static inline void apply(T & /*lat*/) {}
};
template <typename Units>
struct latitude_convert_if_polar<Units, false>
{
template <typename T>
static inline void apply(T & lat)
{
lat = latitude_convert_ep<Units>(lat);
}
};
template <typename Units, typename CoordinateType, bool IsEquatorial = true>
class normalize_spheroidal_coordinates
{
typedef constants_on_spheroid<CoordinateType, Units> constants;
protected:
static inline CoordinateType normalize_up(CoordinateType const& value)
{
return
math::mod(value + constants::half_period(), constants::period())
- constants::half_period();
}
static inline CoordinateType normalize_down(CoordinateType const& value)
{
return
math::mod(value - constants::half_period(), constants::period())
+ constants::half_period();
}
public:
static inline void apply(CoordinateType& longitude)
{
// normalize longitude
if (math::equals(math::abs(longitude), constants::half_period()))
{
longitude = constants::half_period();
}
else if (longitude > constants::half_period())
{
longitude = normalize_up(longitude);
if (math::equals(longitude, -constants::half_period()))
{
longitude = constants::half_period();
}
}
else if (longitude < -constants::half_period())
{
longitude = normalize_down(longitude);
}
}
static inline void apply(CoordinateType& longitude,
CoordinateType& latitude,
bool normalize_poles = true)
{
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude);
#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
// normalize latitude
if (math::larger(latitude, constants::half_period()))
{
latitude = normalize_up(latitude);
}
else if (math::smaller(latitude, -constants::half_period()))
{
latitude = normalize_down(latitude);
}
// fix latitude range
if (latitude < constants::min_latitude())
{
latitude = -constants::half_period() - latitude;
longitude -= constants::half_period();
}
else if (latitude > constants::max_latitude())
{
latitude = constants::half_period() - latitude;
longitude -= constants::half_period();
}
#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
// normalize longitude
apply(longitude);
// finally normalize poles
if (normalize_poles)
{
if (math::equals(math::abs(latitude), constants::max_latitude()))
{
// for the north and south pole we set the longitude to 0
// (works for both radians and degrees)
longitude = CoordinateType(0);
}
}
latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude);
#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
BOOST_GEOMETRY_ASSERT(! math::larger(constants::min_latitude(), latitude));
BOOST_GEOMETRY_ASSERT(! math::larger(latitude, constants::max_latitude()));
#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
BOOST_GEOMETRY_ASSERT(! math::larger_or_equals(constants::min_longitude(), longitude));
BOOST_GEOMETRY_ASSERT(! math::larger(longitude, constants::max_longitude()));
}
};
template <typename Units, typename CoordinateType>
inline void normalize_angle_loop(CoordinateType& angle)
{
typedef constants_on_spheroid<CoordinateType, Units> constants;
CoordinateType const pi = constants::half_period();
CoordinateType const two_pi = constants::period();
while (angle > pi)
angle -= two_pi;
while (angle <= -pi)
angle += two_pi;
}
template <typename Units, typename CoordinateType>
inline void normalize_angle_cond(CoordinateType& angle)
{
typedef constants_on_spheroid<CoordinateType, Units> constants;
CoordinateType const pi = constants::half_period();
CoordinateType const two_pi = constants::period();
if (angle > pi)
angle -= two_pi;
else if (angle <= -pi)
angle += two_pi;
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Short utility to normalize the coordinates on a spheroid
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude Longitude
\param latitude Latitude
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
CoordinateType& latitude)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType
>::apply(longitude, latitude);
}
template <typename Units, bool IsEquatorial, typename CoordinateType>
inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
CoordinateType& latitude)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType, IsEquatorial
>::apply(longitude, latitude);
}
/*!
\brief Short utility to normalize the longitude on a spheroid.
Note that in general both coordinates should be normalized at once.
This utility is suitable e.g. for normalization of the difference of longitudes.
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude Longitude
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_longitude(CoordinateType& longitude)
{
detail::normalize_spheroidal_coordinates
<
Units, CoordinateType
>::apply(longitude);
}
/*!
\brief Short utility to normalize the azimuth on a spheroid
in the range (-180, 180].
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param angle Angle
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline void normalize_azimuth(CoordinateType& angle)
{
normalize_longitude<Units, CoordinateType>(angle);
}
/*!
\brief Normalize the given values.
\tparam ValueType The type of the values
\param x Value x
\param y Value y
TODO: adl1995 - Merge this function with
formulas/vertex_longitude.hpp
*/
template<typename ValueType>
inline void normalize_unit_vector(ValueType& x, ValueType& y)
{
ValueType h = boost::math::hypot(x, y);
BOOST_GEOMETRY_ASSERT(h > 0);
x /= h; y /= h;
}
/*!
\brief Short utility to calculate difference between two longitudes
normalized in range (-180, 180].
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Longitude 1
\param longitude2 Longitude 2
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_distance_signed(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
CoordinateType diff = longitude2 - longitude1;
math::normalize_longitude<Units, CoordinateType>(diff);
return diff;
}
/*!
\brief Short utility to calculate difference between two longitudes
normalized in range [0, 360).
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Longitude 1
\param longitude2 Longitude 2
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
typedef math::detail::constants_on_spheroid
<
CoordinateType, Units
> constants;
CoordinateType const c0 = 0;
CoordinateType diff = longitude_distance_signed<Units>(longitude1, longitude2);
if (diff < c0) // (-180, 180] -> [0, 360)
{
diff += constants::period();
}
return diff;
}
/*!
\brief The abs difference between longitudes in range [0, 180].
\tparam Units The units of the coordindate system in the spheroid
\tparam CoordinateType The type of the coordinates
\param longitude1 Longitude 1
\param longitude2 Longitude 2
\ingroup utility
*/
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_difference(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
return math::abs(math::longitude_distance_signed<Units>(longitude1, longitude2));
}
template <typename Units, typename CoordinateType>
inline CoordinateType longitude_interval_distance_signed(CoordinateType const& longitude_a1,
CoordinateType const& longitude_a2,
CoordinateType const& longitude_b)
{
CoordinateType const c0 = 0;
CoordinateType dist_a12 = longitude_distance_signed<Units>(longitude_a1, longitude_a2);
CoordinateType dist_a1b = longitude_distance_signed<Units>(longitude_a1, longitude_b);
if (dist_a12 < c0)
{
dist_a12 = -dist_a12;
dist_a1b = -dist_a1b;
}
return dist_a1b < c0 ? dist_a1b
: dist_a1b > dist_a12 ? dist_a1b - dist_a12
: c0;
}
} // namespace math
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
+56
View File
@@ -0,0 +1,56 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
#define BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
#include <boost/geometry/core/point_order.hpp>
namespace boost { namespace geometry
{
/*!
\brief Flag for iterating a reversible_view in forward or reverse direction
\ingroup views
*/
enum iterate_direction { iterate_forward, iterate_reverse };
template<order_selector Order>
struct order_as_direction
{};
template<>
struct order_as_direction<clockwise>
{
static const iterate_direction value = iterate_forward;
};
template<>
struct order_as_direction<counterclockwise>
{
static const iterate_direction value = iterate_reverse;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
+78
View File
@@ -0,0 +1,78 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
#define BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
#include <type_traits>
#include <boost/function_types/function_arity.hpp>
#include <boost/function_types/is_member_function_pointer.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/mpl/at.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function selecting a parameter type of a (member) function, by index
\ingroup utility
*/
template <typename Method, std::size_t Index>
struct parameter_type_of
{
typedef typename boost::function_types::parameter_types
<
Method
>::type parameter_types;
typedef std::conditional_t
<
boost::function_types::is_member_function_pointer<Method>::value,
std::integral_constant<int, 1>,
std::integral_constant<int, 0>
> base_index_type;
typedef std::conditional_t
<
Index == 0,
base_index_type,
std::integral_constant
<
int,
(base_index_type::value + Index)
>
> indexed_type;
typedef typename std::remove_reference
<
typename boost::mpl::at
<
parameter_types,
indexed_type
>::type
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
+633
View File
@@ -0,0 +1,633 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2019 Tinko Bartels, Berlin, Germany.
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Contributed and/or modified by Tinko Bartels,
// as part of Google Summer of Code 2019 program.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
#define BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
#include<numeric>
#include<cmath>
#include<limits>
#include<array>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/util/condition.hpp>
// The following code is based on "Adaptive Precision Floating-Point Arithmetic
// and Fast Robust Geometric Predicates" by Richard Shewchuk,
// J. Discrete Comput Geom (1997) 18: 305. https://doi.org/10.1007/PL00009321
namespace boost { namespace geometry
{
namespace detail { namespace precise_math
{
// See Theorem 6, page 6
template
<
typename RealNumber
>
inline std::array<RealNumber, 2> fast_two_sum(RealNumber const a,
RealNumber const b)
{
RealNumber x = a + b;
RealNumber b_virtual = x - a;
return {{x, b - b_virtual}};
}
// See Theorem 7, page 7 - 8
template
<
typename RealNumber
>
inline std::array<RealNumber, 2> two_sum(RealNumber const a,
RealNumber const b)
{
RealNumber x = a + b;
RealNumber b_virtual = x - a;
RealNumber a_virtual = x - b_virtual;
RealNumber b_roundoff = b - b_virtual;
RealNumber a_roundoff = a - a_virtual;
RealNumber y = a_roundoff + b_roundoff;
return {{ x, y }};
}
// See bottom of page 8
template
<
typename RealNumber
>
inline RealNumber two_diff_tail(RealNumber const a,
RealNumber const b,
RealNumber const x)
{
RealNumber b_virtual = a - x;
RealNumber a_virtual = x + b_virtual;
RealNumber b_roundoff = b_virtual - b;
RealNumber a_roundoff = a - a_virtual;
return a_roundoff + b_roundoff;
}
// see bottom of page 8
template
<
typename RealNumber
>
inline std::array<RealNumber, 2> two_diff(RealNumber const a,
RealNumber const b)
{
RealNumber x = a - b;
RealNumber y = two_diff_tail(a, b, x);
return {{ x, y }};
}
// see theorem 18, page 19
template
<
typename RealNumber
>
inline RealNumber two_product_tail(RealNumber const a,
RealNumber const b,
RealNumber const x)
{
return std::fma(a, b, -x);
}
// see theorem 18, page 19
template
<
typename RealNumber
>
inline std::array<RealNumber, 2> two_product(RealNumber const a,
RealNumber const b)
{
RealNumber x = a * b;
RealNumber y = two_product_tail(a, b, x);
return {{ x , y }};
}
// see theorem 12, figure 7, page 11 - 12,
// this is the 2 by 2 case for the corresponding diff-method
// note that this method takes input in descending order of magnitude and
// returns components in ascending order of magnitude
template
<
typename RealNumber
>
inline std::array<RealNumber, 4> two_two_expansion_diff(
std::array<RealNumber, 2> const a,
std::array<RealNumber, 2> const b)
{
std::array<RealNumber, 4> h;
std::array<RealNumber, 2> Qh = two_diff(a[1], b[1]);
h[0] = Qh[1];
Qh = two_sum( a[0], Qh[0] );
RealNumber _j = Qh[0];
Qh = two_diff(Qh[1], b[0]);
h[1] = Qh[1];
Qh = two_sum( _j, Qh[0] );
h[2] = Qh[1];
h[3] = Qh[0];
return h;
}
// see theorem 13, figure 8. This implementation uses zero elimination as
// suggested on page 17, second to last paragraph. Returns the number of
// non-zero components in the result and writes the result to h.
// the merger into a single sequence g is done implicitly
template
<
typename RealNumber,
std::size_t InSize1,
std::size_t InSize2,
std::size_t OutSize
>
inline int fast_expansion_sum_zeroelim(
std::array<RealNumber, InSize1> const& e,
std::array<RealNumber, InSize2> const& f,
std::array<RealNumber, OutSize> & h,
int m = InSize1,
int n = InSize2)
{
std::array<RealNumber, 2> Qh;
int i_e = 0;
int i_f = 0;
int i_h = 0;
if (std::abs(f[0]) > std::abs(e[0]))
{
Qh[0] = e[i_e++];
}
else
{
Qh[0] = f[i_f++];
}
i_h = 0;
if ((i_e < m) && (i_f < n))
{
if (std::abs(f[i_f]) > std::abs(e[i_e]))
{
Qh = fast_two_sum(e[i_e++], Qh[0]);
}
else
{
Qh = fast_two_sum(f[i_f++], Qh[0]);
}
if (Qh[1] != 0.0)
{
h[i_h++] = Qh[1];
}
while ((i_e < m) && (i_f < n))
{
if (std::abs(f[i_f]) > std::abs(e[i_e]))
{
Qh = two_sum(Qh[0], e[i_e++]);
}
else
{
Qh = two_sum(Qh[0], f[i_f++]);
}
if (Qh[1] != 0.0)
{
h[i_h++] = Qh[1];
}
}
}
while (i_e < m)
{
Qh = two_sum(Qh[0], e[i_e++]);
if (Qh[1] != 0.0)
{
h[i_h++] = Qh[1];
}
}
while (i_f < n)
{
Qh = two_sum(Qh[0], f[i_f++]);
if (Qh[1] != 0.0)
{
h[i_h++] = Qh[1];
}
}
if ((Qh[0] != 0.0) || (i_h == 0))
{
h[i_h++] = Qh[0];
}
return i_h;
}
// see theorem 19, figure 13, page 20 - 21. This implementation uses zero
// elimination as suggested on page 17, second to last paragraph. Returns the
// number of non-zero components in the result and writes the result to h.
template
<
typename RealNumber,
std::size_t InSize
>
inline int scale_expansion_zeroelim(
std::array<RealNumber, InSize> const& e,
RealNumber const b,
std::array<RealNumber, 2 * InSize> & h,
int e_non_zeros = InSize)
{
std::array<RealNumber, 2> Qh = two_product(e[0], b);
int i_h = 0;
if (Qh[1] != 0)
{
h[i_h++] = Qh[1];
}
for (int i_e = 1; i_e < e_non_zeros; i_e++)
{
std::array<RealNumber, 2> Tt = two_product(e[i_e], b);
Qh = two_sum(Qh[0], Tt[1]);
if (Qh[1] != 0)
{
h[i_h++] = Qh[1];
}
Qh = fast_two_sum(Tt[0], Qh[0]);
if (Qh[1] != 0)
{
h[i_h++] = Qh[1];
}
}
if ((Qh[0] != 0.0) || (i_h == 0))
{
h[i_h++] = Qh[0];
}
return i_h;
}
template<typename RealNumber>
struct vec2d
{
RealNumber x;
RealNumber y;
};
template
<
typename RealNumber,
std::size_t Robustness
>
inline RealNumber orient2dtail(vec2d<RealNumber> const& p1,
vec2d<RealNumber> const& p2,
vec2d<RealNumber> const& p3,
std::array<RealNumber, 2>& t1,
std::array<RealNumber, 2>& t2,
std::array<RealNumber, 2>& t3,
std::array<RealNumber, 2>& t4,
std::array<RealNumber, 2>& t5_01,
std::array<RealNumber, 2>& t6_01,
RealNumber const& magnitude)
{
t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]);
t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]);
std::array<RealNumber, 4> tA_03 = two_two_expansion_diff(t5_01, t6_01);
RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast<RealNumber>(0));
if (BOOST_GEOMETRY_CONDITION(Robustness == 1))
{
return det;
}
// see p.39, mind the different definition of epsilon for error bound
RealNumber B_relative_bound =
(1 + 3 * std::numeric_limits<RealNumber>::epsilon())
* std::numeric_limits<RealNumber>::epsilon();
RealNumber absolute_bound = B_relative_bound * magnitude;
if (std::abs(det) >= absolute_bound)
{
return det; //B estimate
}
t1[1] = two_diff_tail(p1.x, p3.x, t1[0]);
t2[1] = two_diff_tail(p2.y, p3.y, t2[0]);
t3[1] = two_diff_tail(p1.y, p3.y, t3[0]);
t4[1] = two_diff_tail(p2.x, p3.x, t4[0]);
if ((t1[1] == 0) && (t3[1] == 0) && (t2[1] == 0) && (t4[1] == 0))
{
return det; //If all tails are zero, there is noething else to compute
}
RealNumber sub_bound =
(1.5 + 2 * std::numeric_limits<RealNumber>::epsilon())
* std::numeric_limits<RealNumber>::epsilon();
// see p.39, mind the different definition of epsilon for error bound
RealNumber C_relative_bound =
(2.25 + 8 * std::numeric_limits<RealNumber>::epsilon())
* std::numeric_limits<RealNumber>::epsilon()
* std::numeric_limits<RealNumber>::epsilon();
absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det);
det += (t1[0] * t2[1] + t2[0] * t1[1]) - (t3[0] * t4[1] + t4[0] * t3[1]);
if (Robustness == 2 || std::abs(det) >= absolute_bound)
{
return det; //C estimate
}
std::array<RealNumber, 8> D_left;
int D_left_nz;
{
std::array<RealNumber, 2> t5_23 = two_product(t1[1], t2[0]);
std::array<RealNumber, 2> t6_23 = two_product(t3[1], t4[0]);
std::array<RealNumber, 4> tA_47 = two_two_expansion_diff(t5_23, t6_23);
D_left_nz = fast_expansion_sum_zeroelim(tA_03, tA_47, D_left);
}
std::array<RealNumber, 8> D_right;
int D_right_nz;
{
std::array<RealNumber, 2> t5_45 = two_product(t1[0], t2[1]);
std::array<RealNumber, 2> t6_45 = two_product(t3[0], t4[1]);
std::array<RealNumber, 4> tA_8_11 = two_two_expansion_diff(t5_45, t6_45);
std::array<RealNumber, 2> t5_67 = two_product(t1[1], t2[1]);
std::array<RealNumber, 2> t6_67 = two_product(t3[1], t4[1]);
std::array<RealNumber, 4> tA_12_15 = two_two_expansion_diff(t5_67, t6_67);
D_right_nz = fast_expansion_sum_zeroelim(tA_8_11, tA_12_15, D_right);
}
std::array<RealNumber, 16> D;
int D_nz = fast_expansion_sum_zeroelim(D_left, D_right, D, D_left_nz, D_right_nz);
// only return component of highest magnitude because we mostly care about the sign.
return(D[D_nz - 1]);
}
// see page 38, Figure 21 for the calculations, notation follows the notation
// in the figure.
template
<
typename RealNumber,
std::size_t Robustness = 3,
typename EpsPolicy
>
inline RealNumber orient2d(vec2d<RealNumber> const& p1,
vec2d<RealNumber> const& p2,
vec2d<RealNumber> const& p3,
EpsPolicy& eps_policy)
{
std::array<RealNumber, 2> t1, t2, t3, t4;
t1[0] = p1.x - p3.x;
t2[0] = p2.y - p3.y;
t3[0] = p1.y - p3.y;
t4[0] = p2.x - p3.x;
eps_policy = EpsPolicy(t1[0], t2[0], t3[0], t4[0]);
std::array<RealNumber, 2> t5_01, t6_01;
t5_01[0] = t1[0] * t2[0];
t6_01[0] = t3[0] * t4[0];
RealNumber det = t5_01[0] - t6_01[0];
if (BOOST_GEOMETRY_CONDITION(Robustness == 0))
{
return det;
}
RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]);
// see p.39, mind the different definition of epsilon for error bound
RealNumber const A_relative_bound =
(1.5 + 4 * std::numeric_limits<RealNumber>::epsilon())
* std::numeric_limits<RealNumber>::epsilon();
RealNumber absolute_bound = A_relative_bound * magnitude;
if ( std::abs(det) >= absolute_bound )
{
return det; //A estimate
}
if ( (t5_01[0] > 0 && t6_01[0] <= 0) || (t5_01[0] < 0 && t6_01[0] >= 0) )
{
//if diagonal and antidiagonal have different sign, the sign of det is
//obvious
return det;
}
return orient2dtail<RealNumber, Robustness>(p1, p2, p3, t1, t2, t3, t4,
t5_01, t6_01, magnitude);
}
// This method adaptively computes increasingly precise approximations of the following
// determinant using Laplace expansion along the last column.
// det A =
// | p1_x - p4_x p1_y - p4_y ( p1_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 |
// | p2_x - p4_x p2_y - p4_y ( p2_x - p4_x ) ^ 2 + ( p1_y - p4_y ) ^ 2 |
// | p3_x - p4_x p3_y - p4_y ( p3_x - p4_x ) ^ 2 + ( p3_y - p4_y ) ^ 2 |
// = a_13 * C_13 + a_23 * C_23 + a_33 * C_33
// where a_ij is the i-j-entry and C_ij is the i_j Cofactor
template
<
typename RealNumber,
std::size_t Robustness = 2
>
RealNumber incircle(std::array<RealNumber, 2> const& p1,
std::array<RealNumber, 2> const& p2,
std::array<RealNumber, 2> const& p3,
std::array<RealNumber, 2> const& p4)
{
RealNumber A_11 = p1[0] - p4[0];
RealNumber A_21 = p2[0] - p4[0];
RealNumber A_31 = p3[0] - p4[0];
RealNumber A_12 = p1[1] - p4[1];
RealNumber A_22 = p2[1] - p4[1];
RealNumber A_32 = p3[1] - p4[1];
std::array<RealNumber, 2> A_21_x_A_32,
A_31_x_A_22,
A_31_x_A_12,
A_11_x_A_32,
A_11_x_A_22,
A_21_x_A_12;
A_21_x_A_32[0] = A_21 * A_32;
A_31_x_A_22[0] = A_31 * A_22;
RealNumber A_13 = A_11 * A_11 + A_12 * A_12;
A_31_x_A_12[0] = A_31 * A_12;
A_11_x_A_32[0] = A_11 * A_32;
RealNumber A_23 = A_21 * A_21 + A_22 * A_22;
A_11_x_A_22[0] = A_11 * A_22;
A_21_x_A_12[0] = A_21 * A_12;
RealNumber A_33 = A_31 * A_31 + A_32 * A_32;
RealNumber det = A_13 * (A_21_x_A_32[0] - A_31_x_A_22[0])
+ A_23 * (A_31_x_A_12[0] - A_11_x_A_32[0])
+ A_33 * (A_11_x_A_22[0] - A_21_x_A_12[0]);
if(Robustness == 0) return det;
RealNumber magnitude =
(std::abs(A_21_x_A_32[0]) + std::abs(A_31_x_A_22[0])) * A_13
+ (std::abs(A_31_x_A_12[0]) + std::abs(A_11_x_A_32[0])) * A_23
+ (std::abs(A_11_x_A_22[0]) + std::abs(A_21_x_A_12[0])) * A_33;
RealNumber A_relative_bound =
(5 + 24 * std::numeric_limits<RealNumber>::epsilon())
* std::numeric_limits<RealNumber>::epsilon();
RealNumber absolute_bound = A_relative_bound * magnitude;
if (std::abs(det) > absolute_bound)
{
return det;
}
// (p2_x - p4_x) * (p3_y - p4_y)
A_21_x_A_32[1] = two_product_tail(A_21, A_32, A_21_x_A_32[0]);
// (p3_x - p4_x) * (p2_y - p4_y)
A_31_x_A_22[1] = two_product_tail(A_31, A_22, A_31_x_A_22[0]);
// (bx - dx) * (cy - dy) - (cx - dx) * (by - dy)
std::array<RealNumber, 4> C_13 = two_two_expansion_diff(A_21_x_A_32, A_31_x_A_22);
std::array<RealNumber, 8> C_13_x_A11;
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx )
int C_13_x_A11_nz = scale_expansion_zeroelim(C_13, A_11, C_13_x_A11);
std::array<RealNumber, 16> C_13_x_A11_sq;
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ax - dx ) * (ax - dx)
int C_13_x_A11_sq_nz = scale_expansion_zeroelim(C_13_x_A11,
A_11,
C_13_x_A11_sq,
C_13_x_A11_nz);
std::array<RealNumber, 8> C_13_x_A12;
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy )
int C_13_x_A12_nz = scale_expansion_zeroelim(C_13, A_12, C_13_x_A12);
std::array<RealNumber, 16> C_13_x_A12_sq;
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) ) * ( ay - dy ) * ( ay - dy )
int C_13_x_A12_sq_nz = scale_expansion_zeroelim(C_13_x_A12, A_12,
C_13_x_A12_sq,
C_13_x_A12_nz);
std::array<RealNumber, 32> A_13_x_C13;
// ( (bx - dx) * (cy - dy) - (cx - dx) * (by - dy) )
// * ( ( ay - dy ) * ( ay - dy ) + ( ax - dx ) * (ax - dx) )
int A_13_x_C13_nz = fast_expansion_sum_zeroelim(C_13_x_A11_sq,
C_13_x_A12_sq,
A_13_x_C13,
C_13_x_A11_sq_nz,
C_13_x_A12_sq_nz);
// (cx - dx) * (ay - dy)
A_31_x_A_12[1] = two_product_tail(A_31, A_12, A_31_x_A_12[0]);
// (ax - dx) * (cy - dy)
A_11_x_A_32[1] = two_product_tail(A_11, A_32, A_11_x_A_32[0]);
// (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy)
std::array<RealNumber, 4> C_23 = two_two_expansion_diff(A_31_x_A_12,
A_11_x_A_32);
std::array<RealNumber, 8> C_23_x_A_21;
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx )
int C_23_x_A_21_nz = scale_expansion_zeroelim(C_23, A_21, C_23_x_A_21);
std::array<RealNumber, 16> C_23_x_A_21_sq;
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( bx - dx ) * ( bx - dx )
int C_23_x_A_21_sq_nz = scale_expansion_zeroelim(C_23_x_A_21, A_21,
C_23_x_A_21_sq,
C_23_x_A_21_nz);
std::array<RealNumber, 8> C_23_x_A_22;
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy )
int C_23_x_A_22_nz = scale_expansion_zeroelim(C_23, A_22, C_23_x_A_22);
std::array<RealNumber, 16> C_23_x_A_22_sq;
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) ) * ( by - dy ) * ( by - dy )
int C_23_x_A_22_sq_nz = scale_expansion_zeroelim(C_23_x_A_22, A_22,
C_23_x_A_22_sq,
C_23_x_A_22_nz);
std::array<RealNumber, 32> A_23_x_C_23;
// ( (cx - dx) * (ay - dy) - (ax - dx) * (cy - dy) )
// * ( ( bx - dx ) * ( bx - dx ) + ( by - dy ) * ( by - dy ) )
int A_23_x_C_23_nz = fast_expansion_sum_zeroelim(C_23_x_A_21_sq,
C_23_x_A_22_sq,
A_23_x_C_23,
C_23_x_A_21_sq_nz,
C_23_x_A_22_sq_nz);
// (ax - dx) * (by - dy)
A_11_x_A_22[1] = two_product_tail(A_11, A_22, A_11_x_A_22[0]);
// (bx - dx) * (ay - dy)
A_21_x_A_12[1] = two_product_tail(A_21, A_12, A_21_x_A_12[0]);
// (ax - dx) * (by - dy) - (bx - dx) * (ay - dy)
std::array<RealNumber, 4> C_33 = two_two_expansion_diff(A_11_x_A_22,
A_21_x_A_12);
std::array<RealNumber, 8> C_33_x_A31;
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx )
int C_33_x_A31_nz = scale_expansion_zeroelim(C_33, A_31, C_33_x_A31);
std::array<RealNumber, 16> C_33_x_A31_sq;
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cx - dx ) * ( cx - dx )
int C_33_x_A31_sq_nz = scale_expansion_zeroelim(C_33_x_A31, A_31,
C_33_x_A31_sq,
C_33_x_A31_nz);
std::array<RealNumber, 8> C_33_x_A_32;
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy )
int C_33_x_A_32_nz = scale_expansion_zeroelim(C_33, A_32, C_33_x_A_32);
std::array<RealNumber, 16> C_33_x_A_32_sq;
// ( (ax - dx) * (by - dy) - (bx - dx) * (ay - dy) ) * ( cy - dy ) * ( cy - dy )
int C_33_x_A_32_sq_nz = scale_expansion_zeroelim(C_33_x_A_32, A_32,
C_33_x_A_32_sq,
C_33_x_A_32_nz);
std::array<RealNumber, 32> A_33_x_C_33;
int A_33_x_C_33_nz = fast_expansion_sum_zeroelim(C_33_x_A31_sq,
C_33_x_A_32_sq,
A_33_x_C_33,
C_33_x_A31_sq_nz,
C_33_x_A_32_sq_nz);
std::array<RealNumber, 64> A_13_x_C13_p_A_13_x_C13;
int A_13_x_C13_p_A_13_x_C13_nz = fast_expansion_sum_zeroelim(
A_13_x_C13, A_23_x_C_23,
A_13_x_C13_p_A_13_x_C13,
A_13_x_C13_nz,
A_23_x_C_23_nz);
std::array<RealNumber, 96> det_expansion;
int det_expansion_nz = fast_expansion_sum_zeroelim(
A_13_x_C13_p_A_13_x_C13,
A_33_x_C_33,
det_expansion,
A_13_x_C13_p_A_13_x_C13_nz,
A_33_x_C_33_nz);
det = std::accumulate(det_expansion.begin(),
det_expansion.begin() + det_expansion_nz,
static_cast<RealNumber>(0));
if(Robustness == 1) return det;
RealNumber B_relative_bound =
(2 + 12 * std::numeric_limits<RealNumber>::epsilon())
* std::numeric_limits<RealNumber>::epsilon();
absolute_bound = B_relative_bound * magnitude;
if (std::abs(det) >= absolute_bound)
{
return det;
}
RealNumber A_11tail = two_diff_tail(p1[0], p4[0], A_11);
RealNumber A_12tail = two_diff_tail(p1[1], p4[1], A_12);
RealNumber A_21tail = two_diff_tail(p2[0], p4[0], A_21);
RealNumber A_22tail = two_diff_tail(p2[1], p4[1], A_22);
RealNumber A_31tail = two_diff_tail(p3[0], p4[0], A_31);
RealNumber A_32tail = two_diff_tail(p3[1], p4[1], A_32);
if ((A_11tail == 0) && (A_21tail == 0) && (A_31tail == 0)
&& (A_12tail == 0) && (A_22tail == 0) && (A_32tail == 0))
{
return det;
}
// RealNumber sub_bound = (1.5 + 2.0 * std::numeric_limits<RealNumber>::epsilon())
// * std::numeric_limits<RealNumber>::epsilon();
// RealNumber C_relative_bound = (11.0 + 72.0 * std::numeric_limits<RealNumber>::epsilon())
// * std::numeric_limits<RealNumber>::epsilon()
// * std::numeric_limits<RealNumber>::epsilon();
//absolute_bound = C_relative_bound * magnitude + sub_bound * std::abs(det);
det += ((A_11 * A_11 + A_12 * A_12) * ((A_21 * A_32tail + A_32 * A_21tail)
- (A_22 * A_31tail + A_31 * A_22tail))
+ 2 * (A_11 * A_11tail + A_12 * A_12tail) * (A_21 * A_32 - A_22 * A_31))
+ ((A_21 * A_21 + A_22 * A_22) * ((A_31 * A_12tail + A_12 * A_31tail)
- (A_32 * A_11tail + A_11 * A_32tail))
+ 2 * (A_21 * A_21tail + A_22 * A_22tail) * (A_31 * A_12 - A_32 * A_11))
+ ((A_31 * A_31 + A_32 * A_32) * ((A_11 * A_22tail + A_22 * A_11tail)
- (A_12 * A_21tail + A_21 * A_12tail))
+ 2 * (A_31 * A_31tail + A_32 * A_32tail) * (A_11 * A_22 - A_12 * A_21));
//if (std::abs(det) >= absolute_bound)
//{
return det;
//}
}
}} // namespace detail::precise_math
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_EXTENSIONS_TRIANGULATION_STRATEGIES_CARTESIAN_DETAIL_PRECISE_MATH_HPP
+26
View File
@@ -0,0 +1,26 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
#define BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
#include <boost/config/header_deprecated.hpp>
BOOST_HEADER_DEPRECATED("boost/geometry/core/coordinate_promotion.hpp")
#include <boost/geometry/core/coordinate_promotion.hpp>
#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
+299
View File
@@ -0,0 +1,299 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
#define BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
// For now deactivate the use of multiprecision integers
// TODO: activate it later
#define BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
#include <climits>
#include <cstddef>
#include <type_traits>
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
#include <boost/multiprecision/cpp_int.hpp>
#endif
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace promote_integral
{
// meta-function that returns the bit size of a type
template
<
typename T,
bool IsFundamental = std::is_fundamental<T>::value
>
struct bit_size
{};
// for fundamental types, just return CHAR_BIT * sizeof(T)
template <typename T>
struct bit_size<T, true>
: std::integral_constant<std::size_t, (CHAR_BIT * sizeof(T))>
{};
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
// partial specialization for cpp_int
template
<
unsigned MinSize,
unsigned MaxSize,
boost::multiprecision::cpp_integer_type SignType,
boost::multiprecision::cpp_int_check_type Checked,
typename Allocator,
boost::multiprecision::expression_template_option ExpressionTemplates
>
struct bit_size
<
boost::multiprecision::number
<
boost::multiprecision::cpp_int_backend
<
MinSize, MaxSize, SignType, Checked, Allocator
>,
ExpressionTemplates
>,
false
>
: std::integral_constant<std::size_t, MaxSize>
{};
#endif // BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
template <typename T, std::size_t MinSize, typename ...Ts>
struct promote_to_larger
{
// if promotion fails, keep the number T
// (and cross fingers that overflow will not occur)
typedef T type;
};
template <typename T, std::size_t MinSize, typename CurrentT, typename ...Ts>
struct promote_to_larger<T, MinSize, CurrentT, Ts...>
{
typedef std::conditional_t
<
(bit_size<CurrentT>::value >= MinSize),
CurrentT,
typename promote_to_larger<T, MinSize, Ts...>::type
> type;
};
template <typename ...Ts>
struct integral_types {};
template <typename T, std::size_t MinSize, typename ...Ts>
struct promote_to_larger<T, MinSize, integral_types<Ts...>>
: promote_to_larger<T, MinSize, Ts...>
{};
}} // namespace detail::promote_integral
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Meta-function to define an integral type with size
than is (roughly) twice the bit size of T
\ingroup utility
\details
This meta-function tries to promote the fundamental integral type T
to a another integral type with size (roughly) twice the bit size of T.
To do this, two times the bit size of T is tested against the bit sizes of:
short, int, long, long long, boost::int128_t
and the one that first matches is chosen.
For unsigned types the bit size of T is tested against the bit
sizes of the types above, if T is promoted to a signed type, or
the bit sizes of
unsigned short, unsigned int, unsigned long, std::size_t,
unsigned long long, boost::uint128_t
if T is promoted to an unsigned type.
By default an unsigned type is promoted to a signed type.
This behavior is controlled by the PromoteUnsignedToUnsigned
boolean template parameter, whose default value is "false".
To promote an unsigned type to an unsigned type set the value of
this template parameter to "true".
If the macro BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is not
defined, boost's multiprecision integer cpp_int<> is used as a
last resort.
If BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is defined and an
appropriate type cannot be detected, the input type is returned as is.
Finally, if the passed type is either a floating-point type or a
user-defined type it is returned as is.
\note boost::int128_type and boost::uint128_type are considered
only if the macros BOOST_HAS_INT128 and BOOST_GEOMETRY_ENABLE_INT128
are defined
*/
template
<
typename T,
bool PromoteUnsignedToUnsigned = false,
bool UseCheckedInteger = false,
bool IsIntegral = std::is_integral<T>::value
>
class promote_integral
{
private:
static bool const is_unsigned = std::is_unsigned<T>::value;
typedef detail::promote_integral::bit_size<T> bit_size_type;
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
// Define the proper check policy for the multiprecision integer
typedef std::conditional_t
<
UseCheckedInteger,
std::integral_constant
<
boost::multiprecision::cpp_int_check_type,
boost::multiprecision::checked
>,
std::integral_constant
<
boost::multiprecision::cpp_int_check_type,
boost::multiprecision::unchecked
>
> check_policy_type;
// Meta-function to get the multiprecision integer type for the
// given size and sign type (signed/unsigned)
template
<
unsigned int Size,
boost::multiprecision::cpp_integer_type SignType
>
struct multiprecision_integer_type
{
typedef boost::multiprecision::number
<
boost::multiprecision::cpp_int_backend
<
Size,
Size,
SignType,
check_policy_type::value,
void
>
> type;
};
#endif
// Define the minimum size (in bits) needed for the promoted type
// If T is the input type and P the promoted type, then the
// minimum number of bits for P are (below b stands for the number
// of bits of T):
// * if T is unsigned and P is unsigned: 2 * b
// * if T is signed and P is signed: 2 * b - 1
// * if T is unsigned and P is signed: 2 * b + 1
typedef std::conditional_t
<
(PromoteUnsignedToUnsigned && is_unsigned),
std::integral_constant<std::size_t, (2 * bit_size_type::value)>,
std::conditional_t
<
is_unsigned,
std::integral_constant<std::size_t, (2 * bit_size_type::value + 1)>,
std::integral_constant<std::size_t, (2 * bit_size_type::value - 1)>
>
> min_bit_size_type;
// Define the list of signed integral types we are going to use
// for promotion
typedef detail::promote_integral::integral_types
<
short,
int,
long,
long long
#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
, boost::int128_type
#endif
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
, typename multiprecision_integer_type
<
min_bit_size_type::value,
boost::multiprecision::signed_magnitude
>::type
#endif
> signed_integral_types;
// Define the list of unsigned integral types we are going to use
// for promotion
typedef detail::promote_integral::integral_types
<
unsigned short,
unsigned int,
unsigned long,
std::size_t,
unsigned long long
#if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
, boost::uint128_type
#endif
#if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
, typename multiprecision_integer_type
<
min_bit_size_type::value,
boost::multiprecision::unsigned_magnitude
>::type
#endif
> unsigned_integral_types;
// Define the list of integral types that will be used for
// promotion (depending in whether we was to promote unsigned to
// unsigned or not)
typedef std::conditional_t
<
(is_unsigned && PromoteUnsignedToUnsigned),
unsigned_integral_types,
signed_integral_types
> integral_types;
public:
typedef typename detail::promote_integral::promote_to_larger
<
T,
min_bit_size_type::value,
integral_types
>::type type;
};
template <typename T, bool PromoteUnsignedToUnsigned, bool UseCheckedInteger>
class promote_integral
<
T, PromoteUnsignedToUnsigned, UseCheckedInteger, false
>
{
public:
typedef T type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
+435
View File
@@ -0,0 +1,435 @@
// Boost.Geometry
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// This file was modified by Oracle on 2013-2021.
// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_RANGE_HPP
#define BOOST_GEOMETRY_UTIL_RANGE_HPP
#include <algorithm>
#include <iterator>
#include <type_traits>
#include <boost/concept_check.hpp>
#include <boost/config.hpp>
#include <boost/core/addressof.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/range/concepts.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/has_range_iterator.hpp>
#include <boost/range/iterator.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/mutable_range.hpp>
namespace boost { namespace geometry { namespace range
{
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(iterator_category)
template <typename T>
struct is_iterator
: std::integral_constant
<
bool,
has_iterator_category
<
std::iterator_traits<T>
>::value
>
{};
template <typename T, bool HasIterator = boost::has_range_iterator<T>::value>
struct is_range_impl
: is_iterator
<
typename boost::range_iterator<T>::type
>
{};
template <typename T>
struct is_range_impl<T, false>
: std::false_type
{};
template <typename T>
struct is_range
: is_range_impl<T>
{};
template <typename Range, typename T = void>
using enable_if_mutable_t = std::enable_if_t
<
(! std::is_const<std::remove_reference_t<Range>>::value),
T
>;
} // namespace detail
/*!
\brief Short utility to conveniently return an iterator of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_iterator<RandomAccessRange>::type
pos(RandomAccessRange && rng,
typename boost::range_size<RandomAccessRange>::type i)
{
BOOST_RANGE_CONCEPT_ASSERT((boost::RandomAccessRangeConcept<RandomAccessRange>));
BOOST_GEOMETRY_ASSERT(i <= boost::size(rng));
return boost::begin(rng)
+ static_cast<typename boost::range_difference<RandomAccessRange>::type>(i);
}
/*!
\brief Short utility to conveniently return an element of a RandomAccessRange.
\ingroup utility
*/
template <typename RandomAccessRange>
inline typename boost::range_reference<RandomAccessRange>::type
at(RandomAccessRange && rng,
typename boost::range_size<RandomAccessRange>::type i)
{
return *pos(rng, i);
}
/*!
\brief Short utility to conveniently return the front element of a Range.
\ingroup utility
*/
template <typename Range>
inline typename boost::range_reference<Range>::type
front(Range && rng)
{
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
return *boost::begin(rng);
}
/*!
\brief Short utility to conveniently return the back element of a BidirectionalRange.
\ingroup utility
*/
template <typename BidirectionalRange>
inline typename boost::range_reference<BidirectionalRange>::type
back(BidirectionalRange && rng)
{
BOOST_RANGE_CONCEPT_ASSERT((boost::BidirectionalRangeConcept<BidirectionalRange>));
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
auto it = boost::end(rng);
return *(--it);
}
/*!
\brief Short utility to conveniently clear a mutable range.
It uses traits::clear<>.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline void clear(Range && rng)
{
geometry::traits::clear
<
std::remove_reference_t<Range>
>::apply(rng);
}
/*!
\brief Short utility to conveniently insert a new element at the end of a mutable range.
It uses boost::geometry::traits::push_back<>.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline void push_back(Range && rng,
typename boost::range_value<Range>::type const& value)
{
geometry::traits::push_back
<
std::remove_reference_t<Range>
>::apply(rng, value);
}
/*!
\brief Short utility to conveniently insert a new element at the end of a mutable range.
It uses boost::geometry::traits::push_back<>.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline void push_back(Range && rng,
typename boost::range_value<Range>::type && value)
{
geometry::traits::push_back
<
std::remove_reference_t<Range>
>::apply(rng, std::move(value));
}
/*!
\brief Short utility to conveniently insert a new element at the end of a mutable range.
It uses boost::geometry::traits::emplace_back<>.
\ingroup utility
*/
template
<
typename Range,
typename ...Args,
detail::enable_if_mutable_t<Range, int> = 0
>
inline void emplace_back(Range && rng, Args &&... args)
{
geometry::traits::emplace_back
<
std::remove_reference_t<Range>
>::apply(rng, std::forward<Args>(args)...);
}
/*!
\brief Short utility to conveniently resize a mutable range.
It uses boost::geometry::traits::resize<>.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline void resize(Range && rng,
typename boost::range_size<Range>::type new_size)
{
geometry::traits::resize
<
std::remove_reference_t<Range>
>::apply(rng, new_size);
}
/*!
\brief Short utility to conveniently remove an element from the back of a mutable range.
It uses resize().
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline void pop_back(Range && rng)
{
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
range::resize(rng, boost::size(rng) - 1);
}
/*!
\brief Short utility to conveniently remove an element from a mutable range.
It uses std::move() and resize(). Version taking mutable iterators.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline typename boost::range_iterator<Range>::type
erase(Range && rng,
typename boost::range_iterator<Range>::type it)
{
BOOST_GEOMETRY_ASSERT(!boost::empty(rng));
BOOST_GEOMETRY_ASSERT(it != boost::end(rng));
typename boost::range_difference<Range>::type const
d = std::distance(boost::begin(rng), it);
typename boost::range_iterator<Range>::type
next = it;
++next;
std::move(next, boost::end(rng), it);
range::resize(rng, boost::size(rng) - 1);
// NOTE: In general this should be sufficient:
// return it;
// But in MSVC using the returned iterator causes
// assertion failures when iterator debugging is enabled
// Furthermore the code below should work in the case if resize()
// invalidates iterators when the container is resized down.
return boost::begin(rng) + d;
}
/*!
\brief Short utility to conveniently remove an element from a mutable range.
It uses std::move() and resize(). Version taking non-mutable iterators.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline typename boost::range_iterator<Range>::type
erase(Range && rng,
typename boost::range_iterator<std::remove_reference_t<Range> const>::type cit)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
typename boost::range_iterator<Range>::type
it = boost::begin(rng)
+ std::distance(boost::const_begin(rng), cit);
return range::erase(rng, it);
}
/*!
\brief Short utility to conveniently remove a range of elements from a mutable range.
It uses std::move() and resize(). Version taking mutable iterators.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline typename boost::range_iterator<Range>::type
erase(Range && rng,
typename boost::range_iterator<Range>::type first,
typename boost::range_iterator<Range>::type last)
{
typename boost::range_difference<Range>::type const
diff = std::distance(first, last);
BOOST_GEOMETRY_ASSERT(diff >= 0);
std::size_t const count = static_cast<std::size_t>(diff);
BOOST_GEOMETRY_ASSERT(count <= boost::size(rng));
if ( count > 0 )
{
typename boost::range_difference<Range>::type const
d = std::distance(boost::begin(rng), first);
std::move(last, boost::end(rng), first);
range::resize(rng, boost::size(rng) - count);
// NOTE: In general this should be sufficient:
// return first;
// But in MSVC using the returned iterator causes
// assertion failures when iterator debugging is enabled
// Furthermore the code below should work in the case if resize()
// invalidates iterators when the container is resized down.
return boost::begin(rng) + d;
}
return first;
}
/*!
\brief Short utility to conveniently remove a range of elements from a mutable range.
It uses std::move() and resize(). Version taking non-mutable iterators.
\ingroup utility
*/
template
<
typename Range,
detail::enable_if_mutable_t<Range, int> = 0
>
inline typename boost::range_iterator<Range>::type
erase(Range && rng,
typename boost::range_iterator<std::remove_reference_t<Range> const>::type cfirst,
typename boost::range_iterator<std::remove_reference_t<Range> const>::type clast)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
typename boost::range_iterator<Range>::type
first = boost::begin(rng)
+ std::distance(boost::const_begin(rng), cfirst);
typename boost::range_iterator<Range>::type
last = boost::begin(rng)
+ std::distance(boost::const_begin(rng), clast);
return range::erase(rng, first, last);
}
// back_inserter
template <class Container>
class back_insert_iterator
{
public:
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
typedef Container container_type;
explicit back_insert_iterator(Container & c)
: container(boost::addressof(c))
{}
back_insert_iterator & operator=(typename Container::value_type const& value)
{
range::push_back(*container, value);
return *this;
}
back_insert_iterator & operator=(typename Container::value_type && value)
{
range::push_back(*container, std::move(value));
return *this;
}
back_insert_iterator & operator* ()
{
return *this;
}
back_insert_iterator & operator++ ()
{
return *this;
}
back_insert_iterator operator++(int)
{
return *this;
}
private:
Container * container;
};
template <typename Range>
inline back_insert_iterator<Range> back_inserter(Range & rng)
{
return back_insert_iterator<Range>(rng);
}
}}} // namespace boost::geometry::range
#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP
+179
View File
@@ -0,0 +1,179 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2011-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2011-2012 Mateusz Loskot, London, UK.
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_RATIONAL_HPP
#define BOOST_GEOMETRY_UTIL_RATIONAL_HPP
#include <boost/rational.hpp>
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/geometry/util/coordinate_cast.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost{ namespace geometry
{
// Specialize for Boost.Geometry's coordinate cast
// (from string to coordinate type)
namespace detail
{
template <typename T>
struct coordinate_cast<rational<T> >
{
static inline void split_parts(std::string const& source, std::string::size_type p,
T& before, T& after, bool& negate, std::string::size_type& len)
{
std::string before_part = source.substr(0, p);
std::string const after_part = source.substr(p + 1);
negate = false;
if (before_part.size() > 0 && before_part[0] == '-')
{
negate = true;
before_part.erase(0, 1);
}
before = atol(before_part.c_str());
after = atol(after_part.c_str());
len = after_part.length();
}
static inline rational<T> apply(std::string const& source)
{
T before, after;
bool negate;
std::string::size_type len;
// Note: decimal comma is not (yet) supported, it does (and should) not
// occur in a WKT, where points are comma separated.
std::string::size_type p = source.find('.');
if (p == std::string::npos)
{
p = source.find('/');
if (p == std::string::npos)
{
return rational<T>(atol(source.c_str()));
}
split_parts(source, p, before, after, negate, len);
return negate
? -rational<T>(before, after)
: rational<T>(before, after)
;
}
split_parts(source, p, before, after, negate, len);
T den = 1;
for (std::string::size_type i = 0; i < len; i++)
{
den *= 10;
}
return negate
? -rational<T>(before) - rational<T>(after, den)
: rational<T>(before) + rational<T>(after, den)
;
}
};
} // namespace detail
// Specialize for Boost.Geometry's select_most_precise
template <typename T1, typename T2>
struct select_most_precise<boost::rational<T1>, boost::rational<T2> >
{
typedef typename boost::rational
<
typename select_most_precise<T1, T2>::type
> type;
};
template <typename T>
struct select_most_precise<boost::rational<T>, double>
{
typedef typename boost::rational<T> type;
};
}} // namespace boost::geometry
// Specializes boost::rational to boost::numeric::bounds
namespace boost { namespace numeric
{
template<class T>
struct bounds<rational<T> >
{
static inline rational<T> lowest()
{
return rational<T>(bounds<T>::lowest(), 1);
}
static inline rational<T> highest()
{
return rational<T>(bounds<T>::highest(), 1);
}
};
}} // namespace boost::numeric
// Support for boost::numeric_cast to int and to double (necessary for SVG-mapper)
namespace boost { namespace numeric
{
template
<
typename T,
typename Traits,
typename OverflowHandler,
typename Float2IntRounder,
typename RawConverter,
typename UserRangeChecker
>
struct converter<int, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
{
static inline int convert(rational<T> const& arg)
{
return int(rational_cast<double>(arg));
}
};
template
<
typename T,
typename Traits,
typename OverflowHandler,
typename Float2IntRounder,
typename RawConverter,
typename UserRangeChecker
>
struct converter<double, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
{
static inline double convert(rational<T> const& arg)
{
return rational_cast<double>(arg);
}
};
}}
#endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP
+76
View File
@@ -0,0 +1,76 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function selecting the "calculation" type
\details Based on two input geometry types, and an input calculation type,
(which defaults to void in the calling function), this meta-function
selects the most appropriate:
- if calculation type is specified, that one is used,
- if it is void, the most precise of the two points is used
\ingroup utility
*/
template <typename Geometry1, typename Geometry2, typename CalculationType>
struct select_calculation_type
{
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
typename select_coordinate_type
<
Geometry1,
Geometry2
>::type,
CalculationType
> type;
};
// alternative version supporting more than 2 Geometries
template
<
typename CalculationType,
typename ...Geometries
>
struct select_calculation_type_alt
{
typedef std::conditional_t
<
std::is_void<CalculationType>::value,
typename select_coordinate_type
<
Geometries...
>::type,
CalculationType
> type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
+48
View File
@@ -0,0 +1,48 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
#define BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function selecting the most precise coordinate type
of geometries
\ingroup utility
*/
template <typename ...Geometries>
struct select_coordinate_type
{
typedef typename select_most_precise
<
typename coordinate_type<Geometries>::type...
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
+148
View File
@@ -0,0 +1,148 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2020.
// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
#define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
#include <type_traits>
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace select_most_precise
{
// 0 - void
// 1 - integral
// 2 - floating point
// 3 - non-fundamental
template <typename T>
struct type_priority
: std::conditional_t
<
std::is_void<T>::value,
std::integral_constant<int, 0>,
std::conditional_t
<
std::is_fundamental<T>::value,
std::conditional_t
<
std::is_floating_point<T>::value,
std::integral_constant<int, 2>,
std::integral_constant<int, 1>
>,
std::integral_constant<int, 3>
>
>
{};
template <typename T>
struct type_size
: std::integral_constant<std::size_t, sizeof(T)>
{};
template <>
struct type_size<void>
: std::integral_constant<std::size_t, 0>
{};
}} // namespace detail::select_most_precise
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Meta-function to select the most accurate type for
calculations
\ingroup utility
\details select_most_precise classes, compares types on compile time.
For example, if an addition must be done with a double and an integer, the
result must be a double.
If both types are integer, the result can be an integer.
\note It is different from the "promote" class, already in boost. That
class promotes e.g. a (one) float to a double. This class selects a
type from two types. It takes the most accurate, but does not promote
afterwards.
\note If the input is a non-fundamental type, it might be a calculation
type such as a GMP-value or another high precision value. Therefore,
if one is non-fundamental, that one is chosen.
\note If both types are non-fundamental, the result is indeterminate and
currently the first one is chosen.
*/
template <typename ...Types>
struct select_most_precise
{
typedef void type;
};
template <typename T>
struct select_most_precise<T>
{
typedef T type;
};
template <typename T1, typename T2>
struct select_most_precise<T1, T2>
{
static const int priority1 = detail::select_most_precise::type_priority<T1>::value;
static const int priority2 = detail::select_most_precise::type_priority<T2>::value;
static const std::size_t size1 = detail::select_most_precise::type_size<T1>::value;
static const std::size_t size2 = detail::select_most_precise::type_size<T2>::value;
typedef std::conditional_t
<
(priority1 > priority2),
T1,
std::conditional_t
<
(priority2 > priority1),
T2,
std::conditional_t // priority1 == priority2
<
(priority1 == 0 || priority1 == 3), // both void or non-fundamental
T1,
std::conditional_t // both fundamental
<
(size2 > size1),
T2,
T1
>
>
>
> type;
};
template <typename T1, typename T2, typename ...Types>
struct select_most_precise<T1, T2, Types...>
{
typedef typename select_most_precise
<
typename select_most_precise<T1, T2>::type,
typename select_most_precise<Types...>::type
>::type type;
};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
+299
View File
@@ -0,0 +1,299 @@
// Boost.Geometry
// Copyright (c) 2020-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
#define BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
#include <utility>
#include <type_traits>
namespace boost { namespace geometry
{
namespace util
{
// An alternative would be to use std:tuple and std::pair
// but it would add dependency.
template <typename ...Ts>
struct type_sequence {};
// true if T is a sequence
template <typename T>
struct is_sequence : std::false_type {};
template <typename ...Ts>
struct is_sequence<type_sequence<Ts...>> : std::true_type {};
template <typename T, T ...Is>
struct is_sequence<std::integer_sequence<T, Is...>> : std::true_type {};
// number of elements in a sequence
template <typename Sequence>
struct sequence_size {};
template <typename ...Ts>
struct sequence_size<type_sequence<Ts...>>
: std::integral_constant<std::size_t, sizeof...(Ts)>
{};
template <typename T, T ...Is>
struct sequence_size<std::integer_sequence<T, Is...>>
: std::integral_constant<std::size_t, sizeof...(Is)>
{};
// element of a sequence
template <std::size_t I, typename Sequence>
struct sequence_element {};
template <std::size_t I, typename T, typename ...Ts>
struct sequence_element<I, type_sequence<T, Ts...>>
{
using type = typename sequence_element<I - 1, type_sequence<Ts...>>::type;
};
template <typename T, typename ...Ts>
struct sequence_element<0, type_sequence<T, Ts...>>
{
using type = T;
};
template <std::size_t I, typename T, T J, T ...Js>
struct sequence_element<I, std::integer_sequence<T, J, Js...>>
: std::integral_constant
<
T,
sequence_element<I - 1, std::integer_sequence<T, Js...>>::value
>
{};
template <typename T, T J, T ...Js>
struct sequence_element<0, std::integer_sequence<T, J, Js...>>
: std::integral_constant<T, J>
{};
template <typename ...Ts>
struct pack_front
{
static_assert(sizeof...(Ts) > 0, "Parameter pack can not be empty.");
};
template <typename T, typename ... Ts>
struct pack_front<T, Ts...>
{
typedef T type;
};
template <typename Sequence>
struct sequence_front
: sequence_element<0, Sequence>
{
static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
};
template <typename Sequence>
struct sequence_back
: sequence_element<sequence_size<Sequence>::value - 1, Sequence>
{
static_assert(sequence_size<Sequence>::value > 0, "Sequence can not be empty.");
};
template <typename Sequence>
struct sequence_empty
: std::integral_constant
<
bool,
sequence_size<Sequence>::value == 0
>
{};
// Defines type member for the first type in sequence that satisfies UnaryPred.
template
<
typename Sequence,
template <typename> class UnaryPred
>
struct sequence_find_if {};
template
<
typename T, typename ...Ts,
template <typename> class UnaryPred
>
struct sequence_find_if<type_sequence<T, Ts...>, UnaryPred>
: std::conditional
<
UnaryPred<T>::value,
T,
// TODO: prevent instantiation for the rest of the sequence if value is true
typename sequence_find_if<type_sequence<Ts...>, UnaryPred>::type
>
{};
template <template <typename> class UnaryPred>
struct sequence_find_if<type_sequence<>, UnaryPred>
{
// TODO: This is technically incorrect because void can be stored in a type_sequence
using type = void;
};
// sequence_merge<type_sequence<A, B>, type_sequence<C, D>>::type is
// type_sequence<A, B, C, D>
// sequence_merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
// integer_sequence<A, B, C, D>
template <typename ...Sequences>
struct sequence_merge;
template <typename S>
struct sequence_merge<S>
{
using type = S;
};
template <typename ...T1s, typename ...T2s>
struct sequence_merge<type_sequence<T1s...>, type_sequence<T2s...>>
{
using type = type_sequence<T1s..., T2s...>;
};
template <typename T, T ...I1s, T ...I2s>
struct sequence_merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
{
using type = std::integer_sequence<T, I1s..., I2s...>;
};
template <typename S1, typename S2, typename ...Sequences>
struct sequence_merge<S1, S2, Sequences...>
{
using type = typename sequence_merge
<
typename sequence_merge<S1, S2>::type,
typename sequence_merge<Sequences...>::type
>::type;
};
// sequence_combine<type_sequence<A, B>, type_sequence<C, D>>::type is
// type_sequence<type_sequence<A, C>, type_sequence<A, D>,
// type_sequence<B, C>, type_sequence<B, D>>
template <typename Sequence1, typename Sequence2>
struct sequence_combine;
template <typename ...T1s, typename ...T2s>
struct sequence_combine<type_sequence<T1s...>, type_sequence<T2s...>>
{
template <typename T1>
using type_sequence_t = type_sequence<type_sequence<T1, T2s>...>;
using type = typename sequence_merge<type_sequence_t<T1s>...>::type;
};
// sequence_combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
// type_sequence<integer_sequence<T, 1, 3>, integer_sequence<T, 1, 4>,
// integer_sequence<T, 2, 3>, integer_sequence<T, 2, 4>>
template <typename T, T ...I1s, T ...I2s>
struct sequence_combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
{
template <T I1>
using type_sequence_t = type_sequence<std::integer_sequence<T, I1, I2s>...>;
using type = typename sequence_merge<type_sequence_t<I1s>...>::type;
};
// Selects least element from a parameter pack based on
// LessPred<T1, T2>::value comparison, similar to std::min_element
template
<
template <typename, typename> class LessPred,
typename ...Ts
>
struct pack_min_element;
template
<
template <typename, typename> class LessPred,
typename T
>
struct pack_min_element<LessPred, T>
{
using type = T;
};
template
<
template <typename, typename> class LessPred,
typename T1, typename T2
>
struct pack_min_element<LessPred, T1, T2>
{
using type = std::conditional_t<LessPred<T1, T2>::value, T1, T2>;
};
template
<
template <typename, typename> class LessPred,
typename T1, typename T2, typename ...Ts
>
struct pack_min_element<LessPred, T1, T2, Ts...>
{
using type = typename pack_min_element
<
LessPred,
typename pack_min_element<LessPred, T1, T2>::type,
typename pack_min_element<LessPred, Ts...>::type
>::type;
};
// Selects least element from a sequence based on
// LessPred<T1, T2>::value comparison, similar to std::min_element
template
<
typename Sequence,
template <typename, typename> class LessPred
>
struct sequence_min_element;
template
<
typename ...Ts,
template <typename, typename> class LessPred
>
struct sequence_min_element<type_sequence<Ts...>, LessPred>
{
using type = typename pack_min_element<LessPred, Ts...>::type;
};
// TODO: Since there are two kinds of parameter packs and sequences there probably should be two
// versions of sequence_find_if as well as parameter_pack_min_element and sequence_min_element.
// Currently these utilities support only types.
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
+759
View File
@@ -0,0 +1,759 @@
// Boost.Geometry
// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan.
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program.
// This file was modified by Oracle on 2019.
// Modifications copyright (c) 2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// This file is converted from GeographicLib, https://geographiclib.sourceforge.io
// GeographicLib is originally written by Charles Karney.
// Author: Charles Karney (2008-2017)
// Last updated version of GeographicLib: 1.49
// Original copyright notice:
// Copyright (c) Charles Karney (2008-2017) <charles@karney.com> and licensed
// under the MIT/X11 License. For more information, see
// https://geographiclib.sourceforge.io
#ifndef BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP
#define BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP
#include <boost/array.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry { namespace series_expansion {
/*
Generate and evaluate the series expansion of the following integral
I1 = integrate( sqrt(1+k2*sin(sigma1)^2), sigma1, 0, sigma )
which is valid for k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
and expand (1 - eps) * I1 retaining terms up to order eps^maxpow
in A1 and C1[l].
The resulting series is of the form
A1 * ( sigma + sum(C1[l] * sin(2*l*sigma), l, 1, maxpow) ).
The scale factor A1-1 = mean value of (d/dsigma)I1 - 1
The expansion above is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_A1 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
To replace each number x by CT(x) the following
script can be used:
sed -e 's/[0-9]\+/CT(&)/g; s/\[CT/\[/g; s/)\]/\]/g;
s/case\sCT(/case /g; s/):/:/g; s/epsCT(2)/eps2/g;'
*/
template <size_t SeriesOrder, typename CT>
inline CT evaluate_A1(CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT t;
switch (SeriesOrder/2)
{
case 0:
t = CT(0);
break;
case 1:
t = eps2/CT(4);
break;
case 2:
t = eps2*(eps2+CT(16))/CT(64);
break;
case 3:
t = eps2*(eps2*(eps2+CT(4))+CT(64))/CT(256);
break;
default:
t = eps2*(eps2*(eps2*(CT(25)*eps2+CT(64))+CT(256))+CT(4096))/CT(16384);
break;
}
return (t + eps) / (CT(1) - eps);
}
/*
Generate and evaluate the series expansion of the following integral
I2 = integrate( 1/sqrt(1+k2*sin(sigma1)^2), sigma1, 0, sigma )
which is valid for k2 small. We substitute k2 = 4 * eps / (1 - eps)^2
and expand (1 - eps) * I2 retaining terms up to order eps^maxpow
in A2 and C2[l].
The resulting series is of the form
A2 * ( sigma + sum(C2[l] * sin(2*l*sigma), l, 1, maxpow) )
The scale factor A2-1 = mean value of (d/dsigma)2 - 1
The expansion above is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_A2 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <size_t SeriesOrder, typename CT>
inline CT evaluate_A2(CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT t;
switch (SeriesOrder/2)
{
case 0:
t = CT(0);
break;
case 1:
t = -CT(3)*eps2/CT(4);
break;
case 2:
t = (-CT(7)*eps2-CT(48))*eps2/CT(64);
break;
case 3:
t = eps2*((-CT(11)*eps2-CT(28))*eps2-CT(192))/CT(256);
break;
default:
t = eps2*(eps2*((-CT(375)*eps2-CT(704))*eps2-CT(1792))-CT(12288))/CT(16384);
break;
}
return (t - eps) / (CT(1) + eps);
}
/*
Express
I3 = integrate( (2-f)/(1+(1-f)*sqrt(1+k2*sin(sigma1)^2)), sigma1, 0, sigma )
as a series
A3 * ( sigma + sum(C3[l] * sin(2*l*sigma), l, 1, maxpow-1) )
valid for f and k2 small. It is convenient to write k2 = 4 * eps / (1 -
eps)^2 and f = 2*n/(1+n) and expand in eps and n. This procedure leads
to a series where the coefficients of eps^j are terminating series in n.
The scale factor A3 = mean value of (d/dsigma)I3
The expansion above is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_A3 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_A3(Coeffs &c, CT const& n)
{
switch (int(Coeffs::static_size))
{
case 0:
break;
case 1:
c[0] = CT(1);
break;
case 2:
c[0] = CT(1);
c[1] = -CT(1)/CT(2);
break;
case 3:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = -CT(1)/CT(4);
break;
case 4:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (-n-CT(2))/CT(8);
c[3] = -CT(1)/CT(16);
break;
case 5:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = (-CT(3)*n-CT(1))/CT(16);
c[4] = -CT(3)/CT(64);
break;
case 6:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = ((-n-CT(3))*n-CT(1))/CT(16);
c[4] = (-CT(2)*n-CT(3))/CT(64);
c[5] = -CT(3)/CT(128);
break;
case 7:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = (n*(n*(CT(5)*n-CT(1))-CT(3))-CT(1))/CT(16);
c[4] = ((-CT(10)*n-CT(2))*n-CT(3))/CT(64);
c[5] = (-CT(5)*n-CT(3))/CT(128);
c[6] = -CT(5)/CT(256);
break;
default:
c[0] = CT(1);
c[1] = (n-CT(1))/CT(2);
c[2] = (n*(CT(3)*n-CT(1))-CT(2))/CT(8);
c[3] = (n*(n*(CT(5)*n-CT(1))-CT(3))-CT(1))/CT(16);
c[4] = (n*((-CT(5)*n-CT(20))*n-CT(4))-CT(6))/CT(128);
c[5] = ((-CT(5)*n-CT(10))*n-CT(6))/CT(256);
c[6] = (-CT(15)*n-CT(20))/CT(1024);
c[7] = -CT(25)/CT(2048);
break;
}
}
/*
The coefficients C1[l] in the Fourier expansion of B1.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C1 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_C1(Coeffs &c, CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT d = eps;
switch (int(Coeffs::static_size) - 1)
{
case 0:
break;
case 1:
c[1] = -d/CT(2);
break;
case 2:
c[1] = -d/CT(2);
d *= eps;
c[2] = -d/CT(16);
break;
case 3:
c[1] = d*(CT(3)*eps2-CT(8))/CT(16);
d *= eps;
c[2] = -d/CT(16);
d *= eps;
c[3] = -d/CT(48);
break;
case 4:
c[1] = d*(CT(3)*eps2-CT(8))/CT(16);
d *= eps;
c[2] = d*(eps2-CT(2))/CT(32);
d *= eps;
c[3] = -d/CT(48);
d *= eps;
c[4] = -CT(5)*d/CT(512);
break;
case 5:
c[1] = d*((CT(6)-eps2)*eps2-CT(16))/CT(32);
d *= eps;
c[2] = d*(eps2-CT(2))/CT(32);
d *= eps;
c[3] = d*(CT(9)*eps2-CT(16))/CT(768);
d *= eps;
c[4] = -CT(5)*d/CT(512);
d *= eps;
c[5] = -CT(7)*d/CT(1280);
break;
case 6:
c[1] = d*((CT(6)-eps2)*eps2-CT(16))/CT(32);
d *= eps;
c[2] = d*((CT(64)-CT(9)*eps2)*eps2-CT(128))/CT(2048);
d *= eps;
c[3] = d*(CT(9)*eps2-CT(16))/CT(768);
d *= eps;
c[4] = d*(CT(3)*eps2-CT(5))/CT(512);
d *= eps;
c[5] = -CT(7)*d/CT(1280);
d *= eps;
c[6] = -CT(7)*d/CT(2048);
break;
case 7:
c[1] = d*(eps2*(eps2*(CT(19)*eps2-CT(64))+CT(384))-CT(1024))/CT(2048);
d *= eps;
c[2] = d*((CT(64)-CT(9)*eps2)*eps2-CT(128))/CT(2048);
d *= eps;
c[3] = d*((CT(72)-CT(9)*eps2)*eps2-CT(128))/CT(6144);
d *= eps;
c[4] = d*(CT(3)*eps2-CT(5))/CT(512);
d *= eps;
c[5] = d*(CT(35)*eps2-CT(56))/CT(10240);
d *= eps;
c[6] = -CT(7)*d/CT(2048);
d *= eps;
c[7] = -CT(33)*d/CT(14336);
break;
default:
c[1] = d*(eps2*(eps2*(CT(19)*eps2-CT(64))+CT(384))-CT(1024))/CT(2048);
d *= eps;
c[2] = d*(eps2*(eps2*(CT(7)*eps2-CT(18))+CT(128))-CT(256))/CT(4096);
d *= eps;
c[3] = d*((CT(72)-CT(9)*eps2)*eps2-CT(128))/CT(6144);
d *= eps;
c[4] = d*((CT(96)-CT(11)*eps2)*eps2-CT(160))/CT(16384);
d *= eps;
c[5] = d*(CT(35)*eps2-CT(56))/CT(10240);
d *= eps;
c[6] = d*(CT(9)*eps2-CT(14))/CT(4096);
d *= eps;
c[7] = -CT(33)*d/CT(14336);
d *= eps;
c[8] = -CT(429)*d/CT(262144);
break;
}
}
/*
The coefficients C1p[l] in the Fourier expansion of B1p.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C1p below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_C1p(Coeffs& c, CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT d = eps;
switch (int(Coeffs::static_size) - 1)
{
case 0:
break;
case 1:
c[1] = d/CT(2);
break;
case 2:
c[1] = d/CT(2);
d *= eps;
c[2] = CT(5)*d/CT(16);
break;
case 3:
c[1] = d*(CT(16)-CT(9)*eps2)/CT(32);
d *= eps;
c[2] = CT(5)*d/CT(16);
d *= eps;
c[3] = CT(29)*d/CT(96);
break;
case 4:
c[1] = d*(CT(16)-CT(9)*eps2)/CT(32);
d *= eps;
c[2] = d*(CT(30)-CT(37)*eps2)/CT(96);
d *= eps;
c[3] = CT(29)*d/CT(96);
d *= eps;
c[4] = CT(539)*d/CT(1536);
break;
case 5:
c[1] = d*(eps2*(CT(205)*eps2-CT(432))+CT(768))/CT(1536);
d *= eps;
c[2] = d*(CT(30)-CT(37)*eps2)/CT(96);
d *= eps;
c[3] = d*(CT(116)-CT(225)*eps2)/CT(384);
d *= eps;
c[4] = CT(539)*d/CT(1536);
d *= eps;
c[5] = CT(3467)*d/CT(7680);
break;
case 6:
c[1] = d*(eps2*(CT(205)*eps2-CT(432))+CT(768))/CT(1536);
d *= eps;
c[2] = d*(eps2*(CT(4005)*eps2-CT(4736))+CT(3840))/CT(12288);
d *= eps;
c[3] = d*(CT(116)-CT(225)*eps2)/CT(384);
d *= eps;
c[4] = d*(CT(2695)-CT(7173)*eps2)/CT(7680);
d *= eps;
c[5] = CT(3467)*d/CT(7680);
d *= eps;
c[6] = CT(38081)*d/CT(61440);
break;
case 7:
c[1] = d*(eps2*((CT(9840)-CT(4879)*eps2)*eps2-CT(20736))+CT(36864))/CT(73728);
d *= eps;
c[2] = d*(eps2*(CT(4005)*eps2-CT(4736))+CT(3840))/CT(12288);
d *= eps;
c[3] = d*(eps2*(CT(8703)*eps2-CT(7200))+CT(3712))/CT(12288);
d *= eps;
c[4] = d*(CT(2695)-CT(7173)*eps2)/CT(7680);
d *= eps;
c[5] = d*(CT(41604)-CT(141115)*eps2)/CT(92160);
d *= eps;
c[6] = CT(38081)*d/CT(61440);
d *= eps;
c[7] = CT(459485)*d/CT(516096);
break;
default:
c[1] = d*(eps2*((CT(9840)-CT(4879)*eps2)*eps2-CT(20736))+CT(36864))/CT(73728);
d *= eps;
c[2] = d*(eps2*((CT(120150)-CT(86171)*eps2)*eps2-CT(142080))+CT(115200))/CT(368640);
d *= eps;
c[3] = d*(eps2*(CT(8703)*eps2-CT(7200))+CT(3712))/CT(12288);
d *= eps;
c[4] = d*(eps2*(CT(1082857)*eps2-CT(688608))+CT(258720))/CT(737280);
d *= eps;
c[5] = d*(CT(41604)-CT(141115)*eps2)/CT(92160);
d *= eps;
c[6] = d*(CT(533134)-CT(2200311)*eps2)/CT(860160);
d *= eps;
c[7] = CT(459485)*d/CT(516096);
d *= eps;
c[8] = CT(109167851)*d/CT(82575360);
break;
}
}
/*
The coefficients C2[l] in the Fourier expansion of B2.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C2 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_C2(Coeffs& c, CT const& eps)
{
CT const eps2 = math::sqr(eps);
CT d = eps;
switch (int(Coeffs::static_size) - 1)
{
case 0:
break;
case 1:
c[1] = d/CT(2);
break;
case 2:
c[1] = d/CT(2);
d *= eps;
c[2] = CT(3)*d/CT(16);
break;
case 3:
c[1] = d*(eps2+CT(8))/CT(16);
d *= eps;
c[2] = CT(3)*d/CT(16);
d *= eps;
c[3] = CT(5)*d/CT(48);
break;
case 4:
c[1] = d*(eps2+CT(8))/CT(16);
d *= eps;
c[2] = d*(eps2+CT(6))/CT(32);
d *= eps;
c[3] = CT(5)*d/CT(48);
d *= eps;
c[4] = CT(35)*d/CT(512);
break;
case 5:
c[1] = d*(eps2*(eps2+CT(2))+CT(16))/CT(32);
d *= eps;
c[2] = d*(eps2+CT(6))/CT(32);
d *= eps;
c[3] = d*(CT(15)*eps2+CT(80))/CT(768);
d *= eps;
c[4] = CT(35)*d/CT(512);
d *= eps;
c[5] = CT(63)*d/CT(1280);
break;
case 6:
c[1] = d*(eps2*(eps2+CT(2))+CT(16))/CT(32);
d *= eps;
c[2] = d*(eps2*(CT(35)*eps2+CT(64))+CT(384))/CT(2048);
d *= eps;
c[3] = d*(CT(15)*eps2+CT(80))/CT(768);
d *= eps;
c[4] = d*(CT(7)*eps2+CT(35))/CT(512);
d *= eps;
c[5] = CT(63)*d/CT(1280);
d *= eps;
c[6] = CT(77)*d/CT(2048);
break;
case 7:
c[1] = d*(eps2*(eps2*(CT(41)*eps2+CT(64))+CT(128))+CT(1024))/CT(2048);
d *= eps;
c[2] = d*(eps2*(CT(35)*eps2+CT(64))+CT(384))/CT(2048);
d *= eps;
c[3] = d*(eps2*(CT(69)*eps2+CT(120))+CT(640))/CT(6144);
d *= eps;
c[4] = d*(CT(7)*eps2+CT(35))/CT(512);
d *= eps;
c[5] = d*(CT(105)*eps2+CT(504))/CT(10240);
d *= eps;
c[6] = CT(77)*d/CT(2048);
d *= eps;
c[7] = CT(429)*d/CT(14336);
break;
default:
c[1] = d*(eps2*(eps2*(CT(41)*eps2+CT(64))+CT(128))+CT(1024))/CT(2048);
d *= eps;
c[2] = d*(eps2*(eps2*(CT(47)*eps2+CT(70))+CT(128))+CT(768))/CT(4096);
d *= eps;
c[3] = d*(eps2*(CT(69)*eps2+CT(120))+CT(640))/CT(6144);
d *= eps;
c[4] = d*(eps2*(CT(133)*eps2+CT(224))+CT(1120))/CT(16384);
d *= eps;
c[5] = d*(CT(105)*eps2+CT(504))/CT(10240);
d *= eps;
c[6] = d*(CT(33)*eps2+CT(154))/CT(4096);
d *= eps;
c[7] = CT(429)*d/CT(14336);
d *= eps;
c[8] = CT(6435)*d/CT(262144);
break;
}
}
/*
The coefficients C3[l] in the Fourier expansion of B3.
The expansion below is performed in Maxima, a Computer Algebra System.
The C++ code (that yields the function evaluate_coeffs_C3 below) is
generated by the following Maxima script:
geometry/doc/other/maxima/geod.mac
*/
template <size_t SeriesOrder, typename Coeffs, typename CT>
inline void evaluate_coeffs_C3x(Coeffs &c, CT const& n) {
BOOST_GEOMETRY_ASSERT((Coeffs::static_size == (SeriesOrder * (SeriesOrder - 1)) / 2));
CT const n2 = math::sqr(n);
switch (SeriesOrder)
{
case 0:
break;
case 1:
break;
case 2:
c[0] = (CT(1)-n)/CT(4);
break;
case 3:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = ((n-CT(3))*n+CT(2))/CT(32);
break;
case 4:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = ((n-CT(3))*n+CT(2))/CT(32);
c[4] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[5] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
break;
case 5:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = ((n-CT(3))*n+CT(2))/CT(32);
c[5] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[6] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[7] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[8] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[9] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
break;
case 6:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
c[5] = ((n-CT(3))*n+CT(2))/CT(32);
c[6] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[7] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[8] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
c[9] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[10] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[11] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
c[12] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
c[13] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
c[14] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
break;
case 7:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
c[5] = (CT(10)*n+CT(21))/CT(1024);
c[6] = ((n-CT(3))*n+CT(2))/CT(32);
c[7] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[8] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[9] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
c[10] = (CT(69)*n+CT(108))/CT(8192);
c[11] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[12] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[13] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
c[14] = (CT(12)-n)/CT(1024);
c[15] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
c[16] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
c[17] = (CT(72)-CT(43)*n)/CT(8192);
c[18] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
c[19] = (CT(9)-CT(15)*n)/CT(1024);
c[20] = (CT(44)-CT(99)*n)/CT(8192);
break;
default:
c[0] = (CT(1)-n)/CT(4);
c[1] = (CT(1)-n2)/CT(8);
c[2] = (n*((-CT(5)*n-CT(1))*n+CT(3))+CT(3))/CT(64);
c[3] = (n*((CT(2)-CT(2)*n)*n+CT(2))+CT(5))/CT(128);
c[4] = (n*(CT(3)*n+CT(11))+CT(12))/CT(512);
c[5] = (CT(10)*n+CT(21))/CT(1024);
c[6] = CT(243)/CT(16384);
c[7] = ((n-CT(3))*n+CT(2))/CT(32);
c[8] = (n*(n*(CT(2)*n-CT(3))-CT(2))+CT(3))/CT(64);
c[9] = (n*((-CT(6)*n-CT(9))*n+CT(2))+CT(6))/CT(256);
c[10] = ((CT(1)-CT(2)*n)*n+CT(5))/CT(256);
c[11] = (CT(69)*n+CT(108))/CT(8192);
c[12] = CT(187)/CT(16384);
c[13] = (n*((CT(5)-n)*n-CT(9))+CT(5))/CT(192);
c[14] = (n*(n*(CT(10)*n-CT(6))-CT(10))+CT(9))/CT(384);
c[15] = ((-CT(77)*n-CT(8))*n+CT(42))/CT(3072);
c[16] = (CT(12)-n)/CT(1024);
c[17] = CT(139)/CT(16384);
c[18] = (n*((CT(20)-CT(7)*n)*n-CT(28))+CT(14))/CT(1024);
c[19] = ((-CT(7)*n-CT(40))*n+CT(28))/CT(2048);
c[20] = (CT(72)-CT(43)*n)/CT(8192);
c[21] = CT(127)/CT(16384);
c[22] = (n*(CT(75)*n-CT(90))+CT(42))/CT(5120);
c[23] = (CT(9)-CT(15)*n)/CT(1024);
c[24] = CT(99)/CT(16384);
c[25] = (CT(44)-CT(99)*n)/CT(8192);
c[26] = CT(99)/CT(16384);
c[27] = CT(429)/CT(114688);
break;
}
}
/*
\brief Given the set of coefficients coeffs2[] evaluate on
C3 and return the set of coefficients coeffs1[].
Elements coeffs1[1] through coeffs1[SeriesOrder - 1] are set.
*/
template <typename Coeffs1, typename Coeffs2, typename CT>
inline void evaluate_coeffs_C3(Coeffs1 &coeffs1, Coeffs2 &coeffs2, CT const& eps)
{
CT mult = 1;
size_t offset = 0;
// i is the index of C3[i].
for (size_t i = 1; i < Coeffs1::static_size; ++i)
{
// Order of polynomial in eps.
size_t m = Coeffs1::static_size - i;
mult *= eps;
coeffs1[i] = mult * math::horner_evaluate(eps, coeffs2.begin() + offset,
coeffs2.begin() + offset + m);
offset += m;
}
// Post condition: offset == coeffs_C3_size
}
/*
\brief Evaluate the following:
y = sum(c[i] * sin(2*i * x), i, 1, n)
using Clenshaw summation.
*/
template <typename CT, typename Coeffs>
inline CT sin_cos_series(CT const& sinx, CT const& cosx, Coeffs const& coeffs)
{
size_t n = Coeffs::static_size - 1;
size_t index = 0;
// Point to one beyond last element.
index += (n + 1);
CT ar = 2 * (cosx - sinx) * (cosx + sinx);
// If n is odd, get the last element.
CT k0 = n & 1 ? coeffs[--index] : 0;
CT k1 = 0;
// Make n even.
n /= 2;
while (n--) {
// Unroll loop x 2, so accumulators return to their original role.
k1 = ar * k0 - k1 + coeffs[--index];
k0 = ar * k1 - k0 + coeffs[--index];
}
return 2 * sinx * cosx * k0;
}
/*
The coefficient containers for the series expansions.
These structs allow the caller to only know the series order.
*/
template <size_t SeriesOrder, typename CT>
struct coeffs_C1 : boost::array<CT, SeriesOrder + 1>
{
coeffs_C1(CT const& epsilon)
{
evaluate_coeffs_C1(*this, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C1p : boost::array<CT, SeriesOrder + 1>
{
coeffs_C1p(CT const& epsilon)
{
evaluate_coeffs_C1p(*this, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C2 : boost::array<CT, SeriesOrder + 1>
{
coeffs_C2(CT const& epsilon)
{
evaluate_coeffs_C2(*this, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C3x : boost::array<CT, (SeriesOrder * (SeriesOrder - 1)) / 2>
{
coeffs_C3x(CT const& n)
{
evaluate_coeffs_C3x<SeriesOrder>(*this, n);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_C3 : boost::array<CT, SeriesOrder>
{
coeffs_C3(CT const& n, CT const& epsilon)
{
coeffs_C3x<SeriesOrder, CT> coeffs_C3x(n);
evaluate_coeffs_C3(*this, coeffs_C3x, epsilon);
}
};
template <size_t SeriesOrder, typename CT>
struct coeffs_A3 : boost::array<CT, SeriesOrder>
{
coeffs_A3(CT const& n)
{
evaluate_coeffs_A3(*this, n);
}
};
}}} // namespace boost::geometry::series_expansion
#endif // BOOST_GEOMETRY_UTIL_SERIES_EXPANSION_HPP
+91
View File
@@ -0,0 +1,91 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015-2020.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP
#define BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_ALLOW_DEPRECATED_HEADERS)
BOOST_PRAGMA_MESSAGE("This header is deprecated.")
#endif
#include <boost/mpl/transform.hpp>
#include <boost/variant/variant_fwd.hpp>
namespace boost { namespace geometry
{
/*!
\brief Meta-function that takes a Sequence type, an MPL lambda
expression and an optional Inserter and returns a variant type over
the same types as the initial variant type, each transformed using
the lambda expression.
\ingroup utility
\par Example
\code
typedef boost::mpl::vector<int, float, long> types;
typedef transform_variant<types, add_pointer<_> > transformed;
typedef variant<int*, float*, long*> result;
BOOST_MPL_ASSERT(( equal<result, transformed> ));
\endcode
*/
template <typename Sequence, typename Op, typename In = boost::mpl::na>
struct transform_variant:
make_variant_over<
typename boost::mpl::transform<
Sequence,
Op,
In
>::type
>
{};
/*!
\brief Meta-function that takes a boost::variant type and an MPL lambda
expression and returns a variant type over the same types as the
initial variant type, each transformed using the lambda expression.
\ingroup utility
\par Example
\code
typedef variant<int, float, long> variant_type;
typedef transform_variant<variant_type, add_pointer<_> > transformed;
typedef variant<int*, float*, long*> result;
BOOST_MPL_ASSERT(( equal<result, transformed> ));
\endcode
*/
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Op>
struct transform_variant<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Op, boost::mpl::na> :
make_variant_over<
typename boost::mpl::transform<
typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
Op
>::type
>
{};
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_TRANSFORM_VARIANT_HPP
+389
View File
@@ -0,0 +1,389 @@
// Boost.Geometry Index
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_UTIL_TUPLES_HPP
#define BOOST_GEOMETRY_UTIL_TUPLES_HPP
#include <tuple>
#include <type_traits>
#include <utility>
#include <boost/geometry/core/config.hpp>
#include <boost/tuple/tuple.hpp>
namespace boost { namespace geometry { namespace tuples
{
template <typename T>
struct is_tuple
: std::integral_constant<bool, false>
{};
template <typename ...Ts>
struct is_tuple<std::tuple<Ts...>>
: std::integral_constant<bool, true>
{};
template <typename F, typename S>
struct is_tuple<std::pair<F, S>>
: std::integral_constant<bool, true>
{};
template <typename ...Ts>
struct is_tuple<boost::tuples::tuple<Ts...>>
: std::integral_constant<bool, true>
{};
template <typename HT, typename TT>
struct is_tuple<boost::tuples::cons<HT, TT>>
: std::integral_constant<bool, true>
{};
template <std::size_t I, typename Tuple>
struct element;
template <std::size_t I, typename ...Ts>
struct element<I, std::tuple<Ts...>>
: std::tuple_element<I, std::tuple<Ts...>>
{};
template <std::size_t I, typename HT, typename TT>
struct element<I, std::pair<HT, TT>>
: std::tuple_element<I, std::pair<HT, TT>>
{};
template <std::size_t I, typename ...Ts>
struct element<I, boost::tuples::tuple<Ts...>>
{
typedef typename boost::tuples::element
<
I, boost::tuples::tuple<Ts...>
>::type type;
};
template <std::size_t I, typename HT, typename TT>
struct element<I, boost::tuples::cons<HT, TT>>
{
typedef typename boost::tuples::element
<
I, boost::tuples::cons<HT, TT>
>::type type;
};
template <typename Tuple>
struct size;
template <typename ...Ts>
struct size<std::tuple<Ts...>>
: std::tuple_size<std::tuple<Ts...>>
{};
template <typename HT, typename TT>
struct size<std::pair<HT, TT>>
: std::tuple_size<std::pair<HT, TT>>
{};
template <typename ...Ts>
struct size<boost::tuples::tuple<Ts...>>
: std::integral_constant
<
std::size_t,
boost::tuples::length<boost::tuples::tuple<Ts...>>::value
>
{};
template <typename HT, typename TT>
struct size<boost::tuples::cons<HT, TT>>
: std::integral_constant
<
std::size_t,
boost::tuples::length<boost::tuples::cons<HT, TT>>::value
>
{};
template <std::size_t I, typename ...Ts>
constexpr inline typename std::tuple_element<I, std::tuple<Ts...>>::type&
get(std::tuple<Ts...> & t)
{
return std::get<I>(t);
}
template <std::size_t I, typename ...Ts>
constexpr inline typename std::tuple_element<I, std::tuple<Ts...>>::type const&
get(std::tuple<Ts...> const& t)
{
return std::get<I>(t);
}
template <std::size_t I, typename HT, typename TT>
constexpr inline typename std::tuple_element<I, std::pair<HT, TT>>::type&
get(std::pair<HT, TT> & t)
{
return std::get<I>(t);
}
template <std::size_t I, typename HT, typename TT>
constexpr inline typename std::tuple_element<I, std::pair<HT, TT>>::type const&
get(std::pair<HT, TT> const& t)
{
return std::get<I>(t);
}
template <std::size_t I, typename ...Ts>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::tuple<Ts...>>::type
>::non_const_type
get(boost::tuples::tuple<Ts...> & t)
{
return boost::tuples::get<I>(t);
}
template <std::size_t I, typename ...Ts>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::tuple<Ts...>>::type
>::const_type
get(boost::tuples::tuple<Ts...> const& t)
{
return boost::tuples::get<I>(t);
}
template <std::size_t I, typename HT, typename TT>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
>::non_const_type
get(boost::tuples::cons<HT, TT> & tup)
{
return boost::tuples::get<I>(tup);
}
template <std::size_t I, typename HT, typename TT>
inline typename boost::tuples::access_traits
<
typename boost::tuples::element<I, boost::tuples::cons<HT, TT> >::type
>::const_type
get(boost::tuples::cons<HT, TT> const& tup)
{
return boost::tuples::get<I>(tup);
}
// find_index_if
// Searches for the index of an element for which UnaryPredicate returns true
// If such element is not found the result is N
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t I = 0,
std::size_t N = size<Tuple>::value
>
struct find_index_if
: std::conditional_t
<
UnaryPred<typename element<I, Tuple>::type>::value,
std::integral_constant<std::size_t, I>,
typename find_index_if<Tuple, UnaryPred, I+1, N>::type
>
{};
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t N
>
struct find_index_if<Tuple, UnaryPred, N, N>
: std::integral_constant<std::size_t, N>
{};
// find_if
// Searches for an element for which UnaryPredicate returns true
// If such element is not found the result is detail::null_type
namespace detail
{
struct null_type {};
} // detail
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t I = 0,
std::size_t N = size<Tuple>::value
>
struct find_if
: std::conditional_t
<
UnaryPred<typename element<I, Tuple>::type>::value,
element<I, Tuple>,
find_if<Tuple, UnaryPred, I+1, N>
>
{};
template
<
typename Tuple,
template <typename> class UnaryPred,
std::size_t N
>
struct find_if<Tuple, UnaryPred, N, N>
{
typedef detail::null_type type;
};
// is_found
// Returns true if a type T (the result of find_if) was found.
template <typename T>
struct is_found
: std::integral_constant
<
bool,
! std::is_same<T, detail::null_type>::value
>
{};
// is_not_found
// Returns true if a type T (the result of find_if) was not found.
template <typename T>
struct is_not_found
: std::is_same<T, detail::null_type>
{};
// exists_if
// Returns true if search for element meeting UnaryPred can be found.
template <typename Tuple, template <typename> class UnaryPred>
struct exists_if
: is_found<typename find_if<Tuple, UnaryPred>::type>
{};
// push_back
// A utility used to create a type/object of a Tuple containing
// all types/objects stored in another Tuple plus additional one.
template <typename Tuple,
typename T,
std::size_t I = 0,
std::size_t N = size<Tuple>::value>
struct push_back_bt
{
typedef
boost::tuples::cons<
typename element<I, Tuple>::type,
typename push_back_bt<Tuple, T, I+1, N>::type
> type;
static type apply(Tuple const& tup, T const& t)
{
return
type(
geometry::tuples::get<I>(tup),
push_back_bt<Tuple, T, I+1, N>::apply(tup, t)
);
}
};
template <typename Tuple, typename T, std::size_t N>
struct push_back_bt<Tuple, T, N, N>
{
typedef boost::tuples::cons<T, boost::tuples::null_type> type;
static type apply(Tuple const&, T const& t)
{
return type(t, boost::tuples::null_type());
}
};
template <typename Tuple, typename T>
struct push_back
: push_back_bt<Tuple, T>
{};
template <typename F, typename S, typename T>
struct push_back<std::pair<F, S>, T>
{
typedef std::tuple<F, S, T> type;
static type apply(std::pair<F, S> const& p, T const& t)
{
return type(p.first, p.second, t);
}
static type apply(std::pair<F, S> && p, T const& t)
{
return type(std::move(p.first), std::move(p.second), t);
}
static type apply(std::pair<F, S> && p, T && t)
{
return type(std::move(p.first), std::move(p.second), std::move(t));
}
};
template <typename Is, typename Tuple, typename T>
struct push_back_st;
template <std::size_t ...Is, typename ...Ts, typename T>
struct push_back_st<std::index_sequence<Is...>, std::tuple<Ts...>, T>
{
typedef std::tuple<Ts..., T> type;
static type apply(std::tuple<Ts...> const& tup, T const& t)
{
return type(std::get<Is>(tup)..., t);
}
static type apply(std::tuple<Ts...> && tup, T const& t)
{
return type(std::move(std::get<Is>(tup))..., t);
}
static type apply(std::tuple<Ts...> && tup, T && t)
{
return type(std::move(std::get<Is>(tup))..., std::move(t));
}
};
template <typename ...Ts, typename T>
struct push_back<std::tuple<Ts...>, T>
: push_back_st
<
std::make_index_sequence<sizeof...(Ts)>,
std::tuple<Ts...>,
T
>
{};
}}} // namespace boost::geometry::tuples
#endif // BOOST_GEOMETRY_UTIL_TUPLES_HPP
+315
View File
@@ -0,0 +1,315 @@
// Boost.Geometry
// Copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_TYPE_TRAITS_HPP
#define BOOST_GEOMETRY_UTIL_TYPE_TRAITS_HPP
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
namespace util
{
template <typename T>
struct is_geometry
: bool_constant<! std::is_void<typename tag<T>::type>::value>
{};
template <typename T>
struct is_not_geometry
: std::is_void<typename tag<T>::type>
{};
template <typename T>
struct is_point
: std::is_same<point_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_point
: std::is_same<multi_point_tag, typename tag<T>::type>
{};
template <typename T>
struct is_pointlike
: std::is_base_of<pointlike_tag, typename tag<T>::type>
{};
template <typename T>
struct is_segment
: std::is_same<segment_tag, typename tag<T>::type>
{};
template <typename T>
struct is_linestring
: std::is_same<linestring_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_linestring
: std::is_same<multi_linestring_tag, typename tag<T>::type>
{};
template <typename T>
struct is_polylinear
: std::is_base_of<polylinear_tag, typename tag<T>::type>
{};
template <typename T>
struct is_linear
: std::is_base_of<linear_tag, typename tag<T>::type>
{};
template <typename T>
struct is_box
: std::is_same<box_tag, typename tag<T>::type>
{};
template <typename T>
struct is_ring
: std::is_same<ring_tag, typename tag<T>::type>
{};
template <typename T>
struct is_polygon
: std::is_same<polygon_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_polygon
: std::is_same<multi_polygon_tag, typename tag<T>::type>
{};
template <typename T>
struct is_polygonal
: std::is_base_of<polygonal_tag, typename tag<T>::type>
{};
template <typename T>
struct is_areal
: std::is_base_of<areal_tag, typename tag<T>::type>
{};
template <typename T>
struct is_segmental
: bool_constant<is_linear<T>::value || is_polygonal<T>::value>
{};
template <typename T>
struct is_polysegmental
: bool_constant<is_polylinear<T>::value || is_polygonal<T>::value>
{};
template <typename T>
struct is_multi
: std::is_base_of<multi_tag, typename tag<T>::type>
{};
template <typename T>
struct is_multi_element
: bool_constant<is_point<T>::value || is_linestring<T>::value || is_polygon<T>::value>
{};
template <typename T>
struct is_single
: std::is_base_of<single_tag, typename tag<T>::type>
{};
template <typename T>
struct is_geometry_collection
: std::is_same<geometry_collection_tag, typename tag<T>::type>
{};
template <typename T>
struct is_dynamic_geometry
: std::is_same<dynamic_geometry_tag, typename tag<T>::type>
{};
template <typename Geometry, typename T = void>
struct enable_if_point
: std::enable_if<is_point<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_point_t = typename enable_if_point<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_multi_point
: std::enable_if<is_multi_point<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_multi_point_t = typename enable_if_multi_point<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_pointlike
: std::enable_if<is_pointlike<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_pointlike_t = typename enable_if_pointlike<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_segment
: std::enable_if<is_segment<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_segment_t = typename enable_if_segment<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_linestring
: std::enable_if<is_linestring<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_linestring_t = typename enable_if_linestring<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_multi_linestring
: std::enable_if<is_multi_linestring<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_multi_linestring_t = typename enable_if_multi_linestring<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_polylinear
: std::enable_if<is_polylinear<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_polylinear_t = typename enable_if_polylinear<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_linear
: std::enable_if<is_linear<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_linear_t = typename enable_if_linear<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_box
: std::enable_if<is_box<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_box_t = typename enable_if_box<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_ring
: std::enable_if<is_ring<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_ring_t = typename enable_if_ring<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_polygon
: std::enable_if<is_polygon<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_polygon_t = typename enable_if_polygon<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_multi_polygon
: std::enable_if<is_multi_polygon<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_multi_polygon_t = typename enable_if_multi_polygon<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_polygonal
: std::enable_if<is_polygonal<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_polygonal_t = typename enable_if_polygonal<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_areal
: std::enable_if<is_areal<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_areal_t = typename enable_if_areal<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_polysegmental
: std::enable_if<is_polysegmental<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_polysegmental_t = typename enable_if_polysegmental<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_dynamic_geometry
: std::enable_if<is_dynamic_geometry<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_dynamic_geometry_t = typename enable_if_dynamic_geometry<Geometry, T>::type;
template <typename Geometry, typename T = void>
struct enable_if_geometry_collection
: std::enable_if<is_geometry_collection<Geometry>::value, T>
{};
template <typename Geometry, typename T = void>
using enable_if_geometry_collection_t = typename enable_if_geometry_collection<Geometry, T>::type;
} // namespace util
// Deprecated utilities, defined for backward compatibility but might be
// removed in the future.
/*!
\brief Meta-function defining "true" for areal types (box, (multi)polygon, ring),
\note Used for tag dispatching and meta-function finetuning
\note Also a "ring" has areal properties within Boost.Geometry
\ingroup core
*/
using util::is_areal;
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_DETAIL_HPP
+220
View File
@@ -0,0 +1,220 @@
// Boost.Geometry
// Copyright (c) 2020, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_UTIL_TYPE_TRAITS_STD_HPP
#define BOOST_GEOMETRY_UTIL_TYPE_TRAITS_STD_HPP
#include <cstddef>
#include <type_traits>
namespace boost { namespace geometry
{
namespace util
{
// C++17
template <bool B>
using bool_constant = std::integral_constant<bool, B>;
// non-standard
template <int I>
using int_constant = std::integral_constant<int, I>;
// non-standard
template <std::size_t I>
using index_constant = std::integral_constant<std::size_t, I>;
// non-standard
template <std::size_t S>
using size_constant = std::integral_constant<std::size_t, S>;
// C++17
template <typename ...>
struct conjunction
: std::true_type
{};
template<typename Trait>
struct conjunction<Trait>
: Trait
{};
template <typename Trait, typename ...Traits>
struct conjunction<Trait, Traits...>
: std::conditional_t<Trait::value, conjunction<Traits...>, Trait>
{};
// C++17
template <typename ...>
struct disjunction
: std::false_type
{};
template <typename Trait>
struct disjunction<Trait>
: Trait
{};
template <typename Trait, typename ...Traits>
struct disjunction<Trait, Traits...>
: std::conditional_t<Trait::value, Trait, disjunction<Traits...>>
{};
// C++17
template <typename Trait>
struct negation
: bool_constant<!Trait::value>
{};
// non-standard
/*
template <typename ...Traits>
using and_ = conjunction<Traits...>;
template <typename ...Traits>
using or_ = disjunction<Traits...>;
template <typename Trait>
using not_ = negation<Trait>;
*/
// C++20
template <typename T>
struct remove_cvref
{
using type = std::remove_cv_t<std::remove_reference_t<T>>;
};
template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type;
// non-standard
template <typename T>
struct remove_cref
{
using type = std::remove_const_t<std::remove_reference_t<T>>;
};
template <typename T>
using remove_cref_t = typename remove_cref<T>::type;
// non-standard
template <typename T>
struct remove_cptrref
{
using type = std::remove_const_t
<
std::remove_pointer_t<std::remove_reference_t<T>>
>;
};
template <typename T>
using remove_cptrref_t = typename remove_cptrref<T>::type;
// non-standard
template <typename From, typename To>
struct transcribe_const
{
using type = std::conditional_t
<
std::is_const<std::remove_reference_t<From>>::value,
std::add_const_t<To>,
To
>;
};
template <typename From, typename To>
using transcribe_const_t = typename transcribe_const<From, To>::type;
// non-standard
template <typename From, typename To>
struct transcribe_reference
{
using type = std::remove_reference_t<To>;
};
template <typename From, typename To>
struct transcribe_reference<From &, To>
{
using type = std::remove_reference_t<To> &;
};
template <typename From, typename To>
struct transcribe_reference<From &&, To>
{
using type = std::remove_reference_t<To> &&;
};
template <typename From, typename To>
using transcribe_reference_t = typename transcribe_reference<From, To>::type;
// non-standard
template <typename From, typename To>
struct transcribe_cref
{
using type = transcribe_reference_t<From, transcribe_const_t<From, To>>;
};
template <typename From, typename To>
using transcribe_cref_t = typename transcribe_cref<From, To>::type;
} // namespace util
// Deprecated utilities, defined for backward compatibility but might be
// removed in the future.
/*!
\brief Meta-function to define a const or non const type
\ingroup utility
\details If the boolean template parameter is true, the type parameter
will be defined as const, otherwise it will be defined as it was.
This meta-function is used to have one implementation for both
const and non const references
\note This traits class is completely independant from Boost.Geometry
and might be a separate addition to Boost
\note Used in a.o. for_each, interior_rings, exterior_ring
\par Example
\code
void foo(typename add_const_if_c<IsConst, Point>::type& point)
\endcode
*/
template <bool IsConst, typename Type>
struct add_const_if_c
{
typedef std::conditional_t
<
IsConst,
Type const,
Type
> type;
};
namespace util
{
template <typename T>
using bare_type = remove_cptrref<T>;
} // namespace util
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_UTIL_TYPE_TRAITS_STD_HPP