1 //  duration.hpp  --------------------------------------------------------------//
2 
3 //  Copyright 2008 Howard Hinnant
4 //  Copyright 2008 Beman Dawes
5 //  Copyright 2009-2010 Vicente J. Botet Escriba
6 
7 //  Distributed under the Boost Software License, Version 1.0.
8 //  See http://www.boost.org/LICENSE_1_0.txt
9 
10 /*
11 
12 This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
13 Many thanks to Howard for making his code available under the Boost license.
14 The original code was modified to conform to Boost conventions and to section
15 20.9 Time utilities [time] of the C++ committee's working paper N2798.
16 See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
17 
18 time2_demo contained this comment:
19 
20     Much thanks to Andrei Alexandrescu,
21                    Walter Brown,
22                    Peter Dimov,
23                    Jeff Garland,
24                    Terry Golubiewski,
25                    Daniel Krugler,
26                    Anthony Williams.
27 */
28 
29 
30 #ifndef BOOST_CHRONO_DURATION_HPP
31 #define BOOST_CHRONO_DURATION_HPP
32 
33 #include <boost/chrono/config.hpp>
34 #include <boost/chrono/detail/static_assert.hpp>
35 
36 #include <climits>
37 #include <limits>
38 
39 
40 #include <boost/mpl/logical.hpp>
41 #include <boost/ratio/ratio.hpp>
42 #include <boost/type_traits/common_type.hpp>
43 #include <boost/type_traits/is_arithmetic.hpp>
44 #include <boost/type_traits/is_convertible.hpp>
45 #include <boost/type_traits/is_floating_point.hpp>
46 #include <boost/type_traits/is_unsigned.hpp>
47 #include <boost/chrono/detail/is_evenly_divisible_by.hpp>
48 
49 #include <boost/cstdint.hpp>
50 #include <boost/utility/enable_if.hpp>
51 #include <boost/detail/workaround.hpp>
52 #include <boost/integer_traits.hpp>
53 
54 #if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_CHRONO_USES_MPL_ASSERT)
55 #define BOOST_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION        "A duration representation can not be a duration"
56 #define BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO "Second template parameter of duration must be a boost::ratio"
57 #define BOOST_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE "duration period must be positive"
58 #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"
59 #endif
60 
61 
62 //----------------------------------------------------------------------------//
63 //                                                                            //
64 //                        20.9 Time utilities [time]                          //
65 //                                 synopsis                                   //
66 //                                                                            //
67 //----------------------------------------------------------------------------//
68 
69 namespace boost {
70 namespace chrono {
71 
72     template <class Rep, class Period = ratio<1> >
73     class duration;
74 
75     namespace detail
76     {
77     template <class T>
78       struct is_duration
79         : boost::false_type {};
80 
81     template <class Rep, class Period>
82       struct is_duration<duration<Rep, Period> >
83         : boost::true_type  {};
84 
85     template <class Duration, class Rep, bool = is_duration<Rep>::value>
86     struct duration_divide_result
87     {
88     };
89 
90     template <class Duration, class Rep2,
91         bool = (
92                     ((boost::is_convertible<typename Duration::rep,
93                         typename common_type<typename Duration::rep, Rep2>::type>::value))
94                 &&  ((boost::is_convertible<Rep2,
95                         typename common_type<typename Duration::rep, Rep2>::type>::value))
96                 )
97         >
98     struct duration_divide_imp
99     {
100     };
101 
102     template <class Rep1, class Period, class Rep2>
103     struct duration_divide_imp<duration<Rep1, Period>, Rep2, true>
104     {
105         typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
106     };
107 
108     template <class Rep1, class Period, class Rep2>
109     struct duration_divide_result<duration<Rep1, Period>, Rep2, false>
110         : duration_divide_imp<duration<Rep1, Period>, Rep2>
111     {
112     };
113 
114 ///
115     template <class Rep, class Duration, bool = is_duration<Rep>::value>
116     struct duration_divide_result2
117     {
118     };
119 
120     template <class Rep, class Duration,
121         bool = (
122                     ((boost::is_convertible<typename Duration::rep,
123                         typename common_type<typename Duration::rep, Rep>::type>::value))
124                 &&  ((boost::is_convertible<Rep,
125                         typename common_type<typename Duration::rep, Rep>::type>::value))
126                 )
127         >
128     struct duration_divide_imp2
129     {
130     };
131 
132     template <class Rep1, class Rep2, class Period >
133     struct duration_divide_imp2<Rep1, duration<Rep2, Period>, true>
134     {
135         //typedef typename common_type<Rep1, Rep2>::type type;
136         typedef double type;
137     };
138 
139     template <class Rep1, class Rep2, class Period >
140     struct duration_divide_result2<Rep1, duration<Rep2, Period>, false>
141         : duration_divide_imp2<Rep1, duration<Rep2, Period> >
142     {
143     };
144 
145 ///
146     template <class Duration, class Rep, bool = is_duration<Rep>::value>
147     struct duration_modulo_result
148     {
149     };
150 
151     template <class Duration, class Rep2,
152         bool = (
153                     //boost::is_convertible<typename Duration::rep,
154                         //typename common_type<typename Duration::rep, Rep2>::type>::value
155                 //&&
156     boost::is_convertible<Rep2,
157                         typename common_type<typename Duration::rep, Rep2>::type>::value
158                 )
159         >
160     struct duration_modulo_imp
161     {
162     };
163 
164     template <class Rep1, class Period, class Rep2>
165     struct duration_modulo_imp<duration<Rep1, Period>, Rep2, true>
166     {
167         typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
168     };
169 
170     template <class Rep1, class Period, class Rep2>
171     struct duration_modulo_result<duration<Rep1, Period>, Rep2, false>
172         : duration_modulo_imp<duration<Rep1, Period>, Rep2>
173     {
174     };
175 
176 } // namespace detail
177 } // namespace chrono
178 
179 
180 // common_type trait specializations
181 
182 template <class Rep1, class Period1, class Rep2, class Period2>
183 struct common_type<chrono::duration<Rep1, Period1>,
184                      chrono::duration<Rep2, Period2> >;
185 
186 
187 namespace chrono {
188 
189     // customization traits
190     template <class Rep> struct treat_as_floating_point;
191     template <class Rep> struct duration_values;
192 
193     // convenience typedefs
194     typedef duration<boost::int_least64_t, nano> nanoseconds;    // at least 64 bits needed
195     typedef duration<boost::int_least64_t, micro> microseconds;  // at least 55 bits needed
196     typedef duration<boost::int_least64_t, milli> milliseconds;  // at least 45 bits needed
197     typedef duration<boost::int_least64_t> seconds;              // at least 35 bits needed
198     typedef duration<boost::int_least32_t, ratio< 60> > minutes; // at least 29 bits needed
199     typedef duration<boost::int_least32_t, ratio<3600> > hours;  // at least 23 bits needed
200 
201 //----------------------------------------------------------------------------//
202 //                          duration helpers                                  //
203 //----------------------------------------------------------------------------//
204 
205 namespace detail
206 {
207 
208     // duration_cast
209 
210     // duration_cast is the heart of this whole prototype.  It can convert any
211     //   duration to any other.  It is also (implicitly) used in converting
212     //   time_points.  The conversion is always exact if possible.  And it is
213     //   always as efficient as hand written code.  If different representations
214     //   are involved, care is taken to never require implicit conversions.
215     //   Instead static_cast is used explicitly for every required conversion.
216     //   If there are a mixture of integral and floating point representations,
217     //   the use of common_type ensures that the most logical "intermediate"
218     //   representation is used.
219     template <class FromDuration, class ToDuration,
220               class Period,
221               bool PeriodNumEq1,
222               bool PeriodDenEq1>
223     struct duration_cast_aux;
224 
225     // When the two periods are the same, all that is left to do is static_cast from
226     //   the source representation to the target representation (which may be a no-op).
227     //   This conversion is always exact as long as the static_cast from the source
228     //   representation to the destination representation is exact.
229     template <class FromDuration, class ToDuration, class Period>
230     struct duration_cast_aux<FromDuration, ToDuration, Period, true, true>
231     {
operator ()boost::chrono::detail::duration_cast_aux232         BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
233         {
234             return ToDuration(static_cast<typename ToDuration::rep>(fd.count()));
235         }
236     };
237 
238     // When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is
239     //   divide by the denominator of FromPeriod / ToPeriod.  The common_type of
240     //   the two representations is used for the intermediate computation before
241     //   static_cast'ing to the destination.
242     //   This conversion is generally not exact because of the division (but could be
243     //   if you get lucky on the run time value of fd.count()).
244     template <class FromDuration, class ToDuration, class Period>
245     struct duration_cast_aux<FromDuration, ToDuration, Period, true, false>
246     {
operator ()boost::chrono::detail::duration_cast_aux247         BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
248         {
249             typedef typename common_type<
250                 typename ToDuration::rep,
251                 typename FromDuration::rep,
252                 boost::intmax_t>::type C;
253             return ToDuration(static_cast<typename ToDuration::rep>(
254                               static_cast<C>(fd.count()) / static_cast<C>(Period::den)));
255         }
256     };
257 
258     // When the denomenator of FromPeriod / ToPeriod is 1, then all we need to do is
259     //   multiply by the numerator of FromPeriod / ToPeriod.  The common_type of
260     //   the two representations is used for the intermediate computation before
261     //   static_cast'ing to the destination.
262     //   This conversion is always exact as long as the static_cast's involved are exact.
263     template <class FromDuration, class ToDuration, class Period>
264     struct duration_cast_aux<FromDuration, ToDuration, Period, false, true>
265     {
operator ()boost::chrono::detail::duration_cast_aux266         BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
267         {
268             typedef typename common_type<
269               typename ToDuration::rep,
270               typename FromDuration::rep,
271               boost::intmax_t>::type C;
272             return ToDuration(static_cast<typename ToDuration::rep>(
273                               static_cast<C>(fd.count()) * static_cast<C>(Period::num)));
274         }
275     };
276 
277     // When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to
278     //   multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod.  The
279     //   common_type of the two representations is used for the intermediate computation before
280     //   static_cast'ing to the destination.
281     //   This conversion is generally not exact because of the division (but could be
282     //   if you get lucky on the run time value of fd.count()).
283     template <class FromDuration, class ToDuration, class Period>
284     struct duration_cast_aux<FromDuration, ToDuration, Period, false, false>
285     {
operator ()boost::chrono::detail::duration_cast_aux286         BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
287         {
288             typedef typename common_type<
289               typename ToDuration::rep,
290               typename FromDuration::rep,
291               boost::intmax_t>::type C;
292             return ToDuration(static_cast<typename ToDuration::rep>(
293                static_cast<C>(fd.count()) * static_cast<C>(Period::num)
294                  / static_cast<C>(Period::den)));
295         }
296     };
297 
298     template <class FromDuration, class ToDuration>
299     struct duration_cast {
300         typedef typename ratio_divide<typename FromDuration::period,
301               typename ToDuration::period>::type Period;
302         typedef duration_cast_aux<
303             FromDuration,
304             ToDuration,
305             Period,
306             Period::num == 1,
307             Period::den == 1
308         > Aux;
operator ()boost::chrono::detail::duration_cast309         BOOST_CHRONO_CONSTEXPR ToDuration operator()(const FromDuration& fd) const
310         {
311             return Aux()(fd);
312         }
313     };
314 
315 } // namespace detail
316 
317 //----------------------------------------------------------------------------//
318 //                                                                            //
319 //      20.9.2 Time-related traits [time.traits]                              //
320 //                                                                            //
321 //----------------------------------------------------------------------------//
322 //----------------------------------------------------------------------------//
323 //      20.9.2.1 treat_as_floating_point [time.traits.is_fp]                        //
324 //      Probably should have been treat_as_floating_point. Editor notifed.    //
325 //----------------------------------------------------------------------------//
326 
327     // Support bidirectional (non-exact) conversions for floating point rep types
328     //   (or user defined rep types which specialize treat_as_floating_point).
329     template <class Rep>
330     struct treat_as_floating_point : boost::is_floating_point<Rep> {};
331 
332 //----------------------------------------------------------------------------//
333 //      20.9.2.2 duration_values [time.traits.duration_values]                //
334 //----------------------------------------------------------------------------//
335 
336 namespace detail {
337     template <class T, bool = is_arithmetic<T>::value>
338     struct chrono_numeric_limits {
lowestboost::chrono::detail::chrono_numeric_limits339         static T lowest() throw() {return (std::numeric_limits<T>::min)  ();}
340     };
341 
342     template <class T>
343     struct chrono_numeric_limits<T,true> {
lowestboost::chrono::detail::chrono_numeric_limits344         static T lowest() throw() {return (std::numeric_limits<T>::min)  ();}
345     };
346 
347     template <>
348     struct chrono_numeric_limits<float,true> {
lowestboost::chrono::detail::chrono_numeric_limits349         static float lowest() throw()
350         {
351             return -(std::numeric_limits<float>::max) ();
352         }
353     };
354 
355     template <>
356     struct chrono_numeric_limits<double,true> {
lowestboost::chrono::detail::chrono_numeric_limits357         static double lowest() throw()
358         {
359             return -(std::numeric_limits<double>::max) ();
360         }
361     };
362 
363     template <>
364     struct chrono_numeric_limits<long double,true> {
lowestboost::chrono::detail::chrono_numeric_limits365         static long double lowest() throw()
366         {
367             return -(std::numeric_limits<long double>::max)();
368         }
369     };
370 
371     template <class T>
372     struct numeric_limits : chrono_numeric_limits<typename remove_cv<T>::type>
373     {};
374 
375 }
376 template <class Rep>
377 struct duration_values
378 {
zeroboost::chrono::duration_values379     static BOOST_CHRONO_CONSTEXPR Rep zero() {return Rep(0);}
BOOST_PREVENT_MACRO_SUBSTITUTIONboost::chrono::duration_values380     static BOOST_CHRONO_CONSTEXPR Rep max BOOST_PREVENT_MACRO_SUBSTITUTION ()
381     {
382         return (std::numeric_limits<Rep>::max)();
383     }
384 
BOOST_PREVENT_MACRO_SUBSTITUTIONboost::chrono::duration_values385     static BOOST_CHRONO_CONSTEXPR Rep min BOOST_PREVENT_MACRO_SUBSTITUTION ()
386     {
387         return detail::numeric_limits<Rep>::lowest();
388     }
389 };
390 
391 }  // namespace chrono
392 
393 //----------------------------------------------------------------------------//
394 //      20.9.2.3 Specializations of common_type [time.traits.specializations] //
395 //----------------------------------------------------------------------------//
396 
397 template <class Rep1, class Period1, class Rep2, class Period2>
398 struct common_type<chrono::duration<Rep1, Period1>,
399                    chrono::duration<Rep2, Period2> >
400 {
401   typedef chrono::duration<typename common_type<Rep1, Rep2>::type,
402                       typename boost::ratio_gcd<Period1, Period2>::type> type;
403 };
404 
405 
406 //----------------------------------------------------------------------------//
407 //                                                                            //
408 //         20.9.3 Class template duration [time.duration]                     //
409 //                                                                            //
410 //----------------------------------------------------------------------------//
411 
412 
413 namespace chrono {
414 
415     template <class Rep, class Period>
416     class duration
417     {
418     //BOOST_CHRONO_STATIC_ASSERT(boost::is_integral<Rep>::value, BOOST_CHRONO_A_DURATION_REPRESENTATION_MUST_BE_INTEGRAL, ());
419     BOOST_CHRONO_STATIC_ASSERT(!boost::chrono::detail::is_duration<Rep>::value,
420             BOOST_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION, ());
421     BOOST_CHRONO_STATIC_ASSERT(boost::ratio_detail::is_ratio<typename Period::type>::value,
422             BOOST_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO, ());
423     BOOST_CHRONO_STATIC_ASSERT(Period::num>0,
424             BOOST_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE, ());
425     public:
426         typedef Rep rep;
427         typedef Period period;
428     private:
429         rep rep_;
430     public:
431 
432         BOOST_CHRONO_CONSTEXPR
duration()433       duration() : rep_(duration_values<rep>::zero()) { }
434         template <class Rep2>
435         BOOST_CHRONO_CONSTEXPR
duration(const Rep2 & r,typename boost::enable_if<mpl::and_<boost::is_convertible<Rep2,rep>,mpl::or_<treat_as_floating_point<rep>,mpl::and_<mpl::not_<treat_as_floating_point<rep>>,mpl::not_<treat_as_floating_point<Rep2>>>>>>::type * =0)436         explicit duration(const Rep2& r
437         , typename boost::enable_if <
438                     mpl::and_ <
439                         boost::is_convertible<Rep2, rep>,
440                         mpl::or_ <
441                             treat_as_floating_point<rep>,
442                             mpl::and_ <
443                                 mpl::not_ < treat_as_floating_point<rep> >,
444                                 mpl::not_ < treat_as_floating_point<Rep2> >
445                             >
446                         >
447                     >
448                 >::type* = 0
449         ) : rep_(r) { }
~duration()450         ~duration() {} //= default;
duration(const duration & rhs)451         duration(const duration& rhs) : rep_(rhs.rep_) {} // = default;
operator =(const duration & rhs)452         duration& operator=(const duration& rhs) // = default;
453         {
454             if (&rhs != this) rep_= rhs.rep_;
455             return *this;
456         }
457 
458         // conversions
459         template <class Rep2, class Period2>
460         BOOST_CHRONO_CONSTEXPR
duration(const duration<Rep2,Period2> & d,typename boost::enable_if<mpl::or_<treat_as_floating_point<rep>,mpl::and_<chrono_detail::is_evenly_divisible_by<Period2,period>,mpl::not_<treat_as_floating_point<Rep2>>>>>::type * =0)461         duration(const duration<Rep2, Period2>& d
462         , typename boost::enable_if <
463                     mpl::or_ <
464                         treat_as_floating_point<rep>,
465                         mpl::and_ <
466                             chrono_detail::is_evenly_divisible_by<Period2, period>,
467                             mpl::not_ < treat_as_floating_point<Rep2> >
468                         >
469                     >
470                 >::type* = 0
471         )
472             : rep_(chrono::detail::duration_cast<duration<Rep2, Period2>, duration>()(d).count()) {}
473 
474         // observer
475 
476         BOOST_CHRONO_CONSTEXPR
count() const477         rep count() const {return rep_;}
478 
479         // arithmetic
480 
481         BOOST_CHRONO_CONSTEXPR
operator +() const482         duration  operator+() const {return *this;}
483         BOOST_CHRONO_CONSTEXPR
operator -() const484         duration  operator-() const {return duration(-rep_);}
operator ++()485         duration& operator++()      {++rep_; return *this;}
operator ++(int)486         duration  operator++(int)   {return duration(rep_++);}
operator --()487         duration& operator--()      {--rep_; return *this;}
operator --(int)488         duration  operator--(int)   {return duration(rep_--);}
489 
operator +=(const duration & d)490         duration& operator+=(const duration& d)
491         {
492             rep_ += d.count(); return *this;
493         }
operator -=(const duration & d)494         duration& operator-=(const duration& d)
495         {
496             rep_ -= d.count(); return *this;
497         }
498 
operator *=(const rep & rhs)499         duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;}
operator /=(const rep & rhs)500         duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;}
operator %=(const rep & rhs)501         duration& operator%=(const rep& rhs) {rep_ %= rhs; return *this;}
operator %=(const duration & rhs)502         duration& operator%=(const duration& rhs)
503         {
504             rep_ %= rhs.count(); return *this;
505         }
506         // 20.9.3.4 duration special values [time.duration.special]
507 
zero()508         static BOOST_CHRONO_CONSTEXPR duration zero()
509         {
510             return duration(duration_values<rep>::zero());
511         }
BOOST_PREVENT_MACRO_SUBSTITUTION()512         static BOOST_CHRONO_CONSTEXPR duration min BOOST_PREVENT_MACRO_SUBSTITUTION ()
513         {
514             return duration((duration_values<rep>::min)());
515         }
BOOST_PREVENT_MACRO_SUBSTITUTION()516         static BOOST_CHRONO_CONSTEXPR duration max BOOST_PREVENT_MACRO_SUBSTITUTION ()
517         {
518             return duration((duration_values<rep>::max)());
519         }
520     };
521 
522 //----------------------------------------------------------------------------//
523 //      20.9.3.5 duration non-member arithmetic [time.duration.nonmember]     //
524 //----------------------------------------------------------------------------//
525 
526     // Duration +
527 
528     template <class Rep1, class Period1, class Rep2, class Period2>
529     inline
530     typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator +(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)531     operator+(const duration<Rep1, Period1>& lhs,
532           const duration<Rep2, Period2>& rhs)
533     {
534       typename common_type<duration<Rep1, Period1>,
535         duration<Rep2, Period2> >::type result = lhs;
536       result += rhs;
537       return result;
538     }
539 
540     // Duration -
541 
542     template <class Rep1, class Period1, class Rep2, class Period2>
543     inline
544     typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator -(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)545     operator-(const duration<Rep1, Period1>& lhs,
546           const duration<Rep2, Period2>& rhs)
547     {
548         typename common_type<duration<Rep1, Period1>,
549             duration<Rep2, Period2> >::type result = lhs;
550         result -= rhs;
551         return result;
552     }
553 
554     // Duration *
555 
556     template <class Rep1, class Period, class Rep2>
557     inline
558     typename boost::enable_if <
559         mpl::and_ <
560         boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
561         boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
562         >,
563         duration<typename common_type<Rep1, Rep2>::type, Period>
564     >::type
operator *(const duration<Rep1,Period> & d,const Rep2 & s)565     operator*(const duration<Rep1, Period>& d, const Rep2& s)
566     {
567         typedef typename common_type<Rep1, Rep2>::type CR;
568             duration<CR, Period> r = d;
569         r *= static_cast<CR>(s);
570         return r;
571     }
572 
573     template <class Rep1, class Period, class Rep2>
574     inline
575     typename boost::enable_if <
576         mpl::and_ <
577         boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
578         boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
579         >,
580         duration<typename common_type<Rep1, Rep2>::type, Period>
581     >::type
operator *(const Rep1 & s,const duration<Rep2,Period> & d)582     operator*(const Rep1& s, const duration<Rep2, Period>& d)
583     {
584         return d * s;
585     }
586 
587     // Duration /
588 
589     template <class Rep1, class Period, class Rep2>
590     inline
591     typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>,
592       typename boost::chrono::detail::duration_divide_result<
593         duration<Rep1, Period>, Rep2>::type
594     >::type
operator /(const duration<Rep1,Period> & d,const Rep2 & s)595     operator/(const duration<Rep1, Period>& d, const Rep2& s)
596     {
597         typedef typename common_type<Rep1, Rep2>::type CR;
598           duration<CR, Period> r = d;
599         r /= static_cast<CR>(s);
600         return r;
601     }
602 
603     template <class Rep1, class Period1, class Rep2, class Period2>
604     inline
605     typename common_type<Rep1, Rep2>::type
operator /(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)606     operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
607     {
608         typedef typename common_type<duration<Rep1, Period1>,
609                                    duration<Rep2, Period2> >::type CD;
610         return CD(lhs).count() / CD(rhs).count();
611     }
612 
613     #ifdef BOOST_CHRONO_EXTENSIONS
614     template <class Rep1, class Rep2, class Period>
615     inline
616     typename boost::disable_if <boost::chrono::detail::is_duration<Rep1>,
617       typename boost::chrono::detail::duration_divide_result2<
618         Rep1, duration<Rep2, Period> >::type
619       >::type
operator /(const Rep1 & s,const duration<Rep2,Period> & d)620     operator/(const Rep1& s, const duration<Rep2, Period>& d)
621     {
622         typedef typename common_type<Rep1, Rep2>::type CR;
623         duration<CR, Period> r = d;
624         return  static_cast<CR>(s)/r.count();
625     }
626     #endif
627     // Duration %
628 
629     template <class Rep1, class Period, class Rep2>
630     typename boost::disable_if <boost::chrono::detail::is_duration<Rep2>,
631       typename boost::chrono::detail::duration_modulo_result<
632         duration<Rep1, Period>, Rep2>::type
633     >::type
operator %(const duration<Rep1,Period> & d,const Rep2 & s)634     operator%(const duration<Rep1, Period>& d, const Rep2& s)
635     {
636         typedef typename common_type<Rep1, Rep2>::type CR;
637         duration<CR, Period> r = d;
638         r %= static_cast<CR>(s);
639         return r;
640     }
641 
642     template <class Rep1, class Period1, class Rep2, class Period2>
643     typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator %(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)644     operator%(const duration<Rep1, Period1>& lhs,
645           const duration<Rep2, Period2>& rhs) {
646         typedef typename common_type<duration<Rep1, Period1>,
647                                  duration<Rep2, Period2> >::type CD;
648         CD r(lhs);
649         r%=CD(rhs);
650         return r;
651     }
652 
653 
654 //----------------------------------------------------------------------------//
655 //      20.9.3.6 duration comparisons [time.duration.comparisons]             //
656 //----------------------------------------------------------------------------//
657 
658 namespace detail
659 {
660     template <class LhsDuration, class RhsDuration>
661     struct duration_eq
662     {
operator ()boost::chrono::detail::duration_eq663         bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
664         {
665             typedef typename common_type<LhsDuration, RhsDuration>::type CD;
666             return CD(lhs).count() == CD(rhs).count();
667         }
668     };
669 
670     template <class LhsDuration>
671     struct duration_eq<LhsDuration, LhsDuration>
672     {
operator ()boost::chrono::detail::duration_eq673         bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
674         {
675             return lhs.count() == rhs.count();
676         }
677     };
678 
679     template <class LhsDuration, class RhsDuration>
680     struct duration_lt
681     {
operator ()boost::chrono::detail::duration_lt682         bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
683         {
684             typedef typename common_type<LhsDuration, RhsDuration>::type CD;
685             return CD(lhs).count() < CD(rhs).count();
686         }
687     };
688 
689     template <class LhsDuration>
690     struct duration_lt<LhsDuration, LhsDuration>
691     {
operator ()boost::chrono::detail::duration_lt692         bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
693         {
694             return lhs.count() < rhs.count();
695         }
696     };
697 
698 } // namespace detail
699 
700     // Duration ==
701 
702     template <class Rep1, class Period1, class Rep2, class Period2>
703     inline BOOST_CHRONO_CONSTEXPR
704     bool
operator ==(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)705     operator==(const duration<Rep1, Period1>& lhs,
706           const duration<Rep2, Period2>& rhs)
707     {
708         return boost::chrono::detail::duration_eq<
709             duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
710     }
711 
712     // Duration !=
713 
714     template <class Rep1, class Period1, class Rep2, class Period2>
715     inline BOOST_CHRONO_CONSTEXPR
716     bool
operator !=(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)717     operator!=(const duration<Rep1, Period1>& lhs,
718           const duration<Rep2, Period2>& rhs)
719     {
720         return !(lhs == rhs);
721     }
722 
723     // Duration <
724 
725     template <class Rep1, class Period1, class Rep2, class Period2>
726     inline BOOST_CHRONO_CONSTEXPR
727     bool
operator <(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)728     operator< (const duration<Rep1, Period1>& lhs,
729           const duration<Rep2, Period2>& rhs)
730     {
731         return boost::chrono::detail::duration_lt<
732           duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
733     }
734 
735     // Duration >
736 
737     template <class Rep1, class Period1, class Rep2, class Period2>
738     inline BOOST_CHRONO_CONSTEXPR
739     bool
operator >(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)740     operator> (const duration<Rep1, Period1>& lhs,
741           const duration<Rep2, Period2>& rhs)
742     {
743         return rhs < lhs;
744     }
745 
746     // Duration <=
747 
748     template <class Rep1, class Period1, class Rep2, class Period2>
749     inline BOOST_CHRONO_CONSTEXPR
750     bool
operator <=(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)751     operator<=(const duration<Rep1, Period1>& lhs,
752           const duration<Rep2, Period2>& rhs)
753     {
754         return !(rhs < lhs);
755     }
756 
757     // Duration >=
758 
759     template <class Rep1, class Period1, class Rep2, class Period2>
760     inline
761     bool
operator >=(const duration<Rep1,Period1> & lhs,const duration<Rep2,Period2> & rhs)762     operator>=(const duration<Rep1, Period1>& lhs,
763           const duration<Rep2, Period2>& rhs)
764     {
765         return !(lhs < rhs);
766     }
767 
768 //----------------------------------------------------------------------------//
769 //      20.9.3.7 duration_cast [time.duration.cast]                           //
770 //----------------------------------------------------------------------------//
771 
772     // Compile-time select the most efficient algorithm for the conversion...
773     template <class ToDuration, class Rep, class Period>
774     inline BOOST_CHRONO_CONSTEXPR
775     typename boost::enable_if <
776       boost::chrono::detail::is_duration<ToDuration>, ToDuration>::type
duration_cast(const duration<Rep,Period> & fd)777     duration_cast(const duration<Rep, Period>& fd)
778     {
779         return boost::chrono::detail::duration_cast<
780           duration<Rep, Period>, ToDuration>()(fd);
781     }
782 
783 } // namespace chrono
784 } // namespace boost
785 
786 #endif // BOOST_CHRONO_DURATION_HPP
787