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