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_MULTIPLY_HPP 00021 #define BOOST_INCLUDED_XINT_MULTIPLY_HPP 00022 00024 namespace boost { 00025 namespace xint { 00026 namespace detail { 00027 00028 BOOST_XINT_RAWINT_TPL 00029 BOOST_XINT_RAWINT square(const BOOST_XINT_RAWINT n) { 00030 const digit_t *ndigits = n.digits(); 00031 std::size_t nlen = n.length; 00032 00033 BOOST_XINT_RAWINT target; 00034 digit_t *rdigits = target.digits(n.length * 2 + 1, realloc::zero), *rmax = 00035 rdigits + target.length; 00036 00037 // Calculate the product of digits of unequal index 00038 std::size_t i = 0; 00039 doubledigit_t c; 00040 do { 00041 const doubledigit_t ii = ndigits[i]; 00042 const digit_t *jp = ndigits + i + 1; 00043 digit_t *rp = rdigits + i + (i + 1), *rpe = rdigits + i + nlen; 00044 if (rpe > rmax) rpe = rmax; 00045 00046 c = 0; 00047 while (rp < rpe) { 00048 doubledigit_t t = ii * *jp++ + *rp + c; 00049 *rp++ = static_cast<digit_t>(t); 00050 c = (t >> bits_per_digit); 00051 } 00052 if (rp < rmax) *rp = static_cast<digit_t>(c); 00053 } while (++i < nlen - 1); 00054 00055 // Multiplication of inner products by two 00056 c = 0; 00057 digit_t *rp = rdigits + 1, *rpe = rdigits + (2 * nlen) - 1; 00058 if (rpe > rmax) rpe = rmax; 00059 00060 if (rp < rmax) { 00061 do { 00062 doubledigit_t t = (doubledigit_t(*rp) << 1) + c; 00063 *rp++ = static_cast<digit_t>(t); 00064 c = (t >> bits_per_digit); 00065 } while (rp < rpe); 00066 if (rp < rmax) *rp = static_cast<digit_t>(c); 00067 } 00068 00069 // Addition of inner squares 00070 const digit_t *ip = ndigits, *ipe = ndigits + nlen; 00071 rp = rdigits; 00072 c = 0; 00073 do { 00074 doubledigit_t t = doubledigit_t(*ip) * *ip + *rp + c; 00075 *rp++ = static_cast<digit_t>(t); 00076 if (rp >= rmax) break; 00077 c = (t >> bits_per_digit); 00078 00079 t = c + *rp; 00080 *rp++ = static_cast<digit_t>(t); 00081 if (rp >= rmax) break; 00082 c = (t >> bits_per_digit); 00083 } while (++ip < ipe); 00084 if (rp < rmax) *rp += static_cast<digit_t>(c); 00085 00086 // No need to change length 00087 target.negative = false; 00088 target.trim(); 00089 return target; 00090 } 00091 00092 BOOST_XINT_RAWINT_TPL 00093 BOOST_XINT_RAWINT multiply(const BOOST_XINT_RAWINT n, const BOOST_XINT_RAWINT 00094 by) 00095 { 00096 if (n.is_zero() || by.is_zero()) return 0; 00097 00098 if (n.same_storage(by)) { 00099 if (n.negative != by.negative) { 00100 return BOOST_XINT_RAWINT(square(n), true); 00101 } else { 00102 return square(n); 00103 } 00104 } 00105 00106 BOOST_XINT_RAWINT target; 00107 digit_t *adigits = target.digits(n.length + by.length, realloc::zero), 00108 *ae = adigits + target.max_length(); 00109 std::size_t maxdigit = target.max_length(), nlen = n.length, bylen = 00110 by.length; 00111 00112 // Now multiply the digits, starting at the least-significant digit. 00113 const digit_t *d1 = n.digits(), *d1e = d1 + (std::min)(nlen, maxdigit); 00114 for (int digit1 = 0; d1 < d1e; ++digit1, ++d1) { 00115 const digit_t *d2 = by.digits(), *d2e = d2 + (std::min)(bylen, maxdigit 00116 - digit1); 00117 for (int digit2 = 0; d2 < d2e; ++digit2, ++d2) { 00118 // First multiply the two digits 00119 doubledigit_t t = doubledigit_t(*d1) * *d2; 00120 00121 // Now add the result to the answer. 00122 int carry = 0; 00123 digit_t *a = adigits + digit1 + digit2; 00124 doubledigit_t addt = doubledigit_t(*a) + (t & digit_mask); 00125 if (addt >= digit_overflowbit) carry = 1; 00126 *a++=static_cast<digit_t>(addt); 00127 00128 if (a < ae) { 00129 addt = *a + ((t >> bits_per_digit) & digit_mask) + carry; 00130 if (addt >= digit_overflowbit) carry = 1; else carry = 0; 00131 *a++ = static_cast<digit_t>(addt); 00132 00133 while (carry && a < ae) { 00134 addt = *a + 1; 00135 *a++ = static_cast<digit_t>(addt); 00136 if (addt < digit_overflowbit) break; 00137 } 00138 } 00139 } 00140 } 00141 00142 // No need to change length 00143 target.negative = (n.negative != by.negative); 00144 target.trim(); 00145 return target; 00146 } 00147 00148 BOOST_XINT_RAWINT_TPL 00149 BOOST_XINT_RAWINT& BOOST_XINT_RAWINT::operator*=(const BOOST_XINT_RAWINT by) { 00150 *this = multiply(*this, by); 00151 return *this; 00152 } 00153 00154 BOOST_XINT_RAWINT_TPL 00155 BOOST_XINT_RAWINT operator*(const BOOST_XINT_RAWINT n1, const BOOST_XINT_RAWINT 00156 n2) 00157 { 00158 return multiply(n1, n2); 00159 } 00160 00161 } // namespace detail 00162 } // namespace xint 00163 } // namespace boost 00165 00166 #endif // BOOST_INCLUDED_XINT_MULTIPLY_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)