Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:48

0001 //  duration.hpp  --------------------------------------------------------------//
0002 
0003 //  Copyright 2008 Howard Hinnant
0004 //  Copyright 2008 Beman Dawes
0005 //  Copyright 2009-2011 Vicente J. Botet Escriba
0006 
0007 //  Distributed under the Boost Software License, Version 1.0.
0008 //  See http://www.boost.org/LICENSE_1_0.txt
0009 
0010 /*
0011 
0012 This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
0013 Many thanks to Howard for making his code available under the Boost license.
0014 The original code was modified to conform to Boost conventions and to section
0015 20.9 Time utilities [time] of the C++ committee's working paper N2798.
0016 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
0017 
0018 time2_demo contained this comment:
0019 
0020     Much thanks to Andrei Alexandrescu,
0021                    Walter Brown,
0022                    Peter Dimov,
0023                    Jeff Garland,
0024                    Terry Golubiewski,
0025                    Daniel Krugler,
0026                    Anthony Williams.
0027 */
0028 
0029 
0030 #ifndef BOOST_CHRONO_DURATION_HPP
0031 #define BOOST_CHRONO_DURATION_HPP
0032 
0033 #include <boost/chrono/config.hpp>
0034 #include <boost/chrono/detail/static_assert.hpp>
0035 
0036 #include <climits>
0037 #include <limits>
0038 
0039 
0040 #include <boost/mpl/logical.hpp>
0041 #include <boost/ratio/ratio.hpp>
0042 #include <boost/ratio/detail/is_ratio.hpp>
0043 #include <boost/type_traits/common_type.hpp>
0044 #include <boost/type_traits/is_arithmetic.hpp>
0045 #include <boost/type_traits/is_convertible.hpp>
0046 #include <boost/type_traits/is_floating_point.hpp>
0047 #include <boost/type_traits/is_unsigned.hpp>
0048 #include <boost/chrono/detail/is_evenly_divisible_by.hpp>
0049 
0050 #include <boost/cstdint.hpp>
0051 #include <boost/core/enable_if.hpp>
0052 #include <boost/detail/workaround.hpp>
0053 #include <boost/integer_traits.hpp>
0054 
0055 #if !defined(BOOST_NO_CXX11_STATIC_ASSERT) || !defined(BOOST_CHRONO_USES_MPL_ASSERT)
0056 #define BOOST_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION        "A duration representation can not be a duration"
0057 #define BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO "Second template parameter of duration must be a boost::ratio"
0058 #define BOOST_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE "duration period must be positive"
0059 #define BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_TIME_POINT_MUST_BE_A_BOOST_CHRONO_DURATION "Second template parameter of time_point must be a boost::chrono::duration"
0060 #endif
0061 
0062 #ifndef BOOST_CHRONO_HEADER_ONLY
0063 // this must occur after all of the includes and before any code appears:
0064 #include <boost/config/abi_prefix.hpp> // must be the last #include
0065 #endif
0066 
0067 //----------------------------------------------------------------------------//
0068 //                                                                            //
0069 //                        20.9 Time utilities [time]                          //
0070 //                                 synopsis                                   //
0071 //                                                                            //
0072 //----------------------------------------------------------------------------//
0073 
0074 namespace boost {
0075 namespace chrono {
0076 
0077     template <class Rep, class Period = ratio<1> >
0078     class duration;
0079 
0080     namespace detail
0081     {
0082     template <class T>
0083       struct is_duration
0084         : boost::false_type {};
0085 
0086     template <class Rep, class Period>
0087       struct is_duration<duration<Rep, Period> >
0088         : boost::true_type  {};
0089 
0090     template <class Duration, class Rep, bool = is_duration<Rep>::value>
0091     struct duration_divide_result
0092     {
0093     };
0094 
0095     template <class Duration, class Rep2,
0096         bool = (
0097                     ((boost::is_convertible<typename Duration::rep,
0098                         typename common_type<typename Duration::rep, Rep2>::type>::value))
0099                 &&  ((boost::is_convertible<Rep2,
0100                         typename common_type<typename Duration::rep, Rep2>::type>::value))
0101                 )
0102         >
0103     struct duration_divide_imp
0104     {
0105     };
0106 
0107     template <class Rep1, class Period, class Rep2>
0108     struct duration_divide_imp<duration<Rep1, Period>, Rep2, true>
0109     {
0110         typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
0111     };
0112 
0113     template <class Rep1, class Period, class Rep2>
0114     struct duration_divide_result<duration<Rep1, Period>, Rep2, false>
0115         : duration_divide_imp<duration<Rep1, Period>, Rep2>
0116     {
0117     };
0118 
0119 ///
0120     template <class Rep, class Duration, bool = is_duration<Rep>::value>
0121     struct duration_divide_result2
0122     {
0123     };
0124 
0125     template <class Rep, class Duration,
0126         bool = (
0127                     ((boost::is_convertible<typename Duration::rep,
0128                         typename common_type<typename Duration::rep, Rep>::type>::value))
0129                 &&  ((boost::is_convertible<Rep,
0130                         typename common_type<typename Duration::rep, Rep>::type>::value))
0131                 )
0132         >
0133     struct duration_divide_imp2
0134     {
0135     };
0136 
0137     template <class Rep1, class Rep2, class Period >
0138     struct duration_divide_imp2<Rep1, duration<Rep2, Period>, true>
0139     {
0140         //typedef typename common_type<Rep1, Rep2>::type type;
0141         typedef double type;
0142     };
0143 
0144     template <class Rep1, class Rep2, class Period >
0145     struct duration_divide_result2<Rep1, duration<Rep2, Period>, false>
0146         : duration_divide_imp2<Rep1, duration<Rep2, Period> >
0147     {
0148     };
0149 
0150 ///
0151     template <class Duration, class Rep, bool = is_duration<Rep>::value>
0152     struct duration_modulo_result
0153     {
0154     };
0155 
0156     template <class Duration, class Rep2,
0157         bool = (
0158                     //boost::is_convertible<typename Duration::rep,
0159                         //typename common_type<typename Duration::rep, Rep2>::type>::value
0160                 //&&
0161     boost::is_convertible<Rep2,
0162                         typename common_type<typename Duration::rep, Rep2>::type>::value
0163                 )
0164         >
0165     struct duration_modulo_imp
0166     {
0167     };
0168 
0169     template <class Rep1, class Period, class Rep2>
0170     struct duration_modulo_imp<duration<Rep1, Period>, Rep2, true>
0171     {
0172         typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
0173     };
0174 
0175     template <class Rep1, class Period, class Rep2>
0176     struct duration_modulo_result<duration<Rep1, Period>, Rep2, false>
0177         : duration_modulo_imp<duration<Rep1, Period>, Rep2>
0178     {
0179     };
0180 
0181 } // namespace detail
0182 } // namespace chrono
0183 
0184 
0185 // common_type trait specializations
0186 
0187 template <class Rep1, class Period1, class Rep2, class Period2>
0188 struct common_type<chrono::duration<Rep1, Period1>,
0189                      chrono::duration<Rep2, Period2> >;
0190 
0191 
0192 namespace chrono {
0193 
0194     // customization traits
0195     template <class Rep> struct treat_as_floating_point;
0196     template <class Rep> struct duration_values;
0197 
0198     // convenience typedefs
0199     typedef duration<boost::int_least64_t, nano> nanoseconds;    // at least 64 bits needed
0200     typedef duration<boost::int_least64_t, micro> microseconds;  // at least 55 bits needed
0201     typedef duration<boost::int_least64_t, milli> milliseconds;  // at least 45 bits needed
0202     typedef duration<boost::int_least64_t> seconds;              // at least 35 bits needed
0203     typedef duration<boost::int_least32_t, ratio< 60> > minutes; // at least 29 bits needed
0204     typedef duration<boost::int_least32_t, ratio<3600> > hours;  // at least 23 bits needed
0205 
0206 //----------------------------------------------------------------------------//
0207 //                          duration helpers                                  //
0208 //----------------------------------------------------------------------------//
0209 
0210 namespace detail
0211 {
0212 
0213     // duration_cast
0214 
0215     // duration_cast is the heart of this whole prototype.  It can convert any
0216     //   duration to any other.  It is also (implicitly) used in converting
0217     //   time_points.  The conversion is always exact if possible.  And it is
0218     //   always as efficient as hand written code.  If different representations
0219     //   are involved, care is taken to never require implicit conversions.
0220     //   Instead static_cast is used explicitly for every required conversion.
0221     //   If there are a mixture of integral and floating point representations,
0222     //   the use of common_type ensures that the most logical "intermediate"
0223     //   representation is used.
0224     template <class FromDuration, class ToDuration,
0225               class Period,
0226               bool PeriodNumEq1,
0227               bool PeriodDenEq1>
0228     struct duration_cast_aux;
0229 
0230     // When the two periods are the same, all that is left to do is static_cast from
0231     //   the source representation to the target representation (which may be a no-op).
0232     //   This conversion is always exact as long as the static_cast from the source
0233     //   representation to the destination representation is exact.
0234     template <class FromDuration, class ToDuration, class Period>
0235     struct duration_cast_aux<FromDuration, ToDuration, Period, true, true>
0236     {
0237         BOOST_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
0238         {
0239             return ToDuration(static_cast<typename ToDuration::rep>(fd.count()));
0240         }
0241     };
0242 
0243     // When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is
0244     //   divide by the denominator of FromPeriod / ToPeriod.  The common_type of
0245     //   the two representations is used for the intermediate computation before
0246     //   static_cast'ing to the destination.
0247     //   This conversion is generally not exact because of the division (but could be
0248     //   if you get lucky on the run time value of fd.count()).
0249     template <class FromDuration, class ToDuration, class Period>
0250     struct duration_cast_aux<FromDuration, ToDuration, Period, true, false>
0251     {
0252         BOOST_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
0253         {
0254             typedef typename common_type<
0255                 typename ToDuration::rep,
0256                 typename FromDuration::rep,
0257                 boost::intmax_t>::type C;
0258             return ToDuration(static_cast<typename ToDuration::rep>(
0259                               static_cast<C>(fd.count()) / static_cast<C>(Period::den)));
0260         }
0261     };
0262 
0263     // When the denominator of FromPeriod / ToPeriod is 1, then all we need to do is
0264     //   multiply by the numerator of FromPeriod / ToPeriod.  The common_type of
0265     //   the two representations is used for the intermediate computation before
0266     //   static_cast'ing to the destination.
0267     //   This conversion is always exact as long as the static_cast's involved are exact.
0268     template <class FromDuration, class ToDuration, class Period>
0269     struct duration_cast_aux<FromDuration, ToDuration, Period, false, true>
0270     {
0271         BOOST_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
0272         {
0273             typedef typename common_type<
0274               typename ToDuration::rep,
0275               typename FromDuration::rep,
0276               boost::intmax_t>::type C;
0277             return ToDuration(static_cast<typename ToDuration::rep>(
0278                               static_cast<C>(fd.count()) * static_cast<C>(Period::num)));
0279         }
0280     };
0281 
0282     // When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to
0283     //   multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod.  The
0284     //   common_type of the two representations is used for the intermediate computation before
0285     //   static_cast'ing to the destination.
0286     //   This conversion is generally not exact because of the division (but could be
0287     //   if you get lucky on the run time value of fd.count()).
0288     template <class FromDuration, class ToDuration, class Period>
0289     struct duration_cast_aux<FromDuration, ToDuration, Period, false, false>
0290     {
0291         BOOST_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
0292         {
0293             typedef typename common_type<
0294               typename ToDuration::rep,
0295               typename FromDuration::rep,
0296               boost::intmax_t>::type C;
0297             return ToDuration(static_cast<typename ToDuration::rep>(
0298                static_cast<C>(fd.count()) * static_cast<C>(Period::num)
0299                  / static_cast<C>(Period::den)));
0300         }
0301     };
0302 
0303     template <class FromDuration, class ToDuration>
0304     struct duration_cast {
0305         typedef typename ratio_divide<typename FromDuration::period,
0306               typename ToDuration::period>::type Period;
0307         typedef duration_cast_aux<
0308             FromDuration,
0309             ToDuration,
0310             Period,
0311             Period::num == 1,
0312             Period::den == 1
0313         > Aux;
0314         BOOST_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
0315         {
0316             return Aux()(fd);
0317         }
0318     };
0319 
0320 } // namespace detail
0321 
0322 //----------------------------------------------------------------------------//
0323 //                                                                            //
0324 //      20.9.2 Time-related traits [time.traits]                              //
0325 //                                                                            //
0326 //----------------------------------------------------------------------------//
0327 //----------------------------------------------------------------------------//
0328 //      20.9.2.1 treat_as_floating_point [time.traits.is_fp]                  //
0329 //      Probably should have been treat_as_floating_point. Editor notified.   //
0330 //----------------------------------------------------------------------------//
0331 
0332     // Support bidirectional (non-exact) conversions for floating point rep types
0333     //   (or user defined rep types which specialize treat_as_floating_point).
0334     template <class Rep>
0335     struct treat_as_floating_point : boost::is_floating_point<Rep> {};
0336 
0337 //----------------------------------------------------------------------------//
0338 //      20.9.2.2 duration_values [time.traits.duration_values]                //
0339 //----------------------------------------------------------------------------//
0340 
0341 namespace detail {
0342     template <class T, bool = is_arithmetic<T>::value>
0343     struct chrono_numeric_limits {
0344         static BOOST_CHRONO_LIB_CONSTEXPR T lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW {return (std::numeric_limits<T>::min)  ();}
0345     };
0346 
0347     template <class T>
0348     struct chrono_numeric_limits<T,true> {
0349         static BOOST_CHRONO_LIB_CONSTEXPR T lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW {return (std::numeric_limits<T>::min)  ();}
0350     };
0351 
0352     template <>
0353     struct chrono_numeric_limits<float,true> {
0354         static BOOST_CHRONO_LIB_CONSTEXPR float lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW
0355         {
0356             return -(std::numeric_limits<float>::max) ();
0357         }
0358     };
0359 
0360     template <>
0361     struct chrono_numeric_limits<double,true> {
0362         static BOOST_CHRONO_LIB_CONSTEXPR double lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW
0363         {
0364             return -(std::numeric_limits<double>::max) ();
0365         }
0366     };
0367 
0368     template <>
0369     struct chrono_numeric_limits<long double,true> {
0370         static BOOST_CHRONO_LIB_CONSTEXPR long double lowest() BOOST_CHRONO_LIB_NOEXCEPT_OR_THROW
0371         {
0372             return -(std::numeric_limits<long double>::max)();
0373         }
0374     };
0375 
0376     template <class T>
0377     struct numeric_limits : chrono_numeric_limits<typename remove_cv<T>::type>
0378     {};
0379 
0380 }
0381 template <class Rep>
0382 struct duration_values
0383 {
0384     static BOOST_CONSTEXPR Rep zero() {return Rep(0);}
0385     static BOOST_CHRONO_LIB_CONSTEXPR Rep max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0386     {
0387         return (std::numeric_limits<Rep>::max)();
0388     }
0389 
0390     static BOOST_CHRONO_LIB_CONSTEXPR Rep min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0391     {
0392         return detail::numeric_limits<Rep>::lowest();
0393     }
0394 };
0395 
0396 }  // namespace chrono
0397 
0398 //----------------------------------------------------------------------------//
0399 //      20.9.2.3 Specializations of common_type [time.traits.specializations] //
0400 //----------------------------------------------------------------------------//
0401 
0402 template <class Rep1, class Period1, class Rep2, class Period2>
0403 struct common_type<chrono::duration<Rep1, Period1>,
0404                    chrono::duration<Rep2, Period2> >
0405 {
0406   typedef chrono::duration<typename common_type<Rep1, Rep2>::type,
0407                       typename boost::ratio_gcd<Period1, Period2>::type> type;
0408 };
0409 
0410 
0411 //----------------------------------------------------------------------------//
0412 //                                                                            //
0413 //         20.9.3 Class template duration [time.duration]                     //
0414 //                                                                            //
0415 //----------------------------------------------------------------------------//
0416 
0417 
0418 namespace chrono {
0419 
0420     template <class Rep, class Period>
0421     class BOOST_SYMBOL_VISIBLE duration
0422     {
0423     //BOOST_CHRONO_STATIC_ASSERT(boost::is_integral<Rep>::value, BOOST_CHRONO_A_DURATION_REPRESENTATION_MUST_BE_INTEGRAL, ());
0424     BOOST_CHRONO_STATIC_ASSERT(!boost::chrono::detail::is_duration<Rep>::value,
0425             BOOST_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION, ());
0426     BOOST_CHRONO_STATIC_ASSERT(boost::ratio_detail::is_ratio<typename Period::type>::value,
0427             BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO, ());
0428     BOOST_CHRONO_STATIC_ASSERT(Period::num>0,
0429             BOOST_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE, ());
0430     public:
0431         typedef Rep rep;
0432         typedef Period period;
0433     private:
0434         rep rep_;
0435     public:
0436 
0437 #if  defined   BOOST_CHRONO_DURATION_DEFAULTS_TO_ZERO
0438         BOOST_FORCEINLINE BOOST_CONSTEXPR
0439         duration() : rep_(duration_values<rep>::zero()) { }
0440 #elif  defined   BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
0441         BOOST_CONSTEXPR duration() {}
0442 #else
0443         BOOST_CONSTEXPR duration()  = default;
0444 #endif
0445         template <class Rep2>
0446         BOOST_SYMBOL_VISIBLE BOOST_FORCEINLINE BOOST_CONSTEXPR
0447         explicit duration(const Rep2& r
0448         , typename boost::enable_if <
0449                     mpl::and_ <
0450                         boost::is_convertible<Rep2, rep>,
0451                         mpl::or_ <
0452                             treat_as_floating_point<rep>,
0453                             mpl::and_ <
0454                                 mpl::not_ < treat_as_floating_point<rep> >,
0455                                 mpl::not_ < treat_as_floating_point<Rep2> >
0456                             >
0457                         >
0458                     >
0459                 >::type* = BOOST_NULLPTR
0460             ) : rep_(r) { }
0461 #if  defined   BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
0462         duration& operator=(const duration& rhs)
0463         {
0464             if (&rhs != this) rep_= rhs.rep_;
0465             return *this;
0466         }
0467         duration(const duration& rhs) : rep_(rhs.rep_) {}
0468 #else
0469         duration& operator=(const duration& rhs) = default;
0470         duration(const duration&) = default;
0471 #endif
0472 
0473         // conversions
0474         template <class Rep2, class Period2>
0475         BOOST_FORCEINLINE BOOST_CONSTEXPR
0476         duration(const duration<Rep2, Period2>& d
0477         , typename boost::enable_if <
0478                     mpl::or_ <
0479                         treat_as_floating_point<rep>,
0480                         mpl::and_ <
0481                             chrono_detail::is_evenly_divisible_by<Period2, period>,
0482                             mpl::not_ < treat_as_floating_point<Rep2> >
0483                         >
0484                     >
0485                 >::type* = BOOST_NULLPTR
0486         )
0487             : rep_(chrono::detail::duration_cast<duration<Rep2, Period2>, duration>()(d).count()) {}
0488 
0489         // observer
0490 
0491         BOOST_CONSTEXPR
0492         rep count() const {return rep_;}
0493 
0494         // arithmetic
0495 
0496         BOOST_CONSTEXPR
0497         duration  operator+() const {return duration(rep_);}
0498         BOOST_CONSTEXPR
0499         duration  operator-() const {return duration(-rep_);}
0500         duration& operator++()      {++rep_; return *this;}
0501         duration  operator++(int)   {return duration(rep_++);}
0502         duration& operator--()      {--rep_; return *this;}
0503         duration  operator--(int)   {return duration(rep_--);}
0504 
0505         duration& operator+=(const duration& d)
0506         {
0507             rep_ += d.count(); return *this;
0508         }
0509         duration& operator-=(const duration& d)
0510         {
0511             rep_ -= d.count(); return *this;
0512         }
0513 
0514         duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;}
0515         duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;}
0516         duration& operator%=(const rep& rhs) {rep_ %= rhs; return *this;}
0517         duration& operator%=(const duration& rhs)
0518         {
0519             rep_ %= rhs.count(); return *this;
0520         }
0521         // 20.9.3.4 duration special values [time.duration.special]
0522 
0523         static BOOST_CONSTEXPR duration zero()
0524         {
0525             return duration(duration_values<rep>::zero());
0526         }
0527         static BOOST_CHRONO_LIB_CONSTEXPR duration min BOOST_PREVENT_MACRO_SUBSTITUTION ()
0528         {
0529             return duration((duration_values<rep>::min)());
0530         }
0531         static BOOST_CHRONO_LIB_CONSTEXPR duration max BOOST_PREVENT_MACRO_SUBSTITUTION ()
0532         {
0533             return duration((duration_values<rep>::max)());
0534         }
0535     };
0536 
0537 //----------------------------------------------------------------------------//
0538 //      20.9.3.5 duration non-member arithmetic [time.duration.nonmember]     //
0539 //----------------------------------------------------------------------------//
0540 
0541     // Duration +
0542 
0543     template <class Rep1, class Period1, class Rep2, class Period2>
0544     inline BOOST_CONSTEXPR
0545     typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
0546     operator+(const duration<Rep1, Period1>& lhs,
0547           const duration<Rep2, Period2>& rhs)
0548     {
0549       typedef typename common_type<duration<Rep1, Period1>,
0550         duration<Rep2, Period2> >::type common_duration;
0551       return common_duration(common_duration(lhs).count()+common_duration(rhs).count());
0552     }
0553 
0554     // Duration -
0555 
0556     template <class Rep1, class Period1, class Rep2, class Period2>
0557     inline BOOST_CONSTEXPR
0558     typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
0559     operator-(const duration<Rep1, Period1>& lhs,
0560           const duration<Rep2, Period2>& rhs)
0561     {
0562       typedef typename common_type<duration<Rep1, Period1>,
0563             duration<Rep2, Period2> >::type common_duration;
0564       return common_duration(common_duration(lhs).count()-common_duration(rhs).count());
0565     }
0566 
0567     // Duration *
0568 
0569     template <class Rep1, class Period, class Rep2>
0570     inline BOOST_CONSTEXPR
0571     typename boost::enable_if <
0572         mpl::and_ <
0573         boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
0574         boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
0575         >,
0576         duration<typename common_type<Rep1, Rep2>::type, Period>
0577     >::type
0578     operator*(const duration<Rep1, Period>& d, const Rep2& s)
0579     {
0580       typedef typename common_type<Rep1, Rep2>::type common_rep;
0581       typedef duration<common_rep, Period> common_duration;
0582       return common_duration(common_duration(d).count()*static_cast<common_rep>(s));
0583     }
0584 
0585     template <class Rep1, class Period, class Rep2>
0586     inline BOOST_CONSTEXPR
0587     typename boost::enable_if <
0588         mpl::and_ <
0589         boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
0590         boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
0591         >,
0592         duration<typename common_type<Rep1, Rep2>::type, Period>
0593     >::type
0594     operator*(const Rep1& s, const duration<Rep2, Period>& d)
0595     {
0596         return d * s;
0597     }
0598 
0599     // Duration /
0600 
0601     template <class Rep1, class Period, class Rep2>
0602     inline BOOST_CONSTEXPR
0603     typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>,
0604       typename boost::chrono::detail::duration_divide_result<
0605         duration<Rep1, Period>, Rep2>::type
0606     >::type
0607     operator/(const duration<Rep1, Period>& d, const Rep2& s)
0608     {
0609       typedef typename common_type<Rep1, Rep2>::type common_rep;
0610       typedef duration<common_rep, Period> common_duration;
0611       return common_duration(common_duration(d).count()/static_cast<common_rep>(s));
0612     }
0613 
0614     template <class Rep1, class Period1, class Rep2, class Period2>
0615     inline BOOST_CONSTEXPR
0616     typename common_type<Rep1, Rep2>::type
0617     operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
0618     {
0619         typedef typename common_type<duration<Rep1, Period1>,
0620                                    duration<Rep2, Period2> >::type common_duration;
0621         return common_duration(lhs).count() / common_duration(rhs).count();
0622     }
0623 
0624     #ifdef BOOST_CHRONO_EXTENSIONS
0625     template <class Rep1, class Rep2, class Period>
0626     inline BOOST_CONSTEXPR
0627     typename boost::disable_if <boost::chrono::detail::is_duration<Rep1>,
0628       typename boost::chrono::detail::duration_divide_result2<
0629         Rep1, duration<Rep2, Period> >::type
0630       >::type
0631     operator/(const Rep1& s, const duration<Rep2, Period>& d)
0632     {
0633       typedef typename common_type<Rep1, Rep2>::type common_rep;
0634       typedef duration<common_rep, Period> common_duration;
0635       return static_cast<common_rep>(s)/common_duration(d).count();
0636     }
0637     #endif
0638     // Duration %
0639 
0640     template <class Rep1, class Period, class Rep2>
0641     inline BOOST_CONSTEXPR
0642     typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>,
0643       typename boost::chrono::detail::duration_modulo_result<
0644         duration<Rep1, Period>, Rep2>::type
0645     >::type
0646     operator%(const duration<Rep1, Period>& d, const Rep2& s)
0647     {
0648       typedef typename common_type<Rep1, Rep2>::type common_rep;
0649       typedef duration<common_rep, Period> common_duration;
0650       return common_duration(common_duration(d).count()%static_cast<common_rep>(s));
0651     }
0652 
0653     template <class Rep1, class Period1, class Rep2, class Period2>
0654     inline BOOST_CONSTEXPR
0655     typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
0656     operator%(const duration<Rep1, Period1>& lhs,
0657           const duration<Rep2, Period2>& rhs) {
0658         typedef typename common_type<duration<Rep1, Period1>,
0659                                  duration<Rep2, Period2> >::type common_duration;
0660 
0661       return common_duration(common_duration(lhs).count()%common_duration(rhs).count());
0662     }
0663 
0664 
0665 //----------------------------------------------------------------------------//
0666 //      20.9.3.6 duration comparisons [time.duration.comparisons]             //
0667 //----------------------------------------------------------------------------//
0668 
0669 namespace detail
0670 {
0671     template <class LhsDuration, class RhsDuration>
0672     struct duration_eq
0673     {
0674       BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const
0675         {
0676             typedef typename common_type<LhsDuration, RhsDuration>::type common_duration;
0677             return common_duration(lhs).count() == common_duration(rhs).count();
0678         }
0679     };
0680 
0681     template <class LhsDuration>
0682     struct duration_eq<LhsDuration, LhsDuration>
0683     {
0684       BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) const
0685         {
0686             return lhs.count() == rhs.count();
0687         }
0688     };
0689 
0690     template <class LhsDuration, class RhsDuration>
0691     struct duration_lt
0692     {
0693       BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const RhsDuration& rhs) const
0694         {
0695             typedef typename common_type<LhsDuration, RhsDuration>::type common_duration;
0696             return common_duration(lhs).count() < common_duration(rhs).count();
0697         }
0698     };
0699 
0700     template <class LhsDuration>
0701     struct duration_lt<LhsDuration, LhsDuration>
0702     {
0703       BOOST_CONSTEXPR bool operator()(const LhsDuration& lhs, const LhsDuration& rhs) const
0704         {
0705             return lhs.count() < rhs.count();
0706         }
0707     };
0708 
0709 } // namespace detail
0710 
0711     // Duration ==
0712 
0713     template <class Rep1, class Period1, class Rep2, class Period2>
0714     inline BOOST_CONSTEXPR
0715     bool
0716     operator==(const duration<Rep1, Period1>& lhs,
0717           const duration<Rep2, Period2>& rhs)
0718     {
0719         return boost::chrono::detail::duration_eq<
0720             duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
0721     }
0722 
0723     // Duration !=
0724 
0725     template <class Rep1, class Period1, class Rep2, class Period2>
0726     inline BOOST_CONSTEXPR
0727     bool
0728     operator!=(const duration<Rep1, Period1>& lhs,
0729           const duration<Rep2, Period2>& rhs)
0730     {
0731         return !(lhs == rhs);
0732     }
0733 
0734     // Duration <
0735 
0736     template <class Rep1, class Period1, class Rep2, class Period2>
0737     inline BOOST_CONSTEXPR
0738     bool
0739     operator< (const duration<Rep1, Period1>& lhs,
0740           const duration<Rep2, Period2>& rhs)
0741     {
0742         return boost::chrono::detail::duration_lt<
0743           duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
0744     }
0745 
0746     // Duration >
0747 
0748     template <class Rep1, class Period1, class Rep2, class Period2>
0749     inline BOOST_CONSTEXPR
0750     bool
0751     operator> (const duration<Rep1, Period1>& lhs,
0752           const duration<Rep2, Period2>& rhs)
0753     {
0754         return rhs < lhs;
0755     }
0756 
0757     // Duration <=
0758 
0759     template <class Rep1, class Period1, class Rep2, class Period2>
0760     inline BOOST_CONSTEXPR
0761     bool
0762     operator<=(const duration<Rep1, Period1>& lhs,
0763           const duration<Rep2, Period2>& rhs)
0764     {
0765         return !(rhs < lhs);
0766     }
0767 
0768     // Duration >=
0769 
0770     template <class Rep1, class Period1, class Rep2, class Period2>
0771     inline BOOST_CONSTEXPR
0772     bool
0773     operator>=(const duration<Rep1, Period1>& lhs,
0774           const duration<Rep2, Period2>& rhs)
0775     {
0776         return !(lhs < rhs);
0777     }
0778 
0779 //----------------------------------------------------------------------------//
0780 //      20.9.3.7 duration_cast [time.duration.cast]                           //
0781 //----------------------------------------------------------------------------//
0782 
0783     // Compile-time select the most efficient algorithm for the conversion...
0784     template <class ToDuration, class Rep, class Period>
0785     inline BOOST_CONSTEXPR
0786     typename boost::enable_if <
0787       boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type
0788     duration_cast(const duration<Rep, Period>& fd)
0789     {
0790         return boost::chrono::detail::duration_cast<
0791           duration<Rep, Period>, ToDuration>()(fd);
0792     }
0793 
0794 } // namespace chrono
0795 } // namespace boost
0796 
0797 #ifndef BOOST_CHRONO_HEADER_ONLY
0798 // the suffix header occurs after all of our code:
0799 #include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas
0800 #endif
0801 
0802 #endif // BOOST_CHRONO_DURATION_HPP