diff options
Diffstat (limited to 'boost/multiprecision/cpp_int/import_export.hpp')
-rw-r--r-- | boost/multiprecision/cpp_int/import_export.hpp | 104 |
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> |