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 00021 #ifndef BOOST_INCLUDED_XINT_ROOTS_HPP 00022 #define BOOST_INCLUDED_XINT_ROOTS_HPP 00023 00025 namespace boost { 00026 namespace xint { 00027 namespace detail { 00028 00029 BOOST_XINT_RAWINT_TPL 00030 BOOST_XINT_RAWINT square_root(BOOST_XINT_RAWINT n) { 00031 if (n.is_zero()) return 0; 00032 if (n.negative) exception_handler<>::call(__FILE__, __LINE__, 00033 exceptions::cannot_represent("cannot represent imaginary values (tried " 00034 "to take square_root of negative number)")); 00035 00036 // A naive implementation using pure integers can result in an endless loop, 00037 // cycling between two numbers that are approximately correct (try 00038 // sqrt(23)). To deal with that, we multiply everything by an even power of 00039 // two. 00040 const std::size_t extra_bits = 1; 00041 n <<= (extra_bits * 2); 00042 00043 // Initial guess is half the length of n, in bits 00044 BOOST_XINT_RAWINT target; 00045 setbit(target, log2(n) / 2); 00046 00047 // Now refine it until we're as close as we can get. 00048 while (1) { 00049 BOOST_XINT_RAWINT guess((target + (n / target)) >> 1); 00050 if ((target >> extra_bits) == (guess >> extra_bits)) break; 00051 target = guess; 00052 } 00053 00054 // Remove half of the added bits. 00055 target >>= extra_bits; 00056 return target; 00057 } 00058 00059 } // namespace detail 00060 } // namespace xint 00061 } // namespace boost 00063 00064 #endif // BOOST_INCLUDED_XINT_ROOTS_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)