00001 /* 00002 The Extended Integer (XInt) Library 00003 A fast, portable C++ library for multi-precision integer math 00004 Copyright 2010 by Chad Nelson 00005 00006 Distributed under the Boost Software License, Version 1.0. 00007 See accompanying file LICENSE_1_0.txt or copy at 00008 http://www.boost.org/LICENSE_1_0.txt 00009 00010 See http://www.boost.org/libs/xint for library home page. 00011 */ 00012 00017 #ifndef BOOST_INCLUDED_XINT_INTEGER_OPTIONS_HPP 00018 #define BOOST_INCLUDED_XINT_INTEGER_OPTIONS_HPP 00019 00020 namespace boost { 00021 namespace xint { 00022 00023 #ifndef BOOST_XINT_DOXYGEN_IGNORE 00024 BOOST_PARAMETER_TEMPLATE_KEYWORD(fixedlength_tag) 00025 BOOST_PARAMETER_TEMPLATE_KEYWORD(threadsafe_tag) 00026 BOOST_PARAMETER_TEMPLATE_KEYWORD(secure_tag) 00027 BOOST_PARAMETER_TEMPLATE_KEYWORD(nothrow_tag) 00028 BOOST_PARAMETER_TEMPLATE_KEYWORD(allocator_tag) 00029 BOOST_PARAMETER_TEMPLATE_KEYWORD(sign_tag) 00030 #endif // BOOST_XINT_DOXYGEN_IGNORE 00031 00032 using boost::is_base_of; 00033 using boost::mpl::_; 00034 using boost::parameter::binding; 00035 using boost::parameter::optional; 00036 using boost::parameter::deduced; 00037 00038 #ifndef BOOST_XINT_DOXYGEN_IGNORE 00039 namespace detail { 00040 enum negative_policy { 00041 // This says it's signed, and is the default. 00042 p_signed_type, 00043 00044 // This says it's unsigned, and to use the default negative policy (modulus 00045 // for fixed-length, throw_exception for variable-length). 00046 p_unsigned_type, 00047 00048 // These say that it's unsigned, and to use the specific negative policy 00049 // named. 00050 p_modulus, 00051 p_throw_exception, // or return Not-a-Number for nothrow types 00052 p_force_zero, 00053 p_force_absolute 00054 }; 00055 } // namespace detail 00056 #endif // BOOST_XINT_DOXYGEN_IGNORE 00057 00073 namespace options { 00074 00075 #ifndef BOOST_XINT_DOXYGEN_IGNORE 00076 struct fixedlength_base { }; 00077 struct threadsafe_base { }; 00078 struct secure_base { }; 00079 struct nothrow_base { }; 00080 struct sign_base { }; 00081 #endif // BOOST_XINT_DOXYGEN_IGNORE 00082 00085 00095 template <bitsize_t Bits> struct fixedlength: public fixedlength_base, public 00096 boost::mpl::integral_c<bitsize_t, Bits> { }; 00098 00101 00112 struct threadsafe: public threadsafe_base, public boost::mpl::bool_<true> { }; 00113 00127 struct copy_on_write: public threadsafe_base, public boost::mpl::bool_<false>{}; 00129 00132 00143 struct secure: public secure_base, public boost::mpl::bool_<true> { }; 00144 00151 struct nothrow: public nothrow_base, public boost::mpl::bool_<true> { }; 00153 00156 00162 struct negative_allowed: public sign_base, public 00163 boost::mpl::integral_c<detail::negative_policy, detail::p_signed_type> 00164 { }; 00165 00172 struct negative_not_allowed: public sign_base, public 00173 boost::mpl::integral_c<detail::negative_policy, detail::p_unsigned_type> 00174 { }; 00175 00183 struct negative_modulus: public sign_base, public 00184 boost::mpl::integral_c<detail::negative_policy, detail::p_modulus> 00185 { }; 00186 00193 struct negative_exception: public sign_base, public 00194 boost::mpl::integral_c<detail::negative_policy, detail::p_throw_exception> 00195 { }; 00196 00204 struct negative_zero: public sign_base, public 00205 boost::mpl::integral_c<detail::negative_policy, detail::p_force_zero> 00206 { }; 00207 00214 struct negative_absolute: public sign_base, public 00215 boost::mpl::integral_c<detail::negative_policy, detail::p_force_absolute> 00216 { }; 00218 00219 #ifndef BOOST_XINT_DOXYGEN_IGNORE 00220 typedef parameter::parameters< 00221 optional<deduced<tag::fixedlength_tag>, is_base_of<fixedlength_base, _> >, 00222 optional<deduced<tag::threadsafe_tag>, is_base_of<threadsafe_base, _> >, 00223 optional<deduced<tag::secure_tag>, is_base_of<secure_base, _> >, 00224 optional<deduced<tag::nothrow_tag>, is_base_of<nothrow_base, _> >, 00225 optional<deduced<tag::sign_tag>, is_base_of<sign_base, _> >, 00226 optional<deduced<tag::allocator_tag>, is_class<_> > 00227 > integer_signature; 00228 #endif 00229 00230 } // namespace options 00231 00232 namespace detail { 00233 00235 // integer_t data 00236 00237 #ifdef BOOST_XINT_DOXYGEN_IGNORE 00238 // The documentation should see a simplified version of the template 00239 // parameters. 00240 #define BOOST_XINT_INITIAL_APARAMS ... 00241 #define BOOST_XINT_CLASS_APARAMS ... 00242 #define BOOST_XINT_CLASS_BPARAMS other 00243 #define BOOST_XINT_APARAMS ... 00244 #define BOOST_XINT_BPARAMS other 00245 #else 00246 #define BOOST_XINT_INITIAL_APARAMS \ 00247 class A0 = parameter::void_, \ 00248 class A1 = parameter::void_, \ 00249 class A2 = parameter::void_, \ 00250 class A3 = parameter::void_, \ 00251 class A4 = parameter::void_, \ 00252 class A5 = parameter::void_ 00253 #define BOOST_XINT_CLASS_APARAMS class A0, class A1, class A2, class A3, \ 00254 class A4, class A5 00255 #define BOOST_XINT_APARAMS A0, A1, A2, A3, A4, A5 00256 #define BOOST_XINT_CLASS_BPARAMS class B0, class B1, class B2, class B3, \ 00257 class B4, class B5 00258 #define BOOST_XINT_BPARAMS B0, B1, B2, B3, B4, B5 00259 #endif 00260 00261 #ifndef BOOST_XINT_DOXYGEN_IGNORE 00262 00263 template<BOOST_XINT_CLASS_APARAMS> 00264 class integer_t_data { 00265 public: 00266 typedef typename options::integer_signature::bind<BOOST_XINT_APARAMS>::type 00267 args; 00268 typedef const typename binding<args, tag::fixedlength_tag, 00269 options::fixedlength<0> >::type BitsType; 00270 typedef const typename binding<args, tag::threadsafe_tag, mpl::true_>::type 00271 ThreadsafeType; 00272 typedef const typename binding<args, tag::secure_tag, mpl::false_>::type 00273 SecureType; 00274 typedef const typename binding<args, tag::nothrow_tag, mpl::false_>::type 00275 NothrowType; 00276 typedef const typename binding<args, tag::sign_tag, 00277 options::negative_allowed>::type SignType; 00278 00279 static const bitsize_t Bits; 00280 static const bool Threadsafe, Secure, Nothrow, Signed; 00281 typedef typename binding<args, tag::allocator_tag, 00282 std::allocator<detail::digit_t> >::type Alloc; 00283 typedef raw_integer_t<BitsType::value, SecureType::value, Alloc> datatype; 00284 00285 integer_t_data() { } 00286 integer_t_data(const datatype& copy): data(copy) { } 00287 template <bitsize_t B, bool S, class A> 00288 integer_t_data(const raw_integer_t<B,S,A>& copy): data(copy) { } 00289 00291 00292 datatype& _data() { return data; } 00293 const datatype& _data() const { return data; } 00294 std::size_t _get_length() const { return data.length; } 00295 detail::digit_t _get_digit(std::size_t i) const { return data[i]; } 00296 void _make_unique() { data.make_unique(); } 00298 00299 protected: 00300 datatype data; 00301 }; 00302 00303 template<BOOST_XINT_CLASS_APARAMS> 00304 const bitsize_t integer_t_data<BOOST_XINT_APARAMS>::Bits = 00305 integer_t_data<BOOST_XINT_APARAMS>::BitsType::value; 00306 00307 template<BOOST_XINT_CLASS_APARAMS> 00308 const bool integer_t_data<BOOST_XINT_APARAMS>::Threadsafe = 00309 integer_t_data<BOOST_XINT_APARAMS>::ThreadsafeType::value; 00310 00311 template<BOOST_XINT_CLASS_APARAMS> 00312 const bool integer_t_data<BOOST_XINT_APARAMS>::Secure = 00313 integer_t_data<BOOST_XINT_APARAMS>::SecureType::value; 00314 00315 template<BOOST_XINT_CLASS_APARAMS> 00316 const bool integer_t_data<BOOST_XINT_APARAMS>::Nothrow = 00317 integer_t_data<BOOST_XINT_APARAMS>::NothrowType::value; 00318 00319 template<BOOST_XINT_CLASS_APARAMS> 00320 const bool integer_t_data<BOOST_XINT_APARAMS>::Signed = 00321 (integer_t_data<BOOST_XINT_APARAMS>::SignType::value == p_signed_type); 00322 00324 // class nan_functions, to handle nothrow-specific Not-a-Number stuff 00325 00326 template <bool Nothrow, typename T, BOOST_XINT_CLASS_APARAMS> 00327 class nan_functions { }; 00328 00329 template <typename T, BOOST_XINT_CLASS_APARAMS> 00330 class nan_functions<false, T, BOOST_XINT_APARAMS>: virtual public 00331 integer_t_data<BOOST_XINT_APARAMS> 00332 { 00333 public: 00334 bool is_nan() const { return false; } 00335 }; 00336 00337 template <typename T, BOOST_XINT_CLASS_APARAMS> 00338 class nan_functions<true, T, BOOST_XINT_APARAMS>: virtual public 00339 integer_t_data<BOOST_XINT_APARAMS> 00340 { 00341 public: 00342 bool is_nan() const { 00343 return integer_t_data<BOOST_XINT_APARAMS>::data.is_nan(); 00344 } 00345 00346 static T nan() { return get_nan<T>(); } 00347 }; 00348 00350 // class fixed_functions, to handle fixed-specific stuff 00351 00352 template <bitsize_t Bits, typename T, BOOST_XINT_CLASS_APARAMS> 00353 class fixed_functions: virtual public integer_t_data<BOOST_XINT_APARAMS> { 00354 using integer_t_data<BOOST_XINT_APARAMS>::Threadsafe; 00355 using integer_t_data<BOOST_XINT_APARAMS>::Nothrow; 00356 using integer_t_data<BOOST_XINT_APARAMS>::Signed; 00357 00358 public: 00359 T operator~() const { 00360 if (Nothrow) { 00361 if (integer_t_data<BOOST_XINT_APARAMS>::data.is_nan()) 00362 return detail::get_nan<T>(); 00363 BOOST_XINT_TRY { 00364 T r(~integer_t_data<BOOST_XINT_APARAMS>::data); 00365 if (Threadsafe == true) r._make_unique(); 00366 if (!Signed) r.data.negative = false; 00367 else r.data.negative = !r.data.negative; 00368 return BOOST_XINT_MOVE(r); 00369 } BOOST_XINT_CATCH { 00370 return detail::get_nan<T>(); 00371 } 00372 } else { 00373 T r(~integer_t_data<BOOST_XINT_APARAMS>::data); 00374 if (Threadsafe == true) r._make_unique(); 00375 if (!Signed) r.data.negative = false; 00376 else r.data.negative = !r.data.negative; 00377 return BOOST_XINT_MOVE(r); 00378 } 00379 } 00380 }; 00381 00382 template <typename T, BOOST_XINT_CLASS_APARAMS> 00383 class fixed_functions<0, T, BOOST_XINT_APARAMS>: virtual public 00384 integer_t_data<BOOST_XINT_APARAMS> 00385 { 00386 // Nothing needed here at present. 00387 }; 00388 00390 // class unsigned_negative_functions, for... well, unsigned negatives. :-) 00391 00392 template <negative_policy P, BOOST_XINT_CLASS_APARAMS> 00393 class unsigned_negative_functions { }; 00394 00395 template <BOOST_XINT_CLASS_APARAMS> 00396 class unsigned_negative_functions<p_signed_type, BOOST_XINT_APARAMS> { 00397 public: 00398 void _fix_negative_unsigned() { } // Nothing to do for signed numbers 00399 }; 00400 00401 template <BOOST_XINT_CLASS_APARAMS> 00402 class unsigned_negative_functions<p_unsigned_type, BOOST_XINT_APARAMS>: virtual 00403 public integer_t_data<BOOST_XINT_APARAMS>, public 00404 unsigned_negative_functions<(integer_t_data<BOOST_XINT_APARAMS>::BitsType:: 00405 value != 0 ? p_modulus : p_throw_exception), BOOST_XINT_APARAMS> 00406 { 00407 // Don't need anything here, it inherits from the proper default item 00408 // (modulus for fixed-length, throw_exception for variable-length) 00409 }; 00410 00411 template <BOOST_XINT_CLASS_APARAMS> 00412 class unsigned_negative_functions<p_modulus, BOOST_XINT_APARAMS>: virtual 00413 public integer_t_data<BOOST_XINT_APARAMS> 00414 { 00415 // Types using unsigned_modulus must be fixedlength too. 00416 typedef typename integer_t_data<BOOST_XINT_APARAMS>::BitsType BitsType; 00417 BOOST_STATIC_ASSERT(BitsType::value != 0); 00418 00419 public: 00420 void _fix_negative_unsigned() { 00421 typename integer_t_data<BOOST_XINT_APARAMS>::datatype& 00422 data(integer_t_data<BOOST_XINT_APARAMS>::_data()); 00423 data = ~data; 00424 ++data; 00425 } 00426 }; 00427 00428 template <BOOST_XINT_CLASS_APARAMS> 00429 class unsigned_negative_functions<p_throw_exception, BOOST_XINT_APARAMS>: 00430 virtual public integer_t_data<BOOST_XINT_APARAMS> 00431 { 00432 public: 00433 void _fix_negative_unsigned() { 00434 if (integer_t_data<BOOST_XINT_APARAMS>::NothrowType::value) { 00435 integer_t_data<BOOST_XINT_APARAMS>::_data().make_nan(); 00436 } else { 00437 exception_handler<>::call(__FILE__, __LINE__, 00438 exceptions::cannot_represent("unsigned negative value")); 00439 } 00440 } 00441 }; 00442 00443 template <BOOST_XINT_CLASS_APARAMS> 00444 class unsigned_negative_functions<p_force_zero, BOOST_XINT_APARAMS>: virtual 00445 public integer_t_data<BOOST_XINT_APARAMS> 00446 { 00447 public: 00448 void _fix_negative_unsigned() { 00449 typename integer_t_data<BOOST_XINT_APARAMS>::datatype& 00450 data(integer_t_data<BOOST_XINT_APARAMS>::_data()); 00451 data.set(0); 00452 } 00453 }; 00454 00455 template <BOOST_XINT_CLASS_APARAMS> 00456 class unsigned_negative_functions<p_force_absolute, BOOST_XINT_APARAMS>: virtual 00457 public integer_t_data<BOOST_XINT_APARAMS> 00458 { 00459 public: 00460 void _fix_negative_unsigned() { 00461 typename integer_t_data<BOOST_XINT_APARAMS>::datatype& 00462 data(integer_t_data<BOOST_XINT_APARAMS>::_data()); 00463 data.negative = false; 00464 } 00465 }; 00466 00467 #endif // BOOST_XINT_DOXYGEN_IGNORE 00468 00469 } // namespace detail 00470 } // namespace xint 00471 } // namespace boost 00472 00473 #endif // BOOST_INCLUDED_XINT_INTEGER_OPTIONS_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)