summaryrefslogtreecommitdiff
path: root/boost/multiprecision/cpp_int/import_export.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision/cpp_int/import_export.hpp')
-rw-r--r--boost/multiprecision/cpp_int/import_export.hpp104
1 files changed, 78 insertions, 26 deletions
diff --git a/boost/multiprecision/cpp_int/import_export.hpp b/boost/multiprecision/cpp_int/import_export.hpp
index f2f15f6421..3a2473b0b2 100644
--- a/boost/multiprecision/cpp_int/import_export.hpp
+++ b/boost/multiprecision/cpp_int/import_export.hpp
@@ -85,46 +85,97 @@ namespace boost {
*newval.limbs() = 0;
}
- }
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+ import_bits_generic(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
+ {
+ typename number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>::backend_type newval;
+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
+ typedef typename boost::make_unsigned<value_type>::type unsigned_value_type;
+ typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
+ typedef typename boost::make_unsigned<difference_type>::type size_type;
+ typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag tag_type;
- template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
- import_bits(
- number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
- {
- typename number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>::backend_type newval;
+ if(!chunk_size)
+ chunk_size = std::numeric_limits<value_type>::digits;
- typedef typename std::iterator_traits<Iterator>::value_type value_type;
- typedef typename boost::make_unsigned<value_type>::type unsigned_value_type;
- typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
- typedef typename boost::make_unsigned<difference_type>::type size_type;
- typedef typename cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>::trivial_tag tag_type;
+ size_type limbs = std::distance(i, j);
+ size_type bits = limbs * chunk_size;
+
+ detail::resize_to_bit_size(newval, static_cast<unsigned>(bits), tag_type());
- if(!chunk_size)
- chunk_size = std::numeric_limits<value_type>::digits;
+ difference_type bit_location = msv_first ? bits - chunk_size : 0;
+ difference_type bit_location_change = msv_first ? -static_cast<difference_type>(chunk_size) : chunk_size;
- size_type limbs = std::distance(i, j);
- size_type bits = limbs * chunk_size;
+ while(i != j)
+ {
+ detail::assign_bits(newval, static_cast<unsigned_value_type>(*i), static_cast<unsigned>(bit_location), chunk_size, tag_type());
+ ++i;
+ bit_location += bit_location_change;
+ }
- detail::resize_to_bit_size(newval, static_cast<unsigned>(bits), tag_type());
+ newval.normalize();
- difference_type bit_location = msv_first ? bits - chunk_size : 0;
- difference_type bit_location_change = msv_first ? -static_cast<difference_type>(chunk_size) : chunk_size;
+ val.backend().swap(newval);
+ return val;
+ }
- while(i != j)
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+ inline typename boost::disable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
+ import_bits_fast(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0)
{
- detail::assign_bits(newval, static_cast<unsigned_value_type>(*i), static_cast<unsigned>(bit_location), chunk_size, tag_type());
- ++i;
- bit_location += bit_location_change;
+ std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i));
+ std::size_t limb_len = byte_len / sizeof(limb_type);
+ if(byte_len % sizeof(limb_type))
+ ++limb_len;
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
+ result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
+ result.limbs()[result.size() - 1] = 0u;
+ std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(limb_type)));
+ result.normalize(); // In case data has leading zeros.
+ return val;
}
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+ inline typename boost::enable_if_c<boost::multiprecision::backends::is_trivial_cpp_int<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator> >::value, number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&>::type
+ import_bits_fast(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0)
+ {
+ cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>& result = val.backend();
+ std::size_t byte_len = (j - i) * (chunk_size ? chunk_size / CHAR_BIT : sizeof(*i));
+ std::size_t limb_len = byte_len / sizeof(result.limbs()[0]);
+ if(byte_len % sizeof(result.limbs()[0]))
+ ++limb_len;
+ result.limbs()[0] = 0u;
+ result.resize(limb_len, limb_len); // checked types may throw here if they're not large enough to hold the data!
+ std::memcpy(result.limbs(), i, std::min(byte_len, result.size() * sizeof(result.limbs()[0])));
+ result.normalize(); // In case data has leading zeros.
+ return val;
+ }
+ }
- newval.normalize();
- val.backend().swap(newval);
- return val;
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class Iterator>
+ inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+ import_bits(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, Iterator i, Iterator j, unsigned chunk_size = 0, bool msv_first = true)
+ {
+ return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
}
+ template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class T>
+ inline number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>&
+ import_bits(
+ number<cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ExpressionTemplates>& val, T* i, T* j, unsigned chunk_size = 0, bool msv_first = true)
+ {
+#ifdef BOOST_LITTLE_ENDIAN
+ if(((chunk_size % CHAR_BIT) == 0) && !msv_first)
+ return detail::import_bits_fast(val, i, j, chunk_size);
+#endif
+ return detail::import_bits_generic(val, i, j, chunk_size, msv_first);
+ }
namespace detail {
@@ -152,6 +203,7 @@ namespace boost {
boost::uintmax_t mask = count == std::numeric_limits<boost::uintmax_t>::digits ? ~static_cast<boost::uintmax_t>(0) : (static_cast<boost::uintmax_t>(1u) << count) - 1;
return (result >> location) & mask;
}
+
}
template <unsigned MinBits, unsigned MaxBits, cpp_integer_type SignType, cpp_int_check_type Checked, class Allocator, expression_template_option ExpressionTemplates, class OutputIterator>