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_RAW_INTEGER_HPP 00022 #define BOOST_INCLUDED_XINT_RAW_INTEGER_HPP 00023 00024 namespace boost { 00025 namespace xint { 00026 namespace detail { 00028 00029 #define BOOST_XINT_RAWINT_TPL template <bitsize_t Bits, bool Secure, class \ 00030 Alloc> 00031 #define BOOST_XINT_RAWINT raw_integer_t<Bits, Secure, Alloc> 00032 00033 BOOST_XINT_RAWINT_TPL 00034 class raw_integer_t { 00035 public: 00036 typedef magnitude_manager_t<Bits, Secure, Alloc> datatype; 00037 typedef base_divide_t<BOOST_XINT_RAWINT> divide_t; 00038 00039 std::size_t length; 00040 bool negative; 00041 00042 raw_integer_t(): length(1), negative(false), changed(false) { } 00043 raw_integer_t(const BOOST_XINT_RAWINT& copy): length(copy.length), 00044 negative(copy.negative), changed(false), data(copy.data) { } 00045 template <bitsize_t B, bool S, class A> 00046 raw_integer_t(const raw_integer_t<B,S,A>& copy): length(copy.length), 00047 negative(copy.negative), changed(true), data(copy.data) { make_unique(); 00048 if (length > max_length()) length = max_length(); 00049 trim(); } 00050 raw_integer_t(const BOOST_XINT_RAWINT& copy, bool neg, bool allow_zero = 00051 false): length(copy.length), negative(neg), changed(false), 00052 data(copy.data) { trim(allow_zero); } 00053 template <typename T> 00054 raw_integer_t(T n, std::size_t prealloc = 0, typename boost::enable_if< 00055 boost::is_integral<T> >::type* = 0): length(1), negative(false), 00056 changed(false) { if (std::numeric_limits<T>::is_signed) set_signed(n, 00057 prealloc); else set_unsigned(n, false, prealloc); } 00058 template <typename charT> 00059 raw_integer_t(const charT *s, std::size_t base = 10): length(1), 00060 negative(false), changed(false) { from_string(s, base); } 00061 template <typename charT> 00062 raw_integer_t(const charT *s, const charT*& endptr, std::size_t base = 10): 00063 length(1), negative(false), changed(false) { from_string(s, endptr, 00064 base); } 00065 template <typename charT, typename traitsT, typename allocT> 00066 raw_integer_t(const std::basic_string<charT, traitsT, allocT>& s, 00067 std::size_t base = 10): length(1), negative(false), changed(false) { 00068 from_string(s, base); } 00069 raw_integer_t(const xint::binary_t b, std::size_t bits = 0): length(1), 00070 negative(false), changed(false) { from_binary(b, bits); } 00071 00072 BOOST_XINT_RAWINT& operator=(const BOOST_XINT_RAWINT& set) { length = 00073 set.length; negative = set.negative; data = set.data; return *this; } 00074 00075 digit_t *digits(std::size_t resize, realloc::strategy strategy = 00076 realloc::copy); 00077 const digit_t *digits() const { return data.digits(); } 00078 00079 digit_t get_digit(std::size_t i) const { return (i < max_length() ? 00080 digits()[i] : 0); } 00081 digit_t operator[](std::size_t i) { return digits()[i]; } 00082 digit_t operator[](std::size_t i) const { return get_digit(i); } 00083 std::size_t max_length() const { return data.max_length(); } 00084 bool same_storage(const BOOST_XINT_RAWINT n) const { return 00085 data.same_storage(n.data); } 00086 00087 int sign() const { return negative ? -1 : is_zero() ? 0 : 1; } 00088 int sign(bool allow_signed_zero) const { return (!allow_signed_zero && 00089 is_zero() ? 0 : negative ? -1 : 1); } 00090 bool is_zero() const { return (length == 1 && digits()[0] == 0); } 00091 bool is_odd() const { return (digits()[0] & 0x01) != 0; } 00092 bool is_even() const { return (digits()[0] & 0x01) == 0; } 00093 std::size_t hex_digits() const { return (log2(*this) + 3) / 4; } 00094 raw_integer_t abs() const { return raw_integer_t(*this, false); } 00095 raw_integer_t negate() const { return raw_integer_t(*this, !negative); } 00096 00097 void set(int n) { set_signed(n); } 00098 void set_signed(boost::intmax_t n, std::size_t prealloc = 0); 00099 void set_unsigned(boost::uintmax_t n, bool neg = false, std::size_t prealloc 00100 = 0); 00101 00102 bool is_nan() const { return data.is_nan(); } 00103 void make_nan() { data.make_nan(); } 00104 00105 bool is_unique() const { return data.is_unique(); } 00106 void make_unique() { if (!is_unique()) data.resize_and_uniquify(length); } 00107 00108 void trim(bool allow_negative_zero = false); 00109 00110 raw_integer_t& operator++(); // Preincrement 00111 raw_integer_t& operator--(); // Predecrement 00112 raw_integer_t operator++(int); // Postincrement 00113 raw_integer_t operator--(int); // Postdecrement 00114 00115 bool operator!() const { return is_zero(); } 00116 raw_integer_t operator-() const { return BOOST_XINT_RAWINT(*this, 00117 !negative, true); } 00118 raw_integer_t& operator+() { return *this; } 00119 const raw_integer_t& operator+() const { return *this; } 00120 raw_integer_t operator~() const; // For fixed-size types only! 00121 00122 raw_integer_t& operator+=(const raw_integer_t b); 00123 raw_integer_t& operator-=(const raw_integer_t b); 00124 raw_integer_t& operator*=(const raw_integer_t b); 00125 raw_integer_t& operator/=(const raw_integer_t b); 00126 raw_integer_t& operator%=(const raw_integer_t b); 00127 00128 raw_integer_t& operator&=(const raw_integer_t n); 00129 raw_integer_t& operator|=(const raw_integer_t n); 00130 raw_integer_t& operator^=(const raw_integer_t n); 00131 raw_integer_t& operator<<=(std::size_t shift); 00132 raw_integer_t& operator>>=(std::size_t shift); 00133 00134 template <typename charT> 00135 void from_string(const charT *str, std::size_t base = 10); 00136 template <typename charT> 00137 void from_string(const charT *str, const charT*& endptr, std::size_t base = 00138 10); 00139 template <typename charT, typename traitsT, typename allocT> 00140 void from_string(const std::basic_string<charT, traitsT, allocT>& str, 00141 std::size_t base = 10); 00142 void from_binary(xint::binary_t b, std::size_t bits = 0); 00143 00144 template <class GenType> 00145 static raw_integer_t random_by_size(GenType& gen, bitsize_t bits, bool 00146 high_bit_on = false, bool low_bit_on = false, bool can_be_negative = 00147 false); 00148 00149 template <class GenType> 00150 static raw_integer_t random_prime(GenType& gen, std::size_t size_in_bits, 00151 callback_t callback = no_callback); 00152 00153 void _swap(BOOST_XINT_RAWINT& i2); 00154 00155 private: 00156 bool changed; 00157 datatype data; 00158 00159 template <bitsize_t B, bool S, class A> 00160 friend class raw_integer_t; 00161 }; 00162 00163 BOOST_XINT_RAWINT_TPL 00164 digit_t *BOOST_XINT_RAWINT::digits(std::size_t resize, realloc::strategy 00165 strategy) 00166 { 00167 data.resize_and_uniquify(resize, strategy); 00168 if (resize == 0 || resize > data.max_length()) resize = data.max_length(); 00169 if (strategy != realloc::copy) { 00170 if (length < resize) { 00171 if (strategy == realloc::extend) { 00172 digit_t *d = data.digits(), *p = d + length, *pe = d + resize; 00173 while (p != pe) *p++ = 0; 00174 } 00175 length = resize; 00176 } else if (length > data.max_length()) length = data.max_length(); 00177 } else if (length > data.max_length()) length = data.max_length(); 00178 changed = true; 00179 return data.digits(); 00180 } 00181 00182 BOOST_XINT_RAWINT_TPL 00183 void BOOST_XINT_RAWINT::set_signed(boost::intmax_t n, std::size_t prealloc) { 00184 if (n >= 0) { 00185 if (n <= digit_mask) { 00186 length = 1; 00187 negative = false; 00188 if (prealloc != 0) { 00189 digits(prealloc, realloc::zero)[0] = static_cast<digit_t>(n); 00190 } else { 00191 digits(1, realloc::ignore)[0] = static_cast<digit_t>(n); 00192 } 00193 trim(); 00194 } else set_unsigned(n, false, prealloc); 00195 } else if (n == (std::numeric_limits<boost::intmax_t>::min)()) { 00196 // Have to treat the minimum number carefully, because -n is not 00197 // what you'd think it is. 00198 set_unsigned(-(n + 1), true, prealloc); 00199 --*this; 00200 } else set_unsigned(-n, true, prealloc); 00201 } 00202 00203 BOOST_XINT_RAWINT_TPL 00204 void BOOST_XINT_RAWINT::set_unsigned(boost::uintmax_t n, bool neg, std::size_t 00205 prealloc) 00206 { 00207 if (n <= digit_mask) { 00208 length = 1; 00209 if (prealloc != 0) { 00210 digits(prealloc, realloc::zero)[0] = static_cast<digit_t>(n); 00211 } else { 00212 digits(1, realloc::ignore)[0] = static_cast<digit_t>(n); 00213 } 00214 } else { 00215 digit_t *d = digits((std::max)(digits_in_uintmax, prealloc), 00216 realloc::ignore), *i = d, *ie = i + max_length(); 00217 while (n != 0 && i != ie) { 00218 *i++ = static_cast<digit_t>(n); 00219 n >>= bits_per_digit; 00220 } 00221 length = (i - d); 00222 } 00223 negative = neg; 00224 trim(); 00225 } 00226 00227 BOOST_XINT_RAWINT_TPL 00228 void BOOST_XINT_RAWINT::trim(bool allow_negative_zero) { 00229 assert(length <= max_length()); 00230 00231 bool zero = false; 00232 if (changed) { 00233 data.trim(); 00234 if (length > 1) { 00235 digit_t *d = data.digits(), *i = d + length - 1; 00236 if (*i == 0) { 00237 do { --i; } while (i > d && *i == 0); 00238 length = std::size_t(i - d) + 1; 00239 if (i == d && *i == 0) zero = true; 00240 } 00241 } else if (data.digits()[0] == 0) zero = true; 00242 changed = false; 00243 } else if (length == 1 && data.digits()[0] == 0) zero = true; 00244 if (zero && !allow_negative_zero) negative = false; 00245 } 00246 00247 BOOST_XINT_RAWINT_TPL 00248 void BOOST_XINT_RAWINT::_swap(BOOST_XINT_RAWINT& i2) { 00249 using std::swap; 00250 swap(length, i2.length); 00251 swap(negative, i2.negative); 00252 swap(changed, i2.changed); 00253 swap(data, i2.data); 00254 } 00255 00257 // Free functions 00258 00259 BOOST_XINT_RAWINT_TPL 00260 void swap(BOOST_XINT_RAWINT& i1, BOOST_XINT_RAWINT& i2) { 00261 i1._swap(i2); 00262 } 00263 00265 } // namespace detail 00266 } // namespace xint 00267 } // namespace boost 00268 00269 #endif // BOOST_INCLUDED_XINT_RAW_INTEGER_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)