annotate DEPENDENCIES/generic/include/boost/ratio/detail/overflow_helpers.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 // ratio.hpp ---------------------------------------------------------------//
Chris@16 2
Chris@16 3 // Copyright 2008 Howard Hinnant
Chris@16 4 // Copyright 2008 Beman Dawes
Chris@16 5 // Copyright 2009 Vicente J. Botet Escriba
Chris@16 6
Chris@16 7 // Distributed under the Boost Software License, Version 1.0.
Chris@16 8 // See http://www.boost.org/LICENSE_1_0.txt
Chris@16 9
Chris@16 10 /*
Chris@16 11
Chris@16 12 This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
Chris@16 13 Many thanks to Howard for making his code available under the Boost license.
Chris@16 14 The original code was modified to conform to Boost conventions and to section
Chris@16 15 20.4 Compile-time rational arithmetic [ratio], of the C++ committee working
Chris@16 16 paper N2798.
Chris@16 17 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
Chris@16 18
Chris@16 19 time2_demo contained this comment:
Chris@16 20
Chris@16 21 Much thanks to Andrei Alexandrescu,
Chris@16 22 Walter Brown,
Chris@16 23 Peter Dimov,
Chris@16 24 Jeff Garland,
Chris@16 25 Terry Golubiewski,
Chris@16 26 Daniel Krugler,
Chris@16 27 Anthony Williams.
Chris@16 28 */
Chris@16 29
Chris@16 30 // The way overflow is managed for ratio_less is taken from llvm/libcxx/include/ratio
Chris@16 31
Chris@16 32 #ifndef BOOST_RATIO_DETAIL_RATIO_OPERATIONS_HPP
Chris@16 33 #define BOOST_RATIO_DETAIL_RATIO_OPERATIONS_HPP
Chris@16 34
Chris@16 35 #include <boost/ratio/config.hpp>
Chris@16 36 #include <boost/ratio/detail/mpl/abs.hpp>
Chris@16 37 #include <boost/ratio/detail/mpl/sign.hpp>
Chris@16 38 #include <cstdlib>
Chris@16 39 #include <climits>
Chris@16 40 #include <limits>
Chris@16 41 #include <boost/cstdint.hpp>
Chris@16 42 #include <boost/type_traits/integral_constant.hpp>
Chris@101 43 #include <boost/core/enable_if.hpp>
Chris@16 44 #include <boost/integer_traits.hpp>
Chris@16 45
Chris@16 46 //
Chris@16 47 // We simply cannot include this header on gcc without getting copious warnings of the kind:
Chris@16 48 //
Chris@16 49 // boost/integer.hpp:77:30: warning: use of C99 long long integer constant
Chris@16 50 //
Chris@16 51 // And yet there is no other reasonable implementation, so we declare this a system header
Chris@16 52 // to suppress these warnings.
Chris@16 53 //
Chris@16 54 #if defined(__GNUC__) && (__GNUC__ >= 4)
Chris@16 55 #pragma GCC system_header
Chris@16 56 #endif
Chris@16 57
Chris@16 58 namespace boost
Chris@16 59 {
Chris@16 60
Chris@16 61 //----------------------------------------------------------------------------//
Chris@16 62 // helpers //
Chris@16 63 //----------------------------------------------------------------------------//
Chris@16 64
Chris@16 65 namespace ratio_detail
Chris@16 66 {
Chris@16 67
Chris@16 68 template <boost::intmax_t X, boost::intmax_t Y, boost::intmax_t = mpl::sign_c<boost::intmax_t, Y>::value>
Chris@16 69 class br_add;
Chris@16 70
Chris@16 71 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 72 class br_add<X, Y, 1>
Chris@16 73 {
Chris@16 74 static const boost::intmax_t min = boost::integer_traits<boost::intmax_t>::const_min;
Chris@16 75 static const boost::intmax_t max = boost::integer_traits<boost::intmax_t>::const_max;
Chris@16 76
Chris@16 77 BOOST_RATIO_STATIC_ASSERT(X <= max - Y , BOOST_RATIO_OVERFLOW_IN_ADD, ());
Chris@16 78 public:
Chris@16 79 static const boost::intmax_t value = X + Y;
Chris@16 80 };
Chris@16 81
Chris@16 82 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 83 class br_add<X, Y, 0>
Chris@16 84 {
Chris@16 85 public:
Chris@16 86 static const boost::intmax_t value = X;
Chris@16 87 };
Chris@16 88
Chris@16 89 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 90 class br_add<X, Y, -1>
Chris@16 91 {
Chris@16 92 static const boost::intmax_t min = boost::integer_traits<boost::intmax_t>::const_min;
Chris@16 93 static const boost::intmax_t max = boost::integer_traits<boost::intmax_t>::const_max;
Chris@16 94
Chris@16 95 BOOST_RATIO_STATIC_ASSERT(min - Y <= X, BOOST_RATIO_OVERFLOW_IN_ADD, ());
Chris@16 96 public:
Chris@16 97 static const boost::intmax_t value = X + Y;
Chris@16 98 };
Chris@16 99
Chris@16 100 template <boost::intmax_t X, boost::intmax_t Y, boost::intmax_t = mpl::sign_c<boost::intmax_t, Y>::value>
Chris@16 101 class br_sub;
Chris@16 102
Chris@16 103 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 104 class br_sub<X, Y, 1>
Chris@16 105 {
Chris@16 106 static const boost::intmax_t min = boost::integer_traits<boost::intmax_t>::const_min;
Chris@16 107 static const boost::intmax_t max = boost::integer_traits<boost::intmax_t>::const_max;
Chris@16 108
Chris@16 109 BOOST_RATIO_STATIC_ASSERT(min + Y <= X, BOOST_RATIO_OVERFLOW_IN_SUB, ());
Chris@16 110 public:
Chris@16 111 static const boost::intmax_t value = X - Y;
Chris@16 112 };
Chris@16 113
Chris@16 114 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 115 class br_sub<X, Y, 0>
Chris@16 116 {
Chris@16 117 public:
Chris@16 118 static const boost::intmax_t value = X;
Chris@16 119 };
Chris@16 120
Chris@16 121 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 122 class br_sub<X, Y, -1>
Chris@16 123 {
Chris@16 124 static const boost::intmax_t min = boost::integer_traits<boost::intmax_t>::const_min;
Chris@16 125 static const boost::intmax_t max = boost::integer_traits<boost::intmax_t>::const_max;
Chris@16 126
Chris@16 127 BOOST_RATIO_STATIC_ASSERT(X <= max + Y, BOOST_RATIO_OVERFLOW_IN_SUB, ());
Chris@16 128 public:
Chris@16 129 static const boost::intmax_t value = X - Y;
Chris@16 130 };
Chris@16 131
Chris@16 132 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 133 class br_mul
Chris@16 134 {
Chris@16 135 static const boost::intmax_t nan =
Chris@16 136 boost::intmax_t(BOOST_RATIO_UINTMAX_C(1) << (sizeof(boost::intmax_t) * CHAR_BIT - 1));
Chris@16 137 static const boost::intmax_t min = boost::integer_traits<boost::intmax_t>::const_min;
Chris@16 138 static const boost::intmax_t max = boost::integer_traits<boost::intmax_t>::const_max;
Chris@16 139
Chris@16 140 static const boost::intmax_t a_x = mpl::abs_c<boost::intmax_t, X>::value;
Chris@16 141 static const boost::intmax_t a_y = mpl::abs_c<boost::intmax_t, Y>::value;
Chris@16 142
Chris@16 143 BOOST_RATIO_STATIC_ASSERT(X != nan, BOOST_RATIO_OVERFLOW_IN_MUL, ());
Chris@16 144 BOOST_RATIO_STATIC_ASSERT(Y != nan, BOOST_RATIO_OVERFLOW_IN_MUL, ());
Chris@16 145 BOOST_RATIO_STATIC_ASSERT(a_x <= max / a_y, BOOST_RATIO_OVERFLOW_IN_MUL, ());
Chris@16 146 public:
Chris@16 147 static const boost::intmax_t value = X * Y;
Chris@16 148 };
Chris@16 149
Chris@16 150 template <boost::intmax_t Y>
Chris@16 151 class br_mul<0, Y>
Chris@16 152 {
Chris@16 153 public:
Chris@16 154 static const boost::intmax_t value = 0;
Chris@16 155 };
Chris@16 156
Chris@16 157 template <boost::intmax_t X>
Chris@16 158 class br_mul<X, 0>
Chris@16 159 {
Chris@16 160 public:
Chris@16 161 static const boost::intmax_t value = 0;
Chris@16 162 };
Chris@16 163
Chris@16 164 template <>
Chris@16 165 class br_mul<0, 0>
Chris@16 166 {
Chris@16 167 public:
Chris@16 168 static const boost::intmax_t value = 0;
Chris@16 169 };
Chris@16 170
Chris@16 171 // Not actually used but left here in case needed in future maintenance
Chris@16 172 template <boost::intmax_t X, boost::intmax_t Y>
Chris@16 173 class br_div
Chris@16 174 {
Chris@16 175 static const boost::intmax_t nan = boost::intmax_t(BOOST_RATIO_UINTMAX_C(1) << (sizeof(boost::intmax_t) * CHAR_BIT - 1));
Chris@16 176 static const boost::intmax_t min = boost::integer_traits<boost::intmax_t>::const_min;
Chris@16 177 static const boost::intmax_t max = boost::integer_traits<boost::intmax_t>::const_max;
Chris@16 178
Chris@16 179 BOOST_RATIO_STATIC_ASSERT(X != nan, BOOST_RATIO_OVERFLOW_IN_DIV, ());
Chris@16 180 BOOST_RATIO_STATIC_ASSERT(Y != nan, BOOST_RATIO_OVERFLOW_IN_DIV, ());
Chris@16 181 BOOST_RATIO_STATIC_ASSERT(Y != 0, BOOST_RATIO_DIVIDE_BY_0, ());
Chris@16 182 public:
Chris@16 183 static const boost::intmax_t value = X / Y;
Chris@16 184 };
Chris@16 185
Chris@16 186 // ratio arithmetic
Chris@16 187 template <class R1, class R2> struct ratio_add;
Chris@16 188 template <class R1, class R2> struct ratio_subtract;
Chris@16 189 template <class R1, class R2> struct ratio_multiply;
Chris@16 190 template <class R1, class R2> struct ratio_divide;
Chris@16 191
Chris@16 192 template <class R1, class R2>
Chris@16 193 struct ratio_add
Chris@16 194 {
Chris@16 195 //The nested typedef type shall be a synonym for ratio<T1, T2>::type where T1 has the value R1::num *
Chris@16 196 //R2::den + R2::num * R1::den and T2 has the value R1::den * R2::den.
Chris@16 197 // As the preceding doesn't works because of overflow on boost::intmax_t we need something more elaborated.
Chris@16 198 private:
Chris@16 199 static const boost::intmax_t gcd_n1_n2 = mpl::gcd_c<boost::intmax_t, R1::num, R2::num>::value;
Chris@16 200 static const boost::intmax_t gcd_d1_d2 = mpl::gcd_c<boost::intmax_t, R1::den, R2::den>::value;
Chris@16 201 public:
Chris@16 202 // No need to normalize as ratio_multiply is already normalized
Chris@16 203 typedef typename ratio_multiply
Chris@16 204 <
Chris@16 205 ratio<gcd_n1_n2, R1::den / gcd_d1_d2>,
Chris@16 206 ratio
Chris@16 207 <
Chris@16 208 boost::ratio_detail::br_add
Chris@16 209 <
Chris@16 210 boost::ratio_detail::br_mul<R1::num / gcd_n1_n2, R2::den / gcd_d1_d2>::value,
Chris@16 211 boost::ratio_detail::br_mul<R2::num / gcd_n1_n2, R1::den / gcd_d1_d2>::value
Chris@16 212 >::value,
Chris@16 213 R2::den
Chris@16 214 >
Chris@16 215 >::type type;
Chris@16 216 };
Chris@16 217 template <class R, boost::intmax_t D>
Chris@16 218 struct ratio_add<R, ratio<0,D> >
Chris@16 219 {
Chris@16 220 typedef R type;
Chris@16 221 };
Chris@16 222
Chris@16 223 template <class R1, class R2>
Chris@16 224 struct ratio_subtract
Chris@16 225 {
Chris@16 226 //The nested typedef type shall be a synonym for ratio<T1, T2>::type where T1 has the value
Chris@16 227 // R1::num *R2::den - R2::num * R1::den and T2 has the value R1::den * R2::den.
Chris@16 228 // As the preceding doesn't works because of overflow on boost::intmax_t we need something more elaborated.
Chris@16 229 private:
Chris@16 230 static const boost::intmax_t gcd_n1_n2 = mpl::gcd_c<boost::intmax_t, R1::num, R2::num>::value;
Chris@16 231 static const boost::intmax_t gcd_d1_d2 = mpl::gcd_c<boost::intmax_t, R1::den, R2::den>::value;
Chris@16 232 public:
Chris@16 233 // No need to normalize as ratio_multiply is already normalized
Chris@16 234 typedef typename ratio_multiply
Chris@16 235 <
Chris@16 236 ratio<gcd_n1_n2, R1::den / gcd_d1_d2>,
Chris@16 237 ratio
Chris@16 238 <
Chris@16 239 boost::ratio_detail::br_sub
Chris@16 240 <
Chris@16 241 boost::ratio_detail::br_mul<R1::num / gcd_n1_n2, R2::den / gcd_d1_d2>::value,
Chris@16 242 boost::ratio_detail::br_mul<R2::num / gcd_n1_n2, R1::den / gcd_d1_d2>::value
Chris@16 243 >::value,
Chris@16 244 R2::den
Chris@16 245 >
Chris@16 246 >::type type;
Chris@16 247 };
Chris@16 248
Chris@16 249 template <class R, boost::intmax_t D>
Chris@16 250 struct ratio_subtract<R, ratio<0,D> >
Chris@16 251 {
Chris@16 252 typedef R type;
Chris@16 253 };
Chris@16 254
Chris@16 255 template <class R1, class R2>
Chris@16 256 struct ratio_multiply
Chris@16 257 {
Chris@16 258 // The nested typedef type shall be a synonym for ratio<R1::num * R2::den - R2::num * R1::den, R1::den * R2::den>::type.
Chris@16 259 // As the preceding doesn't works because of overflow on boost::intmax_t we need something more elaborated.
Chris@16 260 private:
Chris@16 261 static const boost::intmax_t gcd_n1_d2 = mpl::gcd_c<boost::intmax_t, R1::num, R2::den>::value;
Chris@16 262 static const boost::intmax_t gcd_d1_n2 = mpl::gcd_c<boost::intmax_t, R1::den, R2::num>::value;
Chris@16 263 public:
Chris@16 264 typedef typename ratio
Chris@16 265 <
Chris@16 266 boost::ratio_detail::br_mul<R1::num / gcd_n1_d2, R2::num / gcd_d1_n2>::value,
Chris@16 267 boost::ratio_detail::br_mul<R2::den / gcd_n1_d2, R1::den / gcd_d1_n2>::value
Chris@16 268 >::type type;
Chris@16 269 };
Chris@16 270
Chris@16 271 template <class R1, class R2>
Chris@16 272 struct ratio_divide
Chris@16 273 {
Chris@16 274 // The nested typedef type shall be a synonym for ratio<R1::num * R2::den, R2::num * R1::den>::type.
Chris@16 275 // As the preceding doesn't works because of overflow on boost::intmax_t we need something more elaborated.
Chris@16 276 private:
Chris@16 277 static const boost::intmax_t gcd_n1_n2 = mpl::gcd_c<boost::intmax_t, R1::num, R2::num>::value;
Chris@16 278 static const boost::intmax_t gcd_d1_d2 = mpl::gcd_c<boost::intmax_t, R1::den, R2::den>::value;
Chris@16 279 public:
Chris@16 280 typedef typename ratio
Chris@16 281 <
Chris@16 282 boost::ratio_detail::br_mul<R1::num / gcd_n1_n2, R2::den / gcd_d1_d2>::value,
Chris@16 283 boost::ratio_detail::br_mul<R2::num / gcd_n1_n2, R1::den / gcd_d1_d2>::value
Chris@16 284 >::type type;
Chris@16 285 };
Chris@16 286 template <class R1, class R2>
Chris@16 287 struct is_evenly_divisible_by
Chris@16 288 {
Chris@16 289 private:
Chris@16 290 static const boost::intmax_t gcd_n1_n2 = mpl::gcd_c<boost::intmax_t, R1::num, R2::num>::value;
Chris@16 291 static const boost::intmax_t gcd_d1_d2 = mpl::gcd_c<boost::intmax_t, R1::den, R2::den>::value;
Chris@16 292 public:
Chris@16 293 typedef integral_constant<bool,
Chris@16 294 ((R2::num / gcd_n1_n2 ==1) && (R1::den / gcd_d1_d2)==1)
Chris@16 295 > type;
Chris@16 296 };
Chris@16 297
Chris@16 298 template <class T>
Chris@16 299 struct is_ratio : public boost::false_type
Chris@16 300 {};
Chris@16 301 template <boost::intmax_t N, boost::intmax_t D>
Chris@16 302 struct is_ratio<ratio<N, D> > : public boost::true_type
Chris@16 303 {};
Chris@16 304
Chris@16 305 template <class R1, class R2,
Chris@16 306 boost::intmax_t Q1 = R1::num / R1::den, boost::intmax_t M1 = R1::num % R1::den,
Chris@16 307 boost::intmax_t Q2 = R2::num / R2::den, boost::intmax_t M2 = R2::num % R2::den>
Chris@16 308 struct ratio_less1
Chris@16 309 {
Chris@16 310 static const bool value = Q1 < Q2;
Chris@16 311 };
Chris@16 312
Chris@16 313 template <class R1, class R2, boost::intmax_t Q>
Chris@16 314 struct ratio_less1<R1, R2, Q, 0, Q, 0>
Chris@16 315 {
Chris@16 316 static const bool value = false;
Chris@16 317 };
Chris@16 318
Chris@16 319 template <class R1, class R2, boost::intmax_t Q, boost::intmax_t M2>
Chris@16 320 struct ratio_less1<R1, R2, Q, 0, Q, M2>
Chris@16 321 {
Chris@16 322 static const bool value = true;
Chris@16 323 };
Chris@16 324
Chris@16 325 template <class R1, class R2, boost::intmax_t Q, boost::intmax_t M1>
Chris@16 326 struct ratio_less1<R1, R2, Q, M1, Q, 0>
Chris@16 327 {
Chris@16 328 static const bool value = false;
Chris@16 329 };
Chris@16 330
Chris@16 331 template <class R1, class R2, boost::intmax_t Q, boost::intmax_t M1, boost::intmax_t M2>
Chris@16 332 struct ratio_less1<R1, R2, Q, M1, Q, M2>
Chris@16 333 {
Chris@16 334 static const bool value = ratio_less1<ratio<R2::den, M2>, ratio<R1::den, M1>
Chris@16 335 >::value;
Chris@16 336 };
Chris@16 337
Chris@16 338 template <
Chris@16 339 class R1,
Chris@16 340 class R2,
Chris@16 341 boost::intmax_t S1 = mpl::sign_c<boost::intmax_t, R1::num>::value,
Chris@16 342 boost::intmax_t S2 = mpl::sign_c<boost::intmax_t, R2::num>::value
Chris@16 343 >
Chris@16 344 struct ratio_less
Chris@16 345 {
Chris@16 346 static const bool value = S1 < S2;
Chris@16 347 };
Chris@16 348
Chris@16 349 template <class R1, class R2>
Chris@16 350 struct ratio_less<R1, R2, 1LL, 1LL>
Chris@16 351 {
Chris@16 352 static const bool value = ratio_less1<R1, R2>::value;
Chris@16 353 };
Chris@16 354
Chris@16 355 template <class R1, class R2>
Chris@16 356 struct ratio_less<R1, R2, -1LL, -1LL>
Chris@16 357 {
Chris@16 358 static const bool value = ratio_less1<ratio<-R2::num, R2::den>,
Chris@16 359 ratio<-R1::num, R1::den> >::value;
Chris@16 360 };
Chris@16 361
Chris@16 362
Chris@16 363 } // namespace ratio_detail
Chris@16 364
Chris@16 365 } // namespace boost
Chris@16 366
Chris@16 367 #endif // BOOST_RATIO_HPP