00001 00002 /* 00003 The Extended Integer (XInt) Library 00004 A fast, portable C++ library for multi-precision integer math 00005 Copyright 2010 by Chad Nelson 00006 00007 Distributed under the Boost Software License, Version 1.0. 00008 See accompanying file LICENSE_1_0.txt or copy at 00009 http://www.boost.org/LICENSE_1_0.txt 00010 00011 See http://www.boost.org/libs/xint for library home page. 00012 */ 00013 00020 #ifndef BOOST_XINT_INCLUDED_BITQUEUET_HPP 00021 #define BOOST_XINT_INCLUDED_BITQUEUET_HPP 00022 00024 namespace boost { 00025 namespace xint { 00026 namespace detail { 00027 00029 class bitqueue_t { 00030 public: 00031 bitqueue_t(): bits_pending(0) { } 00032 void push(doubledigit_t bits, std::size_t count); 00033 doubledigit_t pop(std::size_t requestedbits); 00034 bool empty() const { return pending.empty(); } 00035 std::size_t size() const { return bits_pending; } 00036 00037 private: 00038 static const std::size_t ddbits = 00039 std::numeric_limits<doubledigit_t>::digits; 00040 typedef std::pair<doubledigit_t, std::size_t> indata_t; 00041 typedef std::queue<indata_t> inqueue_t; 00042 00043 std::size_t bits_pending; 00044 inqueue_t pending; 00045 }; 00046 00047 inline void bitqueue_t::push(doubledigit_t bits, std::size_t count) { 00048 if (count < ddbits) { 00049 doubledigit_t mask = (doubledigit_t(1) << count) - 1; 00050 bits &= mask; 00051 } 00052 00053 if (pending.empty()) { 00054 pending.push(std::make_pair(bits, count)); 00055 } else { 00056 indata_t &n(pending.back()); 00057 if (n.second + count <= ddbits) { 00058 n.first |= bits << n.second; 00059 n.second += count; 00060 } else { 00061 pending.push(std::make_pair(bits, count)); 00062 } 00063 } 00064 bits_pending += count; 00065 } 00066 00067 inline doubledigit_t bitqueue_t::pop(std::size_t requestedbits) { 00068 doubledigit_t buffer = 0; 00069 std::size_t bits_in_buffer = 0; 00070 while (bits_in_buffer < requestedbits && !pending.empty()) { 00071 indata_t &n(pending.front()); 00072 std::size_t maxbits = requestedbits - bits_in_buffer, actualbits = 00073 (std::min)(n.second, maxbits); 00074 buffer |= (n.first << bits_in_buffer); 00075 00076 n.first >>= actualbits; 00077 n.second -= actualbits; 00078 bits_in_buffer += actualbits; 00079 bits_pending -= actualbits; 00080 00081 if (n.second == 0) pending.pop(); 00082 } 00083 return (buffer & ((doubledigit_t(1) << requestedbits) - 1)); 00084 } 00085 00086 } // namespace detail 00087 } // namespace xint 00088 } // namespace boost 00090 00091 #endif // BOOST_XINT_INCLUDED_BITQUEUET_HPP
© Copyright Chad Nelson, 2010-2011. Distributed under 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)