annotate DEPENDENCIES/generic/include/boost/multiprecision/integer.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////
Chris@16 2 // Copyright 2012 John Maddock. Distributed under the Boost
Chris@16 3 // Software License, Version 1.0. (See accompanying file
Chris@16 4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
Chris@16 5
Chris@16 6 #ifndef BOOST_MP_INTEGER_HPP
Chris@16 7 #define BOOST_MP_INTEGER_HPP
Chris@16 8
Chris@16 9 #include <boost/multiprecision/cpp_int.hpp>
Chris@16 10 #include <boost/multiprecision/detail/bitscan.hpp>
Chris@16 11
Chris@16 12 namespace boost{
Chris@16 13 namespace multiprecision{
Chris@16 14
Chris@16 15 template <class Integer, class I2>
Chris@16 16 typename enable_if_c<is_integral<Integer>::value && is_integral<I2>::value, Integer&>::type
Chris@16 17 multiply(Integer& result, const I2& a, const I2& b)
Chris@16 18 {
Chris@16 19 return result = static_cast<Integer>(a) * static_cast<Integer>(b);
Chris@16 20 }
Chris@16 21 template <class Integer, class I2>
Chris@16 22 typename enable_if_c<is_integral<Integer>::value && is_integral<I2>::value, Integer&>::type
Chris@16 23 add(Integer& result, const I2& a, const I2& b)
Chris@16 24 {
Chris@16 25 return result = static_cast<Integer>(a) + static_cast<Integer>(b);
Chris@16 26 }
Chris@16 27 template <class Integer, class I2>
Chris@16 28 typename enable_if_c<is_integral<Integer>::value && is_integral<I2>::value, Integer&>::type
Chris@16 29 subtract(Integer& result, const I2& a, const I2& b)
Chris@16 30 {
Chris@16 31 return result = static_cast<Integer>(a) - static_cast<Integer>(b);
Chris@16 32 }
Chris@16 33
Chris@16 34 template <class Integer>
Chris@16 35 typename enable_if_c<is_integral<Integer>::value>::type divide_qr(const Integer& x, const Integer& y, Integer& q, Integer& r)
Chris@16 36 {
Chris@16 37 q = x / y;
Chris@16 38 r = x % y;
Chris@16 39 }
Chris@16 40
Chris@16 41 template <class I1, class I2>
Chris@16 42 typename enable_if_c<is_integral<I1>::value && is_integral<I2>::value, I2>::type integer_modulus(const I1& x, I2 val)
Chris@16 43 {
Chris@16 44 return static_cast<I2>(x % val);
Chris@16 45 }
Chris@16 46
Chris@16 47 namespace detail{
Chris@16 48 //
Chris@16 49 // Figure out the kind of integer that has twice as many bits as some builtin
Chris@16 50 // integer type I. Use a native type if we can (including types which may not
Chris@16 51 // be recognised by boost::int_t because they're larger than long long),
Chris@16 52 // otherwise synthesize a cpp_int to do the job.
Chris@16 53 //
Chris@16 54 template <class I>
Chris@16 55 struct double_integer
Chris@16 56 {
Chris@16 57 static const unsigned int_t_digits =
Chris@16 58 2 * sizeof(I) <= sizeof(long long) ? std::numeric_limits<I>::digits * 2 : 1;
Chris@16 59
Chris@16 60 typedef typename mpl::if_c<
Chris@16 61 2 * sizeof(I) <= sizeof(long long),
Chris@16 62 typename mpl::if_c<
Chris@16 63 is_signed<I>::value,
Chris@16 64 typename boost::int_t<int_t_digits>::least,
Chris@16 65 typename boost::uint_t<int_t_digits>::least
Chris@16 66 >::type,
Chris@16 67 typename mpl::if_c<
Chris@16 68 2 * sizeof(I) <= sizeof(double_limb_type),
Chris@16 69 typename mpl::if_c<
Chris@16 70 is_signed<I>::value,
Chris@16 71 signed_double_limb_type,
Chris@16 72 double_limb_type
Chris@16 73 >::type,
Chris@16 74 number<cpp_int_backend<sizeof(I)*CHAR_BIT*2, sizeof(I)*CHAR_BIT*2, (is_signed<I>::value ? signed_magnitude : unsigned_magnitude), unchecked, void> >
Chris@16 75 >::type
Chris@16 76 >::type type;
Chris@16 77 };
Chris@16 78
Chris@16 79 }
Chris@16 80
Chris@16 81 template <class I1, class I2, class I3>
Chris@101 82 typename enable_if_c<is_integral<I1>::value && is_unsigned<I2>::value && is_integral<I3>::value, I1>::type
Chris@16 83 powm(const I1& a, I2 b, I3 c)
Chris@16 84 {
Chris@16 85 typedef typename detail::double_integer<I1>::type double_type;
Chris@16 86
Chris@16 87 I1 x(1), y(a);
Chris@16 88 double_type result;
Chris@16 89
Chris@16 90 while(b > 0)
Chris@16 91 {
Chris@16 92 if(b & 1)
Chris@16 93 {
Chris@16 94 multiply(result, x, y);
Chris@16 95 x = integer_modulus(result, c);
Chris@16 96 }
Chris@16 97 multiply(result, y, y);
Chris@16 98 y = integer_modulus(result, c);
Chris@16 99 b >>= 1;
Chris@16 100 }
Chris@16 101 return x % c;
Chris@16 102 }
Chris@16 103
Chris@101 104 template <class I1, class I2, class I3>
Chris@101 105 inline typename enable_if_c<is_integral<I1>::value && is_signed<I2>::value && is_integral<I3>::value, I1>::type
Chris@101 106 powm(const I1& a, I2 b, I3 c)
Chris@101 107 {
Chris@101 108 if(b < 0)
Chris@101 109 {
Chris@101 110 BOOST_THROW_EXCEPTION(std::runtime_error("powm requires a positive exponent."));
Chris@101 111 }
Chris@101 112 return powm(a, static_cast<typename make_unsigned<I2>::type>(b), c);
Chris@101 113 }
Chris@101 114
Chris@16 115 template <class Integer>
Chris@16 116 typename enable_if_c<is_integral<Integer>::value, unsigned>::type lsb(const Integer& val)
Chris@16 117 {
Chris@16 118 if(val <= 0)
Chris@16 119 {
Chris@16 120 if(val == 0)
Chris@16 121 {
Chris@16 122 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
Chris@16 123 }
Chris@16 124 else
Chris@16 125 {
Chris@16 126 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
Chris@16 127 }
Chris@16 128 }
Chris@16 129 return detail::find_lsb(val);
Chris@16 130 }
Chris@16 131
Chris@16 132 template <class Integer>
Chris@16 133 typename enable_if_c<is_integral<Integer>::value, unsigned>::type msb(Integer val)
Chris@16 134 {
Chris@16 135 if(val <= 0)
Chris@16 136 {
Chris@16 137 if(val == 0)
Chris@16 138 {
Chris@16 139 BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
Chris@16 140 }
Chris@16 141 else
Chris@16 142 {
Chris@16 143 BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
Chris@16 144 }
Chris@16 145 }
Chris@16 146 return detail::find_msb(val);
Chris@16 147 }
Chris@16 148
Chris@16 149 template <class Integer>
Chris@16 150 typename enable_if_c<is_integral<Integer>::value, bool>::type bit_test(const Integer& val, unsigned index)
Chris@16 151 {
Chris@16 152 Integer mask = 1;
Chris@16 153 if(index >= sizeof(Integer) * CHAR_BIT)
Chris@16 154 return 0;
Chris@16 155 if(index)
Chris@16 156 mask <<= index;
Chris@16 157 return val & mask ? true : false;
Chris@16 158 }
Chris@16 159
Chris@16 160 template <class Integer>
Chris@16 161 typename enable_if_c<is_integral<Integer>::value, Integer&>::type bit_set(Integer& val, unsigned index)
Chris@16 162 {
Chris@16 163 Integer mask = 1;
Chris@16 164 if(index >= sizeof(Integer) * CHAR_BIT)
Chris@16 165 return val;
Chris@16 166 if(index)
Chris@16 167 mask <<= index;
Chris@16 168 val |= mask;
Chris@16 169 return val;
Chris@16 170 }
Chris@16 171
Chris@16 172 template <class Integer>
Chris@16 173 typename enable_if_c<is_integral<Integer>::value, Integer&>::type bit_unset(Integer& val, unsigned index)
Chris@16 174 {
Chris@16 175 Integer mask = 1;
Chris@16 176 if(index >= sizeof(Integer) * CHAR_BIT)
Chris@16 177 return val;
Chris@16 178 if(index)
Chris@16 179 mask <<= index;
Chris@16 180 val &= ~mask;
Chris@16 181 return val;
Chris@16 182 }
Chris@16 183
Chris@16 184 template <class Integer>
Chris@16 185 typename enable_if_c<is_integral<Integer>::value, Integer&>::type bit_flip(Integer& val, unsigned index)
Chris@16 186 {
Chris@16 187 Integer mask = 1;
Chris@16 188 if(index >= sizeof(Integer) * CHAR_BIT)
Chris@16 189 return val;
Chris@16 190 if(index)
Chris@16 191 mask <<= index;
Chris@16 192 val ^= mask;
Chris@16 193 return val;
Chris@16 194 }
Chris@16 195
Chris@16 196 template <class Integer>
Chris@16 197 typename enable_if_c<is_integral<Integer>::value, Integer>::type sqrt(const Integer& x, Integer& r)
Chris@16 198 {
Chris@16 199 //
Chris@16 200 // This is slow bit-by-bit integer square root, see for example
Chris@16 201 // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
Chris@16 202 // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
Chris@16 203 // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
Chris@16 204 // at some point.
Chris@16 205 //
Chris@16 206 Integer s = 0;
Chris@16 207 if(x == 0)
Chris@16 208 {
Chris@16 209 r = 0;
Chris@16 210 return s;
Chris@16 211 }
Chris@16 212 int g = msb(x);
Chris@16 213 if(g == 0)
Chris@16 214 {
Chris@16 215 r = 1;
Chris@16 216 return s;
Chris@16 217 }
Chris@16 218
Chris@101 219 Integer t = 0;
Chris@16 220 r = x;
Chris@16 221 g /= 2;
Chris@16 222 bit_set(s, g);
Chris@16 223 bit_set(t, 2 * g);
Chris@16 224 r = x - t;
Chris@16 225 --g;
Chris@16 226 do
Chris@16 227 {
Chris@16 228 t = s;
Chris@16 229 t <<= g + 1;
Chris@16 230 bit_set(t, 2 * g);
Chris@16 231 if(t <= r)
Chris@16 232 {
Chris@16 233 bit_set(s, g);
Chris@16 234 r -= t;
Chris@16 235 }
Chris@16 236 --g;
Chris@16 237 }
Chris@16 238 while(g >= 0);
Chris@16 239 return s;
Chris@16 240 }
Chris@16 241
Chris@16 242 template <class Integer>
Chris@16 243 typename enable_if_c<is_integral<Integer>::value, Integer>::type sqrt(const Integer& x)
Chris@16 244 {
Chris@16 245 Integer r;
Chris@16 246 return sqrt(x, r);
Chris@16 247 }
Chris@16 248
Chris@16 249 }} // namespaces
Chris@16 250
Chris@16 251 #endif