Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Boot::multiprecision as a DGtal::BigInteger model #1749

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/DGtal/base/BasicTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include <cstdlib>
#include <iostream>
#include <boost/cstdint.hpp>
#include <boost/multiprecision/cpp_int.hpp>

#ifdef WITH_GMP
#include <gmpxx.h>
Expand Down Expand Up @@ -77,6 +78,9 @@ namespace DGtal
#define WITH_BIGINTEGER
///Multi-precision integer with GMP implementation.
typedef mpz_class BigInteger;
#else
#define WITH_BIGINTEGER
typedef boost::multiprecision::cpp_int BigInteger;
#endif

} // namespace DGtal
Expand Down
13 changes: 7 additions & 6 deletions src/DGtal/geometry/curves/ArithmeticalDSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "DGtal/base/Common.h"
#include "DGtal/base/Exceptions.h"
#include "DGtal/base/ReverseIterator.h"
#include "DGtal/kernel/NumberTraits.h"
#include "DGtal/kernel/CInteger.h"
#include "DGtal/kernel/CSignedNumber.h"
#include "DGtal/kernel/SpaceND.h"
Expand Down Expand Up @@ -851,23 +852,23 @@ namespace DGtal
{
BOOST_CONCEPT_ASSERT(( concepts::CSignedNumber<TOutput> ));
BOOST_CONCEPT_ASSERT(( concepts::CInteger<TOutput> ));

inline
static TOutput cast(const DGtal::BigInteger& aInput)
{
ASSERT( (aInput <= static_cast<DGtal::BigInteger>(std::numeric_limits<TOutput>::max())) &&
(aInput >= static_cast<DGtal::BigInteger>(std::numeric_limits<TOutput>::min())) );
return static_cast<TOutput>(aInput.get_si());
ASSERT( (aInput <= static_cast<DGtal::BigInteger>(std::numeric_limits<TOutput>::max())) &&
(aInput >= static_cast<DGtal::BigInteger>(std::numeric_limits<TOutput>::min())) );
return static_cast<TOutput>(DGtal::NumberTraits<DGtal::BigInteger>::castToInt64_t(aInput));
}
};
template <>
struct toCoordinateImpl<DGtal::BigInteger, DGtal::BigInteger>
{

inline
static DGtal::BigInteger cast(const DGtal::BigInteger& aInput)
{
return aInput;
return aInput;
}
};
#endif
Expand Down
108 changes: 68 additions & 40 deletions src/DGtal/kernel/ArithmeticConversionTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

