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_INCLUDED_XINT_SHIFT_HPP 00021 #define BOOST_INCLUDED_XINT_SHIFT_HPP 00022 00024 namespace boost { 00025 namespace xint { 00026 namespace detail { 00027 00028 BOOST_XINT_RAWINT_TPL 00029 BOOST_XINT_RAWINT& BOOST_XINT_RAWINT::operator<<=(std::size_t byBits) { 00030 if (byBits == 0) return *this; 00031 00032 // bits/dchunks is distance to move 00033 std::size_t dchunks = byBits / bits_per_digit, bits = byBits % 00034 bits_per_digit; 00035 std::size_t anslen = length + dchunks + (bits != 0 ? 1 : 0); 00036 digit_t *dstart = digits(anslen); 00037 00038 // nlen is one greater than top source byte to move 00039 std::size_t nlen = (std::min)(length, anslen - dchunks - (bits != 0 ? 1 : 00040 0)); 00041 00042 if (bits != 0 && dchunks + 1 < anslen) { 00043 // Handle both bits and dchunks in one pass 00044 const digit_t *s = dstart + nlen - 1; 00045 digit_t *t = dstart + nlen + dchunks, *te = dstart + max_length(); 00046 length = (std::min<size_t>)(t - dstart + 1, max_length()); 00047 00048 while (t >= te && s > dstart) { --t; --s; } 00049 if (t < te) *t-- = *s >> (bits_per_digit - bits); else --t; 00050 while (s > dstart) { 00051 *t = (*s-- << bits); 00052 *t-- |= (*s >> (bits_per_digit - bits)); 00053 } 00054 *t-- = (*s << bits); 00055 00056 while (t >= dstart) *t-- = 0; 00057 } else if (dchunks != 0 && dchunks < anslen) { 00058 length = anslen; 00059 memmove(dstart + dchunks, dstart, sizeof(digit_t) * nlen); 00060 memset(dstart, 0, dchunks * sizeof(digit_t)); 00061 } else { 00062 set(0); 00063 } 00064 00065 trim(); 00066 return *this; 00067 } 00068 00069 BOOST_XINT_RAWINT_TPL 00070 BOOST_XINT_RAWINT& BOOST_XINT_RAWINT::operator>>=(std::size_t byBits) { 00071 if (byBits == 0) return *this; 00072 00073 std::size_t dchunks = byBits / bits_per_digit, bits = byBits % 00074 bits_per_digit, bits2 = bits_per_digit - bits; 00075 00076 digit_t *tgt = digits(0); 00077 if (dchunks < length) { 00078 if (bits != 0) { 00079 // Handle both bits and dchunks in one pass 00080 const digit_t *s = tgt + dchunks, *se = tgt + length - 1; 00081 digit_t *t = tgt; 00082 while (s != se) { 00083 *t = (*s++ >> bits); 00084 *t++ |= (*s << bits2); 00085 } 00086 *t++ = (*s >> bits); 00087 length = (t - tgt); 00088 } else if (dchunks != 0) { 00089 memmove(tgt, tgt + dchunks, sizeof(digit_t) * (length - dchunks)); 00090 length -= dchunks; 00091 } 00092 } else set(0); 00093 trim(); 00094 return *this; 00095 } 00096 00097 BOOST_XINT_RAWINT_TPL 00098 BOOST_XINT_RAWINT operator<<(BOOST_XINT_RAWINT n, std::size_t bits) { 00099 return (n <<= bits); 00100 } 00101 00102 BOOST_XINT_RAWINT_TPL 00103 BOOST_XINT_RAWINT operator>>(BOOST_XINT_RAWINT n, std::size_t bits) { 00104 return (n >>= bits); 00105 } 00106 00107 } // namespace detail 00108 } // namespace xint 00109 } // namespace boost 00111 00112 #endif // BOOST_INCLUDED_XINT_SHIFT_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)