namespace DGtal
{

/////////////////////////////////////////////////////////////////////////////
// template class ArithmeticConversionTraits
/**
Expand Down Expand Up @@ -92,23 +92,23 @@ namespace DGtal
struct ArithmeticConversionTraits
{
};

/** @brief Specialization in order to remove const specifiers and references from given types
*
* @see ArithmeticConversionTraits
*/
template <typename T, typename U>
struct ArithmeticConversionTraits< T, U,
typename std::enable_if<
! std::is_same< T, typename std::remove_cv< typename std::remove_reference<T>::type >::type >::value
|| ! std::is_same< U, typename std::remove_cv< typename std::remove_reference<U>::type >::type >::value >::type >
: ArithmeticConversionTraits<
typename std::remove_cv< typename std::remove_reference<T>::type >::type,
typename std::remove_cv< typename std::remove_reference<U>::type >::type >
typename std::enable_if<
! std::is_same< T, typename std::remove_cv< typename std::remove_reference<T>::type >::type >::value
|| ! std::is_same< U, typename std::remove_cv< typename std::remove_reference<U>::type >::type >::value >::type >
: ArithmeticConversionTraits<
typename std::remove_cv< typename std::remove_reference<T>::type >::type,
typename std::remove_cv< typename std::remove_reference<U>::type >::type >
{
};


/** @brief Specialization for (fundamental) arithmetic types.
*
* Resulting type is deduced from usual arithmetic conversion using
Expand All @@ -117,13 +117,12 @@ namespace DGtal
* @see ArithmeticConversionTraits
*/
template <typename T, typename U>
struct ArithmeticConversionTraits< T, U,
typename std::enable_if< std::is_arithmetic<T>::value
&& std::is_arithmetic<U>::value >::type >
struct ArithmeticConversionTraits< T, U, typename std::enable_if< std::is_arithmetic<T>::value
&& std::is_arithmetic<U>::value >::type >
{
using type = typename std::common_type<T, U>::type; //! Arithmetic operation result type.
};

/** @brief Result type of arithmetic binary operators between two given types.
*
* @tparam T First operand type.
Expand All @@ -133,7 +132,7 @@ namespace DGtal
*/
template <typename T, typename U>
using ArithmeticConversionType = typename ArithmeticConversionTraits<T, U>::type;

/** @brief Helper to determine if an arithmetic operation between two given
* types has a valid result type (ie is valid).
*
Expand All @@ -143,10 +142,10 @@ namespace DGtal
*/
template <typename T, typename U, typename Enable = void>
struct IsArithmeticConversionValid
: std::false_type
: std::false_type
{
};

/** @brief Specialization when arithmetic operation between the two given
* type is valid.
*
Expand All @@ -157,12 +156,12 @@ namespace DGtal
*/
template <typename T, typename U>
struct IsArithmeticConversionValid<T, U,
typename std::conditional<false, ArithmeticConversionType<T, U>, void>::type >
: std::true_type
typename std::conditional<false, ArithmeticConversionType<T, U>, void>::type >
: std::true_type
{
};


/** @brief Call constructor for the result type of an arithmetic operation.
*
* @tparam LHS First operand type.
Expand All @@ -173,22 +172,19 @@ namespace DGtal
* @param rhs Second operand (only used for auto-deducing its type).
* @param args Parameters forwarded to the constructor.
*/
template <
typename LHS,
typename RHS,
typename... Args >
template <typename LHS,typename RHS,typename... Args >
inline
ArithmeticConversionType<LHS, RHS>
constructFromArithmeticConversion( LHS const& lhs, RHS const& rhs, Args &&... args )
{
boost::ignore_unused_variable_warning(lhs);
boost::ignore_unused_variable_warning(rhs);

return ArithmeticConversionType<LHS, RHS>( std::forward<Args>(args)... );
}

{
boost::ignore_unused_variable_warning(lhs);
boost::ignore_unused_variable_warning(rhs);
return ArithmeticConversionType<LHS, RHS>( std::forward<Args>(args)... );
}
#ifdef WITH_GMP
/** @brief Specialization when first operand is a @ref BigInteger.
/** @brief Specialization when first operand is a @ref BigInteger with GMP.
*
* @warning result type if set to BigInteger instead of the possible
* more complex __gmp_expr.
Expand All @@ -197,12 +193,12 @@ namespace DGtal
*/
template <typename T, typename GMP1, typename GMP2>
struct ArithmeticConversionTraits<T, __gmp_expr<GMP1, GMP2>,
typename std::enable_if< std::is_integral<T>::value >::type >
typename std::enable_if< std::is_integral<T>::value >::type >
{
using type = BigInteger;
};

/** @brief Specialization when second operand is a @ref BigInteger.
/** @brief Specialization when second operand is a @ref BigInteger with GMP.
*
* @warning result type if set to BigInteger instead of the possible
* more complex __gmp_expr.
Expand All @@ -211,12 +207,12 @@ namespace DGtal
*/
template <typename GMP1, typename GMP2, typename U>
struct ArithmeticConversionTraits<__gmp_expr<GMP1, GMP2>, U,
typename std::enable_if< std::is_integral<U>::value >::type >
typename std::enable_if< std::is_integral<U>::value >::type >
{
using type = BigInteger;
};

/** @brief Specialization when both operands are @ref BigInteger.
/** @brief Specialization when both operands are @ref BigInteger with GMP.
*
* @warning result type if set to BigInteger instead of the possible
* more complex __gmp_expr.
Expand All @@ -229,9 +225,41 @@ namespace DGtal
using type = BigInteger;
};
#endif



/** @brief Specialization when first operand is a @ref BigInteger.
*
* @see ArithmeticConversionTraits
*/
template <typename T>
struct ArithmeticConversionTraits<T, BigInteger,typename std::enable_if< std::is_integral<T>::value >::type >
{
using type = BigInteger;
};

/** @brief Specialization when second operand is a @ref BigInteger with GMP.
*
* @see ArithmeticConversionTraits
*/
template <typename U>
struct ArithmeticConversionTraits<BigInteger, U,typename std::enable_if< std::is_integral<U>::value >::type >
{
using type = BigInteger;
};

/** @brief Specialization when both operands are @ref BigInteger.
*
*
* @see ArithmeticConversionTraits
*/
template <>
struct ArithmeticConversionTraits<BigInteger,BigInteger>
{
using type = BigInteger;
};
} // namespace DGtal


#endif // !defined ArithmeticConversionTraits_h

#undef ArithmeticConversionTraits_RECURSES
Expand Down
13 changes: 12 additions & 1 deletion src/DGtal/kernel/IntegerConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
namespace DGtal
{
#ifdef WITH_BIGINTEGER
#ifdef WITH_GMP
namespace detail {
/// ------------- GMP SPECIALIZED SERVICES ----------------------------

Expand Down Expand Up @@ -96,6 +97,7 @@ namespace DGtal
return (long long)mpz_get_ull(n); /* just use unsigned version */
}
}
#endif
#endif

/// ------------- INTEGER/POINT CONVERSION SERVICES --------------------
Expand Down Expand Up @@ -197,7 +199,7 @@ namespace DGtal
/// @return the same integer
static DGtal::int32_t cast( DGtal::BigInteger i )
{
auto r = i.get_si();
auto r = NumberTraits<DGtal::BigInteger>::castToInt64_t(i);
if ( DGtal::BigInteger( r ) != i )
trace.warning() << "Bad integer conversion: " << i << " -> " << r
<< std::endl;
Expand Down Expand Up @@ -279,9 +281,14 @@ namespace DGtal
/// @return the same integer
static DGtal::int64_t cast( DGtal::BigInteger i )
{
#ifdef WITH_GMP
DGtal::int64_t r = detail::mpz_get_sll( i.get_mpz_t() );
DGtal::BigInteger tmp;
detail::mpz_set_sll( tmp.get_mpz_t(), r );
#else
DGtal::int64_t r = NumberTraits<DGtal::BigInteger>::castToInt64_t(i);
DGtal::BigInteger tmp(r);
#endif
if ( tmp != i )
trace.warning() << "Bad integer conversion: " << i << " -> " << r
<< std::endl;
Expand Down Expand Up @@ -346,7 +353,11 @@ namespace DGtal
static DGtal::BigInteger cast( DGtal::int64_t i )
{
DGtal::BigInteger tmp;
#ifdef WITH_GMP
detail::mpz_set_sll( tmp.get_mpz_t(), i );
#else
tmp = i;
#endif
return tmp;
}

Expand Down
Loading
Loading