|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r67575 - in trunk/libs/ratio: . doc example example/type_traits example/type_traits/detail
From: vicente.botet_at_[hidden]
Date: 2011-01-02 11:26:55
Author: viboes
Date: 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
New Revision: 67575
URL: http://svn.boost.org/trac/boost/changeset/67575
Log:
Boost.Ratio: moved to trunk
Added:
trunk/libs/ratio/
trunk/libs/ratio/doc/
trunk/libs/ratio/doc/Jamfile.v2 (contents, props changed)
trunk/libs/ratio/doc/index.html (contents, props changed)
trunk/libs/ratio/doc/ratio.pdf (contents, props changed)
trunk/libs/ratio/doc/ratio.qbk (contents, props changed)
trunk/libs/ratio/example/
trunk/libs/ratio/example/config.hpp (contents, props changed)
trunk/libs/ratio/example/display_ex.cpp (contents, props changed)
trunk/libs/ratio/example/duration.hpp (contents, props changed)
trunk/libs/ratio/example/si_physics.cpp (contents, props changed)
trunk/libs/ratio/example/static_assert.hpp (contents, props changed)
trunk/libs/ratio/example/type_traits/
trunk/libs/ratio/example/type_traits/add_rvalue_reference.hpp (contents, props changed)
trunk/libs/ratio/example/type_traits/common_type.hpp (contents, props changed)
trunk/libs/ratio/example/type_traits/declval.hpp (contents, props changed)
trunk/libs/ratio/example/type_traits/detail/
trunk/libs/ratio/example/type_traits/detail/common_type.hpp (contents, props changed)
Added: trunk/libs/ratio/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/doc/Jamfile.v2 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,73 @@
+# Boost.Ratio library documentation Jamfile ---------------------------------
+#
+# Copyright Vicente J. Botet Escriba 2010. Use, modification and
+# distribution is subject to the Boost Software License, Version
+# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+# http://www.boost.org/LICENSE_1_0.txt)
+#
+# See http://www.boost.org for updates, documentation, and revision history.
+
+#import doxygen ;
+import quickbook ;
+
+#doxygen autodoc
+# :
+# [ glob ../../../boost/chrono/*.hpp ]
+# [ glob ../../../boost/chrono/allocators/*.hpp ]
+# :
+# <doxygen:param>EXTRACT_ALL=NO
+# <doxygen:param>HIDE_UNDOC_MEMBERS=YES
+# <doxygen:param>EXTRACT_PRIVATE=NO
+# <doxygen:param>EXPAND_ONLY_PREDEF=YES
+# <doxygen:param>PREDEFINED=BOOST_INTERPROCESS_DOXYGEN_INVOKED
+# <xsl:param>"boost.doxygen.reftitle=Boost.Chrono Reference"
+# ;
+
+xml ratio : ratio.qbk ;
+
+boostbook standalone
+ :
+ ratio
+ :
+ # HTML options first:
+ # Use graphics not text for navigation:
+ <xsl:param>navig.graphics=1
+ # How far down we chunk nested sections, basically all of them:
+ <xsl:param>chunk.section.depth=0
+ # Don't put the first section on the same page as the TOC:
+ <xsl:param>chunk.first.sections=1
+ # How far down sections get TOC's
+ <xsl:param>toc.section.depth=4
+ # Max depth in each TOC:
+ <xsl:param>toc.max.depth=2
+ # How far down we go with TOC's
+ <xsl:param>generate.section.toc.level=10
+ # Path for links to Boost:
+ <xsl:param>boost.root=../../../..
+ # Path for libraries index:
+ <xsl:param>boost.libraries=../../../../libs/libraries.htm
+ # Use the main Boost stylesheet:
+ <xsl:param>html.stylesheet=../../../../doc/src/boostbook.css
+
+ # PDF Options:
+ # TOC Generation: this is needed for FOP-0.9 and later:
+ <xsl:param>fop1.extensions=0
+ # Or enable this if you're using XEP:
+ <xsl:param>xep.extensions=1
+ # TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
+ <xsl:param>fop.extensions=0
+ # No indent on body text:
+ <xsl:param>body.start.indent=0pt
+ # Margin size:
+ <xsl:param>page.margin.inner=0.5in
+ # Margin size:
+ <xsl:param>page.margin.outer=0.5in
+ # Yes, we want graphics for admonishments:
+ <xsl:param>admon.graphics=1
+ # Set this one for PDF generation *only*:
+ # default pnd graphics are awful in PDF form,
+ # better use SVG's instead:
+ <format>pdf:<xsl:param>admon.graphics.extension=".svg"
+ <format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
+ <format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/regex/doc/html
+ ;
Added: trunk/libs/ratio/doc/index.html
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/doc/index.html 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,15 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=html/index.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+../../doc/html/ratio.html
+<p>© Copyright 2009-2010 Vicente J. Botet Escribá.
+Distributed under the Boost Software
+License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
+LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
+http://www.boost.org/LICENSE_1_0.txt>)
+</p>
+</body>
+</html>
Added: trunk/libs/ratio/doc/ratio.pdf
==============================================================================
Binary file. No diff available.
Added: trunk/libs/ratio/doc/ratio.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/doc/ratio.qbk 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,1256 @@
+[/
+ / Copyright (c) 2008 Howard Hinnant
+ / Copyright (c) 2006, 2008 Beman Dawes
+ / Copyright (c) 2009-20010 Vicente J. Botet Escriba
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See accompanying
+ / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ /]
+
+[article Boost.Ratio
+ [quickbook 1.5]
+ [version 1.0.0]
+ [authors [Hinnant, Howard]]
+ [authors [Dawes, Beman]]
+ [authors [Botet Escriba, Vicente J.]]
+ [copyright 2008 Howard Hinnant]
+ [copyright 2006, 2008 Beman Dawes]
+ [copyright 2009-2010 Vicente J. Botet Escriba]
+ [license
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ [@http://www.boost.org/LICENSE_1_0.txt])
+ ]
+]
+
+[/==================]
+[def __Boost_Ratio__ [*Boost.Ratio]]
+
+[/===============================================]
+
+[def __time_point `time_point`]
+[def __hours `hours`]
+
+[/===============================================]
+[def __ratio [link boost_ratio.reference.ratio_hpp.ratio `ratio`]]
+
+[template ratio_conf[link_text] [link boost_ratio.reference.ratio_hpp.conf [link_text]]]
+
+[def __BOOST_RATIO_USES_STATIC_ASSERT [link boost_ratio.reference.ratio_hpp.conf `BOOST_RATIO_USES_STATIC_ASSERT`]]
+[def __BOOST_RATIO_USES_MPL_ASSERT [link boost_ratio.reference.ratio_hpp.conf `BOOST_RATIO_USES_MPL_ASSERT`]]
+[def __BOOST_RATIO_USES_ARRAY_ASSERT [link boost_ratio.reference.ratio_hpp.conf `BOOST_RATIO_USES_ARRAY_ASSERT`]]
+
+[template ratio_arithmetic[link_text] [link boost_ratio.reference.ratio_hpp.ratio_arithmetic [link_text]]]
+[def __ratio_add [link boost_ratio.reference.ratio_hpp.ratio_arithmetic `ratio_add`]]
+[def __ratio_subtract [link boost_ratio.reference.ratio_hpp.ratio_arithmetic `ratio_subtract`]]
+[def __ratio_multiply [link boost_ratio.reference.ratio_hpp.ratio_arithmetic `ratio_multiply`]]
+[def __ratio_divide [link boost_ratio.reference.ratio_hpp.ratio_arithmetic `ratio_divide`]]
+
+
+[template ratio_comparison[link_text] [link boost_ratio.reference.ratio_hpp.ratio_comparison [link_text]]]
+[def __ratio_equal [link boost_ratio.reference.ratio_hpp.ratio_comparison `ratio_equal`]]
+[def __ratio_not_equal [link boost_ratio.reference.ratio_hpp.ratio_comparison `ratio_not_equal`]]
+[def __ratio_less [link boost_ratio.reference.ratio_hpp.ratio_comparison `ratio_less`]]
+[def __ratio_less_equal [link boost_ratio.reference.ratio_hpp.ratio_comparison `ratio_less_equal`]]
+[def __ratio_greater [link boost_ratio.reference.ratio_hpp.ratio_comparison `ratio_greater`]]
+[def __ratio_greater_equal [link boost_ratio.reference.ratio_hpp.ratio_comparison `ratio_greater_equal`]]
+
+
+[template ratio_si_typedefs[link_text] [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs [link_text]]]
+[def __atto [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `atto`]]
+[def __femto [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `femto`]]
+[def __pico [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `pico`]]
+[def __nano [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `nano`]]
+[def __micro [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `micro`]]
+[def __milli [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `milli`]]
+[def __centi [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `centi`]]
+[def __deci [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `deci`]]
+[def __deca [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `deca`]]
+[def __hecto [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `hecto`]]
+[def __kilo [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `kilo`]]
+[def __mega [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `mega`]]
+[def __giga [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `giga`]]
+[def __tera [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `tera`]]
+[def __peta [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `peta`]]
+[def __exa [link boost_ratio.reference.ratio_hpp.ratio_si_typedefs `exa`]]
+
+
+[warning Ratio is not part of the Boost libraries.]
+
+[/===============]
+[section Overview]
+[/===============]
+
+
+[/====================================]
+[heading How to Use This Documentation]
+[/====================================]
+
+This documentation makes use of the following naming and formatting conventions.
+
+* Code is in `fixed width font` and is syntax-highlighted.
+* Replaceable text that you will need to supply is in [~italics].
+* Free functions are rendered in the code font followed by `()`, as in `free_function()`.
+* If a name refers to a class template, it is specified like this: `class_template<>`; that is, it is in code font and its name is followed by `<>` to indicate that it is a class template.
+* If a name refers to a function-like macro, it is specified like this: `MACRO()`;
+ that is, it is uppercase in code font and its name is followed by `()` to indicate that it is a function-like macro. Object-like macros appear without the trailing `()`.
+* Names that refer to /concepts/ in the generic programming sense are specified in CamelCase.
+
+[note In addition, notes such as this one specify non-essential information that provides additional background or rationale.]
+
+Finally, you can mentally add the following to any code fragments in this document:
+
+ // Include all of Ratio files
+ #include <boost/ratio.hpp>
+ using namespace boost;
+
+[/=================]
+[section Motivation]
+[/=================]
+
+__Boost_Ratio__ aims to implement the compile time ratio facility in C++0x, as proposed in [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm [*N2661 - A Foundation to Sleep On]]. That document provides background and motivation for key design decisions and is the source of a good deal of information in this documentation.
+
+[endsect]
+
+[/==================]
+[section Description]
+[/==================]
+
+The __Boost_Ratio__ library provides:
+
+* A class template, __ratio, for specifying compile time rational constants such as 1/3 of a nanosecond or the number of inches per meter. __ratio represents a compile time ratio of compile time constants with support for compile time arithmetic with overflow and division by zero protection
+
+* It provides a textual representation of `boost::ratio<N, D>` in the form of a `std::basic_string` which can be useful for I/O.
+
+[endsect]
+
+[endsect]
+
+
+[/==============================]
+[section:users_guide User's Guide]
+[/==============================]
+
+[/======================================]
+[section:getting_started Getting Started]
+[/======================================]
+
+[/======================================]
+[section:install Installing Ratio]
+[/======================================]
+
+[/=================================]
+[heading Getting Boost.Ratio ]
+[/=================================]
+
+You can get the last stable release of __Boost_Ratio__ by downloading [^ratio.zip] from the
+[@http://www.boostpro.com/vault/index.php?action=downloadfile&filename=ratio.zip&directory=Math%20-%20Numerics&PHPSESSID=2d7859f3e812c993f5a9e2d9900dfee8 Boost Vault].
+
+You can also access the latest (unstable?) state from the [@https://svn.boost.org/svn/boost/sandbox/chrono Boost Sandbox] directories boost/ratio and libs/ratio. Just go to [@http://svn.boost.org/trac/boost/wiki/BoostSubversion here] and follow the instructions there for anonymous SVN access.
+
+[/==========================================]
+[heading Where to install Boost.Ratio? ]
+[/==========================================]
+
+The simple way is to decompress (or checkout from SVN) the file in your BOOST_ROOT directory.
+
+Othesewise, if you decompress in a different directory, you will need to comment some lines, and uncomment and change others in the build/Jamfile and test/Jamfile. Sorry for this, but I have not reached yet to write a Jamfile that is able to work in both environements and use the BOOST_ROOT variable. Any help is welcome.
+
+[/=================================]
+[heading Building Boost.Ratio ]
+[/=================================]
+
+__Boost_Ratio__ is a header only library, so no need to compile anything.
+
+
+[/===================]
+[heading Requirements]
+[/===================]
+
+__Boost_Ratio__ depends on some Boost libraries. For these specific parts you must use either Boost version 1.39.0 or later (even if older versions should works also).
+
+In particular, __Boost_Ratio__ depends on:
+
+[variablelist
+[
+ [[@http://www.boost.org/libs/config [*Boost.Config]]] [for configuration purposes, ...]
+]
+[
+ [[@http://www.boost.org/libs/integer [*Boost.Integer]]] [for cstdint conformance, and integer traits ...]
+]
+[
+ [[@http://www.boost.org/libs/mpl [*Boost.MPL]]] [for MPL Assert and bool, logical ...]
+]
+[
+ [[@http://www.boost.org/libs/static_assert [*Boost.StaticAssert]]] [for STATIC_ASSERT, ...]
+]
+[
+ [[@http://www.boost.org/libs/type_traits [*Boost.TypeTraits]]] [for is_base, is_convertible ...]
+]
+[
+ [[@http://www.boost.org/libs/utility [*Boost.Utility/EnableIf]]] [for enable_if, ...]
+]
+]
+
+
+[/=========================================================]
+[heading Building an executable that uses __Boost_Ratio__ ]
+[/=========================================================]
+
+No link is needed.
+
+
+[/=========================]
+[heading Exception safety ]
+[/=========================]
+
+All functions in the library are exception-neutral, providing the strong exception safety guarantee.
+
+[/=====================]
+[heading Thread safety ]
+[/=====================]
+
+All functions in the library are thread-unsafe except when noted explicitly.
+
+[/========================]
+[heading Tested compilers ]
+[/========================]
+
+__Boost_Ratio__ should work with an C++03 conforming compiler. The current version has been tested on:
+
+Windows with
+
+* MSVC 10.0
+* MSVC 9.0 Express
+* MSVC 8.0
+
+[/* Intel 11.0]
+
+Scientific Linux with
+
+* GCC 4.1.2
+
+Cygwin with
+
+* GCC 3.4.4
+* GCC 4.3.2
+
+MinGW with
+
+* GCC 4.4.0
+* GCC 4.5.0
+
+Initial version was tested on:
+
+MacOS with GCC 4.2.4
+
+Ubuntu Linux with GCC 4.2.4
+
+[note Please let us know how this works on other platforms/compilers.]
+
+[note Please send any questions, comments and bug reports to boost <at> lists <dot> boost <dot> org.]
+
+[endsect]
+[/
+[/====================]
+[section Hello World! ]
+[/====================]
+
+If all you want to do is to time a program's execution, here is a complete program (stopclock_example.cpp):
+
+ #include <boost/ratio.hpp>
+
+
+[endsect]
+]
+[endsect]
+
+
+[section Tutorial]
+
+[heading Ratio]
+
+__ratio is a general purpose utility inspired by Walter Brown allowing one to easily and safely compute rational values at compile time. The __ratio class catches all errors (such as divide by zero and overflow) at compile time. It is used in the duration and __time_point classes to efficiently create units of time. It can also be used in other "quantity" libraries or anywhere there is a rational constant which is known at compile time. The use of this utility can greatly reduce the chances of run time overflow because the __ratio (and any ratios resulting from __ratio arithmetic) are always reduced to lowest terms.
+
+__ratio is a template taking two intmax_ts, with the second defaulted to 1. In addition to copy constructors and assignment, it only has two public members, both of which are static const intmax_t. One is the numerator of the __ratio and the other is the denominator. The __ratio is always normalized such that it is expressed in lowest terms, and the denominator is always positive. When the numerator is 0, the denominator is always 1.
+
+[*Example:]
+
+ typedef __ratio<5, 3> five_thirds;
+ // five_thirds::num == 5, five_thirds::den == 3
+
+ typedef __ratio<25, 15> also_five_thirds;
+ // also_five_thirds::num == 5, also_five_thirds::den == 3
+
+ typedef ratio_divide<five_thirds, also_five_thirds>::type one;
+ // one::num == 1, one::den == 1
+
+This facility also includes convenience typedefs for the SI prefixes __atto through __exa corresponding to their internationally recognized definitions (in terms of __ratio). This is a tremendous syntactic convenience. It will prevent errors in specifying constants as one no longer has to double count the number of zeros when trying to write millions or billions.
+
+[*Example:]
+
+ typedef ratio_multiply<__ratio<5>, giga>::type _5giga;
+ // _5giga::num == 5000000000, _5giga::den == 1
+
+ typedef ratio_multiply<__ratio<5>, nano>::type _5nano;
+ // _5nano::num == 1, _5nano::den == 200000000
+
+[heading Ratio I/O]
+
+For each `ratio<N, D>` there exists a `ratio_string<ratio<N, D>, CharT>` for which you can query two strings: `short_name` and `long_name`. For those `ratio`'s that correspond to an [@http://en.wikipedia.org/wiki/SI_prefix#List_of_SI_prefixes SI prefix] long_name corresponds to the internationally recognized prefix, stored as a `basic_string<CharT>`. For example `ratio_string<mega, char>::long_name()` returns `string("mega")`. For those `ratio`'s that correspond to an [@http://en.wikipedia.org/wiki/SI_prefix#List_of_SI_prefixes SI prefix] `short_name` corresponds to the internationally recognized symbol, stored as a `basic_string<CharT>`. For example `ratio_string<mega, char>::short_name()` returns `string("M")`. For all other `ratio`'s, both `long_name()` and `short_name()` return a `basic_string` containing "[`ratio::num/ratio::den`]".
+
+`ratio_string<ratio<N, D>, CharT>` is only defined for four character types:
+
+* `char`: UTF-8
+* `char16_t`: UTF-16
+* `char32_t`: UTF-32
+* `wchar_t`: UTF-16 (if wchar_t is 16 bits) or UTF-32
+
+When the character is char, UTF-8 will be used to encode the names. When the character is `char16_t`, UTF-16 will be used to encode the names. When the character is `char32_t`, UTF-32 will be used to encode the names. When the character is `wchar_t`, the encoding will be UTF-16 if `wchar_t` is 16 bits, and otherwise UTF-32.
+
+The `short_name` for micro is defined by [@http://www.unicode.org/charts/PDF/U0080.pdf Unicode] to be U+00B5.
+
+[*Examples:]
+
+ #include <boost/ratio/ratio_io.hpp>
+ #include <iostream>
+
+ int main()
+ {
+ using namespace std;
+ using namespace boost;
+
+ cout << "ratio_string<deca, char>::long_name() = "
+ << ratio_string<deca, char>::long_name() << '\n';
+ cout << "ratio_string<deca, char>::short_name() = "
+ << ratio_string<deca, char>::short_name() << '\n';
+
+ cout << "ratio_string<giga, char>::long_name() = "
+ << ratio_string<giga, char>::long_name() << '\n';
+ cout << "ratio_string<giga, char>::short_name() = "
+ << ratio_string<giga, char>::short_name() << '\n';
+
+ cout << "ratio_string<ratio<4, 6>, char>::long_name() = "
+ << ratio_string<ratio<4, 6>, char>::long_name() << '\n';
+ cout << "ratio_string<ratio<4, 6>, char>::short_name() = "
+ << ratio_string<ratio<4, 6>, char>::short_name() << '\n';
+ }
+
+The output will be
+
+ ratio_string<deca, char>::long_name() = deca
+ ratio_string<deca, char>::short_name() = da
+ ratio_string<giga, char>::long_name() = giga
+ ratio_string<giga, char>::short_name() = G
+ ratio_string<ratio<4, 6>, char>::long_name() = [2/3]
+ ratio_string<ratio<4, 6>, char>::short_name() = [2/3]
+
+[endsect]
+[/===============]
+[section:Examples Example]
+[/===============]
+
+[/===============]
+[section SI units]
+[/===============]
+
+This example illustrates the use of type-safe physics code interoperating with `boost::chrono::duration` types, taking advantage of the __Boost_Ratio__ infrastructure and design philosophy.
+
+Let's start by defining a `length` class template that mimics `boost::chrono::duration`, which represents a time duration in various units, but restricts the representation to `double` and uses __Boost_Ratio__ for length unit conversions:
+
+
+ template <class Ratio>
+ class length {
+ private:
+ double len_;
+ public:
+ typedef Ratio ratio;
+ length() : len_(1) {}
+ length(const double& len) : len_(len) {}
+
+ template <class R>
+ length(const length<R>& d)
+ : len_(d.count() * boost::ratio_divide<Ratio, R>::type::den /
+ boost::ratio_divide<Ratio, R>::type::num) {}
+
+ double count() const {return len_;}
+
+ length& operator+=(const length& d) {len_ += d.count(); return *this;}
+ length& operator-=(const length& d) {len_ -= d.count(); return *this;}
+
+ length operator+() const {return *this;}
+ length operator-() const {return length(-len_);}
+
+ length& operator*=(double rhs) {len_ *= rhs; return *this;}
+ length& operator/=(double rhs) {len_ /= rhs; return *this;}
+ };
+
+
+Here's a small sampling of length units:
+
+ typedef length<boost::__ratio<1> > meter; // set meter as "unity"
+ typedef length<boost::__centi> centimeter; // 1/100 meter
+ typedef length<boost::__kilo> kilometer; // 1000 meters
+ typedef length<boost::__ratio<254, 10000> > inch; // 254/10000 meters
+
+Note that since `length`'s template parameter is actually a generic ratio type, so we can use boost::ratio allowing for more complex length units:
+
+ typedef length<boost::ratio_multiply<boost::__ratio<12>, inch::__ratio>::type> foot; // 12 inchs
+ typedef length<boost::ratio_multiply<boost::__ratio<5280>, foot::__ratio>::type> mile; // 5280 feet
+
+Now we need a floating point-based definition of seconds:
+
+ typedef boost::chrono::duration<double> seconds; // unity
+
+We can even support sub-nanosecond durations:
+
+ typedef boost::chrono::duration<double, boost::__pico> picosecond; // 10^-12 seconds
+ typedef boost::chrono::duration<double, boost::__femto> femtosecond; // 10^-15 seconds
+ typedef boost::chrono::duration<double, boost::__atto> attosecond; // 10^-18 seconds
+
+Finally, we can write a proof-of-concept of an SI units library, hard-wired for meters and floating point seconds, though it will accept other units:
+
+ template <class R1, class R2>
+ class quantity
+ {
+ double q_;
+ public:
+ typedef R1 time_dim;
+ typedef R2 distance_dim;
+ quantity() : q_(1) {}
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+ };
+
+ template <>
+ class quantity<boost::__ratio<1>, boost::__ratio<0> >
+ {
+ double q_;
+ public:
+ quantity() : q_(1) {}
+ quantity(seconds d) : q_(d.count()) {} // note: only User1::seconds needed here
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+ };
+
+ template <>
+ class quantity<boost::__ratio<0>, boost::__ratio<1> >
+ {
+ double q_;
+ public:
+ quantity() : q_(1) {}
+ quantity(meter d) : q_(d.count()) {} // note: only User1::meter needed here
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+ };
+
+ template <>
+ class quantity<boost::__ratio<0>, boost::__ratio<0> >
+ {
+ double q_;
+ public:
+ quantity() : q_(1) {}
+ quantity(double d) : q_(d) {}
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+ };
+
+That allows us to create some useful SI-based unit types:
+
+ typedef quantity<boost::__ratio<0>, boost::__ratio<0> > Scalar;
+ typedef quantity<boost::__ratio<1>, boost::__ratio<0> > Time; // second
+ typedef quantity<boost::__ratio<0>, boost::__ratio<1> > Distance; // meter
+ typedef quantity<boost::__ratio<-1>, boost::__ratio<1> > Speed; // meter/second
+ typedef quantity<boost::__ratio<-2>, boost::__ratio<1> > Acceleration; // meter/second^2
+
+To make quantity useful, we need to be able to do arithmetic:
+
+ template <class R1, class R2, class R3, class R4>
+ quantity<typename boost::ratio_subtract<R1, R3>::type,
+ typename boost::ratio_subtract<R2, R4>::type>
+ operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
+ {
+ typedef quantity<typename boost::ratio_subtract<R1, R3>::type,
+ typename boost::ratio_subtract<R2, R4>::type> R;
+ R r;
+ r.set(x.get() / y.get());
+ return r;
+ }
+
+ template <class R1, class R2, class R3, class R4>
+ quantity<typename boost::ratio_add<R1, R3>::type,
+ typename boost::ratio_add<R2, R4>::type>
+ operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
+ {
+ typedef quantity<typename boost::ratio_add<R1, R3>::type,
+ typename boost::ratio_add<R2, R4>::type> R;
+ R r;
+ r.set(x.get() * y.get());
+ return r;
+ }
+
+ template <class R1, class R2>
+ quantity<R1, R2>
+ operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
+ {
+ typedef quantity<R1, R2> R;
+ R r;
+ r.set(x.get() + y.get());
+ return r;
+ }
+
+ template <class R1, class R2>
+ quantity<R1, R2>
+ operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
+ {
+ typedef quantity<R1, R2> R;
+ R r;
+ r.set(x.get() - y.get());
+ return r;
+ }
+
+With all of the foregoing scaffolding, we can now write an exemplar of a type-safe physics function:
+
+ Distance
+ compute_distance(Speed v0, Time t, Acceleration a)
+ {
+ return v0 * t + Scalar(.5) * a * t * t; // if a units mistake is made here it won't compile
+ }
+
+
+Finally, we can exercise what we've created, even using custom time durations (`User1::seconds`) as well as Boost time durations (`boost::chrono::hours`). The input can be in arbitrary, though type-safe, units, the output is always in SI units. (A complete Units library would support other units, of course.)
+
+ int main()
+ {
+ typedef boost::__ratio<8, BOOST_INTMAX_C(0x7FFFFFFFD)> R1;
+ typedef boost::__ratio<3, BOOST_INTMAX_C(0x7FFFFFFFD)> R2;
+ typedef User1::quantity<boost::ratio_subtract<boost::__ratio<0>, boost::__ratio<1> >::type,
+ boost::ratio_subtract<boost::__ratio<1>, boost::__ratio<0> >::type > RR;
+ typedef boost::ratio_subtract<R1, R2>::type RS;
+ std::cout << RS::num << '/' << RS::den << '\n';
+
+
+ std::cout << "*************\n";
+ std::cout << "* testUser1 *\n";
+ std::cout << "*************\n";
+ User1::Distance d( User1::mile(110) );
+ User1::Time t( boost::chrono::__hours(2) );
+
+ RR r=d / t;
+ //r.set(d.get() / t.get());
+
+ User1::Speed rc= r;
+
+ User1::Speed s = d / t;
+ std::cout << "Speed = " << s.get() << " meters/sec\n";
+ User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time();
+ std::cout << "Acceleration = " << a.get() << " meters/sec^2\n";
+ User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a);
+ std::cout << "Distance = " << df.get() << " meters\n";
+ std::cout << "There are "
+ << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter";
+ User1::meter mt = 1;
+ User1::mile mi = mt;
+ std::cout << " which is approximately " << mi.count() << '\n';
+ std::cout << "There are "
+ << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile";
+ mi = 1;
+ mt = mi;
+ std::cout << " which is approximately " << mt.count() << '\n';
+ User1::attosecond as(1);
+ User1::seconds sec = as;
+ std::cout << "1 attosecond is " << sec.count() << " seconds\n";
+ std::cout << "sec = as; // compiles\n";
+ sec = User1::seconds(1);
+ as = sec;
+ std::cout << "1 second is " << as.count() << " attoseconds\n";
+ std::cout << "as = sec; // compiles\n";
+ std::cout << "\n";
+ return 0;
+ }
+
+['See the source file [@../../example/si_physics.cpp example/si_physics.cpp]]
+
+[endsect]
+
+
+[endsect]
+
+[/================================]
+[section:ext_references External Resources]
+[/================================]
+
+[variablelist
+
+[
+ [[@http://www.open-std.org/jtc1/sc22/wg21 [*C++ Standards Committee's current Working Paper]]]
+ [The most authoritative reference material for the library is the C++ Standards Committee's current Working Paper (WP). 20.6 Compile-time rational arithmetic "ratio"]
+]
+
+[
+ [[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm [*N2661 - A Foundation to Sleep On]]]
+ [From Howard E. Hinnant, Walter E. Brown, Jeff Garland and Marc Paterno. Is very informative and provides motivation for key design decisions]
+]
+
+
+[
+ [[@http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#1281 [*LWG 1281. CopyConstruction and Assignment between ratios having the same normalized form]]]
+ [From Vicente Juan Botet Escriba.]
+]
+
+
+]
+
+[endsect]
+
+[endsect]
+
+[/=================]
+[section:reference Reference ]
+[/=================]
+
+[/===========================================]
+[section:ratio_fwdhpp Header `<boost/ratio_fwd.hpp>`]
+[/===========================================]
+
+This header provides forward declarations for the `<boost/ratio.hpp>` file.
+
+ namespace boost {
+
+ template <boost::intmax_t N, boost::intmax_t D = 1> class __ratio;
+
+ // ratio arithmetic
+ template <class R1, class R2> struct __ratio_add;
+ template <class R1, class R2> struct __ratio_subtract;
+ template <class R1, class R2> struct __ratio_multiply;
+ template <class R1, class R2> struct __ratio_divide;
+
+ // ratio comparison
+ template <class R1, class R2> struct __ratio_equal;
+ template <class R1, class R2> struct __ratio_not_equal;
+ template <class R1, class R2> struct __ratio_less;
+ template <class R1, class R2> struct __ratio_less_equal;
+ template <class R1, class R2> struct __ratio_greater;
+ template <class R1, class R2> struct __ratio_greater_equal;
+
+ // convenience SI typedefs
+ typedef ratio<1LL, 1000000000000000000LL> __atto;
+ typedef ratio<1LL, 1000000000000000LL> __femto;
+ typedef ratio<1LL, 1000000000000LL> __pico;
+ typedef ratio<1LL, 1000000000LL> __nano;
+ typedef ratio<1LL, 1000000LL> __micro;
+ typedef ratio<1LL, 1000LL> __milli;
+ typedef ratio<1LL, 100LL> __centi;
+ typedef ratio<1LL, 10LL> __deci;
+ typedef ratio< 10LL, 1LL> __deca;
+ typedef ratio< 100LL, 1LL> __hecto;
+ typedef ratio< 1000LL, 1LL> __kilo;
+ typedef ratio< 1000000LL, 1LL> __mega;
+ typedef ratio< 1000000000LL, 1LL> __giga;
+ typedef ratio< 1000000000000LL, 1LL> __tera;
+ typedef ratio< 1000000000000000LL, 1LL> __peta;
+ typedef ratio<1000000000000000000LL, 1LL> __exa;
+ }
+
+[endsect]
+
+[/===========================================]
+[section:ratio_hpp Header `<boost/ratio.hpp>`]
+[/===========================================]
+
+__ratio is a facility which is useful in specifying compile time rational constants. Compile time rational arithmetic is supported with protection against overflow and divide by zero. Such a facility is very handy when needing to efficiently represent 1/3 of a nanosecond, or specifying an inch in terms of meters (for example 254/10000 meters - which __ratio will reduce to 127/5000 meters).
+
+ // configuration macros
+ #define __BOOST_RATIO_USES_STATIC_ASSERT
+ #define __BOOST_RATIO_USES_MPL_ASSERT
+ #define __BOOST_RATIO_USES_ARRAY_ASSERT
+
+
+
+[section:conf Configuration Macros]
+
+When BOOST_NO_STATIC_ASSERT is defined, the user can select the way static assertions are reported. Define
+
+* BOOST_RATIO_USES_STATIC_ASSERT to use Boost.StaticAssert
+* BOOST_RATIO_USES_MPL_ASSERT to use Boost.MPL static assertions
+* BOOST_RATIO_USES_RATIO_ASSERT to use __Boost_Ratio__ static assertions
+
+The default behavior is as if BOOST_RATIO_USES_ARRAY_ASSERT is defined.
+
+
+When BOOST_RATIO_USES_MPL_ASSERT is not defined the following symbols are defined as shown:
+
+ #define BOOST_RATIO_OVERFLOW_IN_ADD "overflow in ratio add"
+ #define BOOST_RATIO_OVERFLOW_IN_SUB "overflow in ratio sub"
+ #define BOOST_RATIO_OVERFLOW_IN_MUL "overflow in ratio mul"
+ #define BOOST_RATIO_OVERFLOW_IN_DIV "overflow in ratio div"
+ #define BOOST_RATIO_NUMERATOR_IS_OUT_OF_RANGE "ratio numerator is out of range"
+ #define BOOST_RATIO_DIVIDE_BY_0 "ratio divide by 0"
+ #define BOOST_RATIO_DENOMINATOR_IS_OUT_OF_RANGE "ratio denominator is out of range"
+
+Depending upon the static assertion system used, a hint as to the failing assertion will appear in some form in the compiler diagnostic output.
+
+[endsect]
+
+[section:ratio Class Template `ratio<>`]
+
+ template <boost::intmax_t N, boost::intmax_t D>
+ class ratio {
+ public:
+ static const boost::intmax_t num;
+ static const boost::intmax_t den;
+ typedef ratio<num, den> type;
+
+ ratio() = default;
+
+ template <intmax_t _N2, intmax_t _D2>
+ ratio(const ratio<_N2, _D2>&);
+
+ template <intmax_t _N2, intmax_t _D2>
+ ratio& operator=(const ratio<_N2, _D2>&) {return *this;}
+ };
+
+A diagnostic will be emitted if __ratio is instantiated with `D == 0`, or if the absolute value of `N` or `D` can not be represented. [*Note:] These rules ensure that infinite ratios are avoided and that for any negative input, there exists a representable value of its absolute value which is positive. In a two's complement representation, this excludes the most negative value.
+
+The members num and den will be normalized values of the template arguments N and D computed as follows. Let `gcd` denote the greatest common divisor of `N`'s absolute value and of `D`'s absolute value. Then:
+
+* `num` has the value `sign(N)*sign(D)*abs(N)/gcd`.
+
+* `den` has the value `abs(D)/gcd`.
+
+The nested typedef `type` denotes the normalized form of this __ratio type. It should be
+used when the normalized form of the template arguments are required, since the arguments are not necessarily normalized.
+
+Two __ratio classes `__ratio<N1,D1>` and `__ratio<N2,D2>` have the same normalized form if `__ratio<N1,D1>::type` is the same type as `__ratio<N2,D2>::type`
+
+[section:ca Construction and Assignment]
+
+ template <intmax_t N2, intmax_t D2>
+ ratio(const __ratio<N2, D2>& r);
+
+[*Effects:] Constructs a __ratio object.
+
+[*Remarks:] This constructor will not participate in overload resolution unless `r` has the same normalized form as `*this`.
+
+ template <intmax_t N2, intmax_t D2>
+ __ratio& operator=(const __ratio<N2, D2>& r);
+
+[*Effects:] Assigns a __ratio object.
+
+[*Returns:] *this.
+
+[*Remarks:] This operator will not participate in overload resolution unless `r` has the same normalized form as `*this`.
+
+[endsect]
+
+
+[endsect]
+
+
+[section:ratio_arithmetic `ratio` Arithmetic]
+
+For each of the class templates in this section, each template parameter refers to a `ratio`. If the implementation is unable to form the indicated __ratio due to overflow, a diagnostic will be issued.
+
+[heading `ratio_add<>`]
+
+ template <class R1, class R2> struct ratio_add {
+ typedef [/see below] type;
+ };
+
+The nested typedef `type` is a synonym for `__ratio<R1::num * R2::den + R2::num * R1::den, R1::den * R2::den>::type`.
+
+[heading `ratio_subtract<>`]
+
+ template <class R1, class R2> struct ratio_subtract {
+ typedef [/see below] type;
+ };
+
+The nested typedef `type` is a synonym for `__ratio<R1::num * R2::den - R2::num * R1::den, R1::den * R2::den>::type`.
+
+[heading `ratio_multiply<>`]
+
+ template <class R1, class R2> struct ratio_multiply {
+ typedef [/see below] type;
+ };
+
+The nested typedef `type` is a synonym for `__ratio<R1::num * R2::num, R1::den * R2::den>::type`.
+
+[heading `ratio_divide<>`]
+
+ template <class R1, class R2> struct ratio_divide {
+ typedef [/see below] type;
+ };
+
+The nested typedef `type` is a synonym for `__ratio<R1::num * R2::den, R2::num * R1::den>::type`.
+
+[endsect]
+
+[section:ratio_comparison `ratio` Comparison]
+
+[heading `ratio_equal<>`]
+
+ template <class R1, class R2> struct ratio_equal
+ : public boost::integral_constant<bool, [/see below] > {};
+
+If R1::num == R2::num && R1::den == R2::den, ratio_equal derives from true_type, else derives from false_type.
+
+[heading `ratio_not_equal<>`]
+
+ template <class R1, class R2> struct ratio_not_equal
+ : public boost::integral_constant<bool, !ratio_equal<R1, R2>::value> {};
+
+[heading `ratio_less<>`]
+
+ template <class R1, class R2>
+ struct ratio_less
+ : public boost::integral_constant<bool, [/see below] > {};
+
+If R1::num * R2::den < R2::num * R1::den, ratio_less derives from true_type, else derives from false_type.
+
+[heading `ratio_less_equal<>`]
+
+ template <class R1, class R2> struct ratio_less_equal
+ : public boost::integral_constant<bool, !ratio_less<R2, R1>::value> {};
+
+[heading `ratio_greater<>`]
+
+ template <class R1, class R2> struct ratio_greater
+ : public boost::integral_constant<bool, ratio_less<R2, R1>::value> {};
+
+[heading `ratio_greater_equal<>`]
+
+ template <class R1, class R2> struct ratio_greater_equal
+ : public boost::integral_constant<bool, !ratio_less<R1, R2>::value> {};
+
+
+[endsect]
+
+[section:ratio_si_typedefs SI typedefs]
+
+The [@http://en.wikipedia.org/wiki/SI_prefix#List_of_SI_prefixes International System of Units] specifies twenty SI prefixes. __Boost_Ratio__ defines all except `yocto`, `zepto`, `zetta`, and `yotta`
+
+ // convenience SI typedefs
+ typedef __ratio<1LL, 1000000000000000000LL> atto;
+ typedef __ratio<1LL, 1000000000000000LL> femto;
+ typedef __ratio<1LL, 1000000000000LL> pico;
+ typedef __ratio<1LL, 1000000000LL> nano;
+ typedef __ratio<1LL, 1000000LL> micro;
+ typedef __ratio<1LL, 1000LL> milli;
+ typedef __ratio<1LL, 100LL> centi;
+ typedef __ratio<1LL, 10LL> deci;
+ typedef __ratio< 10LL, 1LL> deca;
+ typedef __ratio< 100LL, 1LL> hecto;
+ typedef __ratio< 1000LL, 1LL> kilo;
+ typedef __ratio< 1000000LL, 1LL> mega;
+ typedef __ratio< 1000000000LL, 1LL> giga;
+ typedef __ratio< 1000000000000LL, 1LL> tera;
+ typedef __ratio< 1000000000000000LL, 1LL> peta;
+ typedef __ratio<1000000000000000000LL, 1LL> exa;
+
+[endsect]
+
+
+[section:limitations Limitations and Extensions]
+
+The following are limitations of Boost.Ratio relative to the specification in the C++0x draft standard:
+
+* Four of the SI units typedefs -- `yocto`, `zepto`, `zetta`, and `yotta` -- are to be conditionally supported, if the range of `intmax_t` allows, but are not supported by __Boost_Ratio__.
+* Ratio values should be of type static `constexpr intmax_t` (see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3135.html#1121 Ratio values should be constexpr]), but no compiler supports `constexpr` today, so __Boost_Ratio__ uses `static const intmax_t` instead.
+* Rational arithmetic should use template aliases (see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3134.html#921 Rational Arithmetic should use template aliases]), but those are not available in C++03, so inheritance is used instead.
+
+The current implementation extends the requirements of the C++0x draft standard by making the copy constructor and copy assignment operator have the same normalized form (see [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3133.html#1281 copy constructor and assignment between ratios having the same normalized form]).
+
+[endsect]
+
+[endsect]
+
+[/===========================================]
+[section:ratio_io_hpp Header `<boost/ratio_io.hpp>`]
+[/===========================================]
+
+This header provides `ratio_string<>` which can generate a textual representation of a `ratio<>` in the form of a `std::basic_string<>`. These strings can be useful for I/O."
+
+ namespace boost {
+
+ template <class Ratio, class CharT>
+ struct ratio_string
+ {
+ static std::basic_string<CharT> short_name();
+ static std::basic_string<CharT> long_name();
+ };
+
+ }
+
+[endsect]
+[endsect]
+
+
+[/=================]
+[section Appendices]
+[/=================]
+[/==================================]
+[section:history Appendix A: History]
+[/==================================]
+
+[section [*Version 1.0.0, ?? ??, 2010] ]
+[endsect]
+
+[/
+[section [*Version 0.2.1, September 27, 2010] ]
+
+[*Fixes:]
+
+* Removal of LLVM adapted files due to incompatible License issue.
+
+[endsect]
+
+[section [*Version 0.2.0, September 22, 2010] ]
+
+[*Featurs:]
+
+* Added ratio_string traits.
+
+[*Fixes:]
+
+* ratio_less overflow avoided following the algorithm from libc++.
+
+[*Test:]
+
+* A more complete test has been included adapted from the test of from libc++/ratio.
+
+[endsect]
+
+[section [*Version 0.1.0, September 10, 2010] ]
+
+[*Features:]
+
+* Ratio has been extracted from Boost.Chrono.
+
+[endsect]
+
+]
+
+[endsect]
+
+[/======================================]
+[section:rationale Appendix B: Rationale]
+
+[heading Why ratio needs CopyConstruction and Assignment from ratios having the same normalized form]
+
+Current [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf [*N3000]] doesn't allows to copy-construct or assign ratio instances of ratio classes having the same normalized form.
+
+This simple example
+
+ __ratio<1,3> r1;
+ __ratio<3,9> r2;
+ r1 = r2; // (1)
+
+fails to compile in (1). Other example
+
+ __ratio<1,3> r1;
+ __ratio_subtract<__ratio<2,3>,__ratio<1,3> > r2=r1; // (2)
+
+The type of `__ratio_subtract<__ratio<2,3>,__ratio<1,3> >` could be `__ratio<3,9>` so the compilation could fail in (2). It could also be __ratio<1,3> and the compilation succeeds.
+
+[heading Why ratio needs the nested normalizer typedef type]
+
+The current resolution of issue LWG 1281 acknowledges the need for a nested type typedef, so Boost.Ratio is tracking the likely final version of std::ratio.
+
+[endsect]
+
+[/======================================================]
+[section:implementation Appendix C: Implementation Notes]
+
+[heading How Boost.Ratio manage with compile-time rational arithmetic overflow?]
+
+When the result is representable, but a simple application of arithmetic rules would result in overflow, e.g. `ratio_multiply<ratio<INTMAX_MAX,2>,ratio<2,INTMAX_MAX>>` can be reduced to `ratio<1,1>`, but the direct result of `ratio<INTMAX_MAX*2,INTMAX_MAX*2>` would result in overflow.
+
+Boost.Ratio implementes some simplifications in order to reduce the possibility of overflow. The general ideas are:
+
+* The `num` and `den` `ratio<>` fields are normalized.
+* Use the gcd of some of the possible products that can overflow, and simplify before doing the product.
+* Use some equivalences relations that avoid addition or subtraction that can overflow or underflow.
+
+The following subsections cover each case in more detail.
+
+[*ratio_add]
+
+In
+
+ (n1/d1)+(n2/d2)=(n1*d2+n2*d1)/(d1*d2)
+
+either n1*d2+n2*d1 or d1*d2 can overflow.
+
+ ( (n1 * d2) + (n2 * d1) )
+ --------------------------
+ (d1 * d2)
+
+Dividing by gcd(d1,d2) on both num and den
+
+ ( (n1 * (d2/gcd(d1,d2))) + (n2 * (d1/gcd(d1,d2))) )
+ ----------------------------------------------------
+ ((d1 * d2) / gcd(d1,d2))
+
+
+Multipliying and diving by gcd(n1,n2) in numerator
+
+ ( ((gcd(n1,n2)*(n1/gcd(n1,n2))) * (d2/gcd(d1,d2))) +
+ ((gcd(n1,n2)*(n2/gcd(n1,n2))) * (d1/gcd(d1,d2)))
+ )
+ --------------------------------------------------
+ ( (d1 * d2) / gcd(d1,d2) )
+
+Factorizing gcd(n1,n2)
+
+ ( gcd(n1,n2) *
+ ( ((n1/gcd(n1,n2)) * (d2/gcd(d1,d2))) + ((n2/gcd(n1,n2)) * (d1/gcd(d1,d2))) )
+ )
+ -------------------------------------------------------------------------------
+ ( (d1 * d2) / gcd(d1,d2) )
+
+Regrouping
+
+ ( gcd(n1,n2) *
+ ( ((n1/gcd(n1,n2)) * (d2/gcd(d1,d2))) + ((n2/gcd(n1,n2)) * (d1/gcd(d1,d2))) )
+ )
+ -------------------------------------------------------------------------------
+ ( (d1 / gcd(d1,d2)) * d2 )
+
+Dividing by (d1 / gcd(d1,d2))
+
+ ( ( gcd(n1,n2) / (d1 / gcd(d1,d2)) ) *
+ ( ((n1/gcd(n1,n2)) * (d2/gcd(d1,d2))) + ((n2/gcd(n1,n2)) * (d1/gcd(d1,d2))) )
+ )
+ -------------------------------------------------------------------------------
+ d2
+
+
+Dividing by d2
+
+ ( gcd(n1,n2) / (d1 / gcd(d1,d2)) ) *
+ ( ((n1/gcd(n1,n2)) * (d2/gcd(d1,d2))) + ((n2/gcd(n1,n2)) * (d1/gcd(d1,d2))) / d2 )
+
+This expression correspond to the multiply of two ratios that have less risk of overflow as the initial numerators and denomitators appear now in most of the cases divided by a gcd.
+
+
+For ratio_subtract the reasoning is the same
+
+[*ratio_multiply]
+
+In
+
+ (n1/d1)*(n2/d2)=((n1*n2)/(d1*d2))
+
+either n1*n2 or d1*d2 can overflow.
+
+Dividing by gcc(n1,d2) numerator and denominator
+
+ (((n1/gcc(n1,d2))*n2)
+ ---------------------
+ (d1*(d2/gcc(n1,d2))))
+
+Dividing by gcc(n2,d1)
+
+ ((n1/gcc(n1,d2))*(n2/gcc(n2,d1)))
+ ---------------------------------
+ ((d1/gcc(n2,d1))*(d2/gcc(n1,d2)))
+
+And now all the initial numerator and denominators have been reduced, avoiding the overflow.
+
+For ratio_divide the reasoning is similar.
+
+[*ratio_less]
+
+In order to evaluate
+
+ (n1/d1)<(n2/d2)
+
+without moving to floating point numbers, two techniques are used:
+
+* First compare the sign of the numerators
+
+If sign(n1) < sign(n2) the result is true.
+
+If sign(n1) == sign(n2) the result depends on the following after making the numerators positive
+
+* When the sign is equal the technique used is to work with integer division and modulo when the signs are equal.
+
+Let call Qi the integer division of ni and di and Mi the modulo of ni and di.
+
+ ni = Qi * di + Mi and Mi < di
+
+Form
+
+ ((n1*d2)<(d1*n2))
+
+we get
+
+ (((Q1 * d1 + M1)*d2)<(d1*((Q2 * d2 + M2))))
+
+Developing
+
+ ((Q1 * d1 * d2)+ (M1*d2))<((d1 * Q2 * d2) + (d1*M2))
+
+Dividing by d1*d2
+
+ Q1 + (M1/d1) < Q2 + (M2/d2)
+
+If Q1=Q2 the result depends on
+
+ (M1/d1) < (M2/d2)
+
+If M1==0==M2 the result is false
+
+If M1=0 M2!=0 the result is true
+
+If M1!=0 M2==0 the result is false
+
+If M1!=0 M2!=0 the result depends on
+
+ (d2/M2) < (d1/M1)
+
+If Q1!=Q2, the result of
+
+ Q1 + (M1/d1) < Q2 + (M2/d2)
+
+depends only on Q1 and Q2 as Qi are integers and (Mi/di) <1 because Mi<di.
+
+if Q1>Q2, Q1==Q2+k, k>=1
+
+ Q2+k + (M1/d1) < Q2 + (M2/d2)
+ k + (M1/d1) < (M2/d2)
+ k < (M2/d2) - (M1/d1)
+
+but the difference between two numbers between 0 and 1 can not be greater than 1, so the result is false.
+
+if Q2>Q1, Q2==Q1+k, k>=1
+
+ Q1 + (M1/d1) < Q1+k + (M2/d2)
+ (M1/d1) < k + (M2/d2)
+ (M1/d1) - (M2/d2) < k
+
+which is always true, so the result is true.
+
+The following table recapitulates this analisys
+
+[table
+ [[ratio<n1,d1>][ratio<n2,d2>] [Q1] [Q2] [M1] [M2] [Result]]
+ [[ratio<n1,d1>][ratio<n2,d2>] [Q1] [Q2] [!=0] [!=0] [Q1 < Q2]]
+ [[ratio<n1,d1>][ratio<n2,d2>] [Q] [Q] [0] [0] [false]]
+ [[ratio<n1,d1>][ratio<n2,d2>] [Q] [Q] [0] [!=0] [true]]
+ [[ratio<n1,d1>][ratio<n2,d2>] [Q] [Q] [!=0] [0] [false]]
+ [[ratio<n1,d1>][ratio<n2,d2>] [Q] [Q] [!=0] [!=0] [ratio_less<ratio<d2,M2>, ratio<d1/M1>>]]
+]
+
+
+
+[endsect]
+
+[/======================================================]
+[section:faq Appendix D: FAQ]
+
+
+[endsect]
+
+[/====================================================]
+[section:acknowledgements Appendix E: Acknowledgements]
+
+The library's code was derived from Howard Hinnant's time2_demo prototype. Many thanks to Howard for making his code available under the Boost license. The original code was modified by Beman Dawes to conform to Boost conventions.
+
+time2_demo contained this comment:
+
+Much thanks to Andrei Alexandrescu, Walter Brown, Peter Dimov, Jeff Garland, Terry Golubiewski, Daniel Krugler, Anthony Williams.
+
+The ratio.hpp source has been adapted from the experimental header `<ratio_io>` from Howard Hinnant.
+
+Thanks to Adrew Chinnoff for his help polishing the documentation.
+
+[endsect]
+
+[/
+[/====================================================]
+[section:tests Appendix F: Tests]
+
+In order to test you need to do.
+
+ bjam libs/ratio/test
+
+You can also run a specific suite of test by doing
+
+ cd libs/chrono/test
+ bjam ratio
+
+
+[section `ratio`]
+[table
+ [[Name] [kind] [Description] [Result] [Ticket]]
+ [[typedefs.pass] [run] [check the num/den are correct for the predefined typedefs] [Pass] [#]]
+ [[ratio.pass] [run] [check the num/den are correctly simplified] [Pass] [#]]
+ [[ratio1.fail] [compile-fails] [The template argument D shall not be zero] [Pass] [#]]
+ [[ratio2.fail] [compile-fails] [the absolute values of the template arguments N and D shall be representable by type intmax_t] [Pass] [#]]
+ [[ratio3.fail] [compile-fails] [the absolute values of the template arguments N and D shall be representable by type intmax_t] [Pass] [#]]
+]
+[endsect]
+
+[section `comparison`]
+[table
+ [[Name] [kind] [Description] [Result] [Ticket]]
+ [[ratio_equal.pass] [run] [check ratio_equal metafunction class] [Pass] [#]]
+ [[ratio_not_equal.pass] [run] [check ratio_not_equal metafunction class] [Pass] [#]]
+ [[ratio_less.pass] [run] [check ratio_less metafunction class] [Pass] [#]]
+ [[ratio_less_equal.pass] [run] [check ratio_less_equal metafunction class] [Pass] [#]]
+ [[ratio_greater.pass] [run] [check ratio_greater metafunction class] [Pass] [#]]
+ [[ratio_greater_equal.pass] [run] [check ratio_greater_equal metafunction class] [Pass] [#]]
+]
+[endsect]
+
+[section `arithmetic`]
+[table
+ [[Name] [kind] [Description] [Result] [Ticket]]
+ [[ratio_add.pass] [run] [check ratio_add metafunction class] [Pass] [#]]
+ [[ratio_subtract.pass] [run] [check ratio_subtract metafunction class] [Pass] [#]]
+ [[ratio_multiply.pass] [run] [check ratio_multiply metafunction class] [Pass] [#]]
+ [[ratio_divide.pass] [run] [check ratio_divide metafunction class] [Pass] [#]]
+ [[ratio_add.fail] [compile-fails] [check ratio_add overflow metafunction class] [Pass] [#]]
+ [[ratio_subtract.fail] [compile-fails] [check ratio_subtract underflow metafunction class] [Pass] [#]]
+ [[ratio_multiply.fail] [compile-fails] [check ratio_multiply overflow metafunction class] [Pass] [#]]
+ [[ratio_divide.fail] [compile-fails] [check ratio_divide overflow metafunction class] [Pass] [#]]
+]
+[endsect]
+
+
+[endsect]
+[/=====================================]
+[section:tickets Appendix G: Tickets]
+
+[table
+ [[Ticket] [Description] [Resolution] [State]]
+ [[1] [result of metafunctions ratio_multiply and ratio_divide were not normalized ratios] [Use of the nested ratio typedef type on ratio arithmetic operations.] [Closed]]
+ [[2] [INTMAX_C is not always defined] [Replace INTMAX_C by BOOST_INTMAX_C until boost/cstdint.hpp ensures INTMAX_C is always defined.] [Closed]]
+
+ [[3] [MSVC reports a warning instead of an error when there is an integral constant overflow] [manage with MSVC reporting a warning instead of an error when there is an integral constant overflow] [Closed]]
+ [[4] [ration_less overflow on cases where it can be avoided] [Change the algorithm as implemented in libc++] [Closed]]
+ [/[#] [XXXX] [XXXX] [Closed]]
+]
+
+
+[endsect]
+
+]
+[/=====================================]
+[section:todo Appendix F: Future Plans]
+[/=====================================]
+
+[heading For later releases]
+
+* Use constexpr on compilers providing it
+* Use template aliases on compiler providing it
+* Implement [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3135.html#3135 multiple arguments] ratio arithmetic.
+
+[endsect]
+
+[endsect]
Added: trunk/libs/ratio/example/config.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/config.hpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,123 @@
+// boost/chrono/config.hpp -------------------------------------------------//
+
+// Copyright Beman Dawes 2003, 2006, 2008
+// Copyright 2009 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// See http://www.boost.org/libs/chrono for documentation.
+
+#ifndef BOOST_EX_CHRONO_CONFIG_HPP
+#define BOOST_EX_CHRONO_CONFIG_HPP
+
+#include <boost/config.hpp>
+
+// BOOST_EX_CHRONO_POSIX_API, BOOST_EX_CHRONO_MAC_API, or BOOST_EX_CHRONO_WINDOWS_API
+// can be defined by the user to specify which API should be used
+
+#if defined(BOOST_EX_CHRONO_WINDOWS_API)
+# warning Boost.Chrono will use the Windows API
+#elif defined(BOOST_EX_CHRONO_MAC_API)
+# warning Boost.Chrono will use the Mac API
+#elif defined(BOOST_EX_CHRONO_POSIX_API)
+# warning Boost.Chrono will use the POSIX API
+#endif
+
+# if defined( BOOST_EX_CHRONO_WINDOWS_API ) && defined( BOOST_EX_CHRONO_POSIX_API )
+# error both BOOST_EX_CHRONO_WINDOWS_API and BOOST_EX_CHRONO_POSIX_API are defined
+# elif defined( BOOST_EX_CHRONO_WINDOWS_API ) && defined( BOOST_EX_CHRONO_MAC_API )
+# error both BOOST_EX_CHRONO_WINDOWS_API and BOOST_EX_CHRONO_MAC_API are defined
+# elif defined( BOOST_EX_CHRONO_MAC_API ) && defined( BOOST_EX_CHRONO_POSIX_API )
+# error both BOOST_EX_CHRONO_MAC_API and BOOST_EX_CHRONO_POSIX_API are defined
+# elif !defined( BOOST_EX_CHRONO_WINDOWS_API ) && !defined( BOOST_EX_CHRONO_MAC_API ) && !defined( BOOST_EX_CHRONO_POSIX_API )
+# if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
+# define BOOST_EX_CHRONO_WINDOWS_API
+# define BOOST_EX_CHRONO_HAS_CLOCK_MONOTONIC
+# define BOOST_EX_CHRONO_HAS_THREAD_CLOCK
+# define BOOST_EX_CHRONO_THREAD_CLOCK_IS_MONOTONIC true
+# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
+# define BOOST_EX_CHRONO_MAC_API
+# define BOOST_EX_CHRONO_HAS_CLOCK_MONOTONIC
+# define BOOST_EX_CHRONO_THREAD_CLOCK_IS_MONOTONIC true
+# else
+# define BOOST_EX_CHRONO_POSIX_API
+# endif
+# endif
+
+# if defined( BOOST_EX_CHRONO_POSIX_API )
+# include <time.h> //to check for CLOCK_REALTIME and CLOCK_MONOTONIC and _POSIX_THREAD_CPUTIME
+# if defined(CLOCK_REALTIME)
+# if defined(CLOCK_MONOTONIC)
+# define BOOST_EX_CHRONO_HAS_CLOCK_MONOTONIC
+# endif
+# else
+# error <time.h> does not supply CLOCK_REALTIME
+# endif
+# if defined(_POSIX_THREAD_CPUTIME)
+# define BOOST_EX_CHRONO_HAS_THREAD_CLOCK
+# define BOOST_EX_CHRONO_THREAD_CLOCK_IS_MONOTONIC true
+# endif
+# endif
+
+
+
+// enable dynamic linking on Windows ---------------------------------------//
+
+//# if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_EX_CHRONO_DYN_LINK)) && defined(__BORLANDC__) && defined(__WIN32__)
+//# error Dynamic linking Boost.System does not work for Borland; use static linking instead
+//# endif
+
+#ifdef BOOST_HAS_DECLSPEC // defined by boost.config
+// we need to import/export our code only if the user has specifically
+// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
+// libraries to be dynamically linked, or BOOST_EX_CHRONO_DYN_LINK
+// if they want just this one to be dynamically liked:
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_EX_CHRONO_DYN_LINK)
+// export if this is our own source, otherwise import:
+#ifdef BOOST_EX_CHRONO_SOURCE
+# define BOOST_EX_CHRONO_DECL __declspec(dllexport)
+#else
+# define BOOST_EX_CHRONO_DECL __declspec(dllimport)
+#endif // BOOST_EX_CHRONO_SOURCE
+#endif // DYN_LINK
+#endif // BOOST_HAS_DECLSPEC
+//
+// if BOOST_EX_CHRONO_DECL isn't defined yet define it now:
+#ifndef BOOST_EX_CHRONO_DECL
+#define BOOST_EX_CHRONO_DECL
+#endif
+
+// define constexpr related macros ------------------------------//
+
+//~ #include <boost/config.hpp>
+#if defined(BOOST_NO_CONSTEXPR)
+#define BOOST_EX_CHRONO_CONSTEXPR
+#define BOOST_EX_CHRONO_CONST_REF const&
+#else
+#define BOOST_EX_CHRONO_CONSTEXPR constexpr
+#define BOOST_EX_CHRONO_CONST_REF
+#endif
+
+// enable automatic library variant selection ------------------------------//
+
+#if !defined(BOOST_EX_CHRONO_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_EX_CHRONO_NO_LIB)
+//
+// Set the name of our library; this will get undef'ed by auto_link.hpp
+// once it's done with it:
+//
+#define BOOST_LIB_NAME boost_chrono
+//
+// If we're importing code from a dll, then tell auto_link.hpp about it:
+//
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_EX_CHRONO_DYN_LINK)
+# define BOOST_DYN_LINK
+#endif
+//
+// And include the header that does the work:
+//
+#include <boost/config/auto_link.hpp>
+#endif // auto-linking disabled
+
+#endif // BOOST_EX_CHRONO_CONFIG_HPP
+
Added: trunk/libs/ratio/example/display_ex.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/display_ex.cpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,39 @@
+// io_ex2.cpp ----------------------------------------------------------//
+
+// Copyright 2010 Howard Hinnant
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+/*
+This code was adapted by Vicente J. Botet Escriba from Hinnant's html documentation.
+Many thanks to Howard for making his code available under the Boost license.
+*/
+
+#include <iostream>
+#include <boost/ratio/ratio_io.hpp>
+
+int main()
+{
+ using namespace std;
+ using namespace boost;
+
+ cout << "ratio_string<deca, char>::long_name() = "
+ << ratio_string<deca, char>::long_name() << '\n';
+ cout << "ratio_string<deca, char>::short_name() = "
+ << ratio_string<deca, char>::short_name() << '\n';
+
+ cout << "ratio_string<giga, char>::long_name() = "
+ << ratio_string<giga, char>::long_name() << '\n';
+ cout << "ratio_string<giga, char>::short_name() = "
+ << ratio_string<giga, char>::short_name() << '\n';
+
+ cout << "ratio_string<ratio<4, 6>, char>::long_name() = "
+ << ratio_string<ratio<4, 6>, char>::long_name() << '\n';
+ cout << "ratio_string<ratio<4, 6>, char>::short_name() = "
+ << ratio_string<ratio<4, 6>, char>::short_name() << '\n';
+
+ return 0;
+}
+
Added: trunk/libs/ratio/example/duration.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/duration.hpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,793 @@
+// duration.hpp --------------------------------------------------------------//
+
+// Copyright 2008 Howard Hinnant
+// Copyright 2008 Beman Dawes
+// Copyright 2009-2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+/*
+
+This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
+Many thanks to Howard for making his code available under the Boost license.
+The original code was modified to conform to Boost conventions and to section
+20.9 Time utilities [time] of the C++ committee's working paper N2798.
+See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
+
+time2_demo contained this comment:
+
+ Much thanks to Andrei Alexandrescu,
+ Walter Brown,
+ Peter Dimov,
+ Jeff Garland,
+ Terry Golubiewski,
+ Daniel Krugler,
+ Anthony Williams.
+*/
+
+
+#ifndef BOOST_EX_CHRONO_DURATION_HPP
+#define BOOST_EX_CHRONO_DURATION_HPP
+
+#include "config.hpp"
+#include "static_assert.hpp"
+
+//~ #include <iostream>
+
+#include <climits>
+#include <limits>
+
+
+#include <boost/mpl/logical.hpp>
+#include <boost/ratio.hpp>
+#include "type_traits/common_type.hpp"
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_floating_point.hpp>
+#include <boost/type_traits/is_unsigned.hpp>
+
+#include <boost/cstdint.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/integer_traits.hpp>
+
+#if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_EX_CHRONO_USES_MPL_ASSERT)
+#define BOOST_EX_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION "A duration representation can not be a duration"
+#define BOOST_EX_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO "Second template parameter of duration must be a boost::ratio"
+#define BOOST_EX_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE "duration period must be positive"
+#define BOOST_EX_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_TIME_POINT_MUST_BE_A_BOOST_EX_CHRONO_DURATION "Second template parameter of time_point must be a boost_ex::chrono::duration"
+#endif
+
+
+//----------------------------------------------------------------------------//
+// //
+// 20.9 Time utilities [time] //
+// synopsis //
+// //
+//----------------------------------------------------------------------------//
+
+namespace boost_ex {
+ using boost::ratio;
+
+namespace chrono {
+
+ template <class Rep, class Period = ratio<1> >
+ class duration;
+
+ namespace detail
+ {
+ template <class T>
+ struct is_duration
+ : boost::false_type {};
+
+ template <class Rep, class Period>
+ struct is_duration<duration<Rep, Period> >
+ : boost::true_type {};
+ //template <class T>
+ // struct is_duration
+ // : is_duration<typename boost::remove_cv<T>::type> {};
+
+ template <class Duration, class Rep, bool = is_duration<Rep>::value>
+ struct duration_divide_result
+ {
+ };
+
+ template <class Duration, class Rep2,
+ bool = (
+ (boost::is_convertible<typename Duration::rep,
+ typename common_type<typename Duration::rep, Rep2>::type>::value)
+ && (boost::is_convertible<Rep2,
+ typename common_type<typename Duration::rep, Rep2>::type>::value)
+ )
+ >
+ struct duration_divide_imp
+ {
+ };
+
+ template <class Rep1, class Period, class Rep2>
+ struct duration_divide_imp<duration<Rep1, Period>, Rep2, true>
+ {
+ typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
+ };
+
+ template <class Rep1, class Period, class Rep2>
+ struct duration_divide_result<duration<Rep1, Period>, Rep2, false>
+ : duration_divide_imp<duration<Rep1, Period>, Rep2>
+ {
+ };
+
+///
+ template <class Rep, class Duration, bool = is_duration<Rep>::value>
+ struct duration_divide_result2
+ {
+ };
+
+ template <class Rep, class Duration,
+ bool = (
+ (boost::is_convertible<typename Duration::rep,
+ typename common_type<typename Duration::rep, Rep>::type>::value)
+ && (boost::is_convertible<Rep,
+ typename common_type<typename Duration::rep, Rep>::type>::value)
+ )
+ >
+ struct duration_divide_imp2
+ {
+ };
+
+ template <class Rep1, class Rep2, class Period >
+ struct duration_divide_imp2<Rep1, duration<Rep2, Period>, true>
+ {
+ //typedef typename common_type<Rep1, Rep2>::type type;
+ typedef double type;
+ };
+
+ template <class Rep1, class Rep2, class Period >
+ struct duration_divide_result2<Rep1, duration<Rep2, Period>, false>
+ : duration_divide_imp2<Rep1, duration<Rep2, Period> >
+ {
+ };
+
+///
+ template <class Duration, class Rep, bool = is_duration<Rep>::value>
+ struct duration_modulo_result
+ {
+ };
+
+ template <class Duration, class Rep2,
+ bool = (
+ //boost::is_convertible<typename Duration::rep,
+ //typename common_type<typename Duration::rep, Rep2>::type>::value
+ //&&
+ boost::is_convertible<Rep2,
+ typename common_type<typename Duration::rep, Rep2>::type>::value
+ )
+ >
+ struct duration_modulo_imp
+ {
+ };
+
+ template <class Rep1, class Period, class Rep2>
+ struct duration_modulo_imp<duration<Rep1, Period>, Rep2, true>
+ {
+ typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
+ };
+
+ template <class Rep1, class Period, class Rep2>
+ struct duration_modulo_result<duration<Rep1, Period>, Rep2, false>
+ : duration_modulo_imp<duration<Rep1, Period>, Rep2>
+ {
+ };
+
+ } // namespace detail
+} // namespace chrono
+
+
+// common_type trait specializations
+
+template <class Rep1, class Period1, class Rep2, class Period2>
+ struct common_type<chrono::duration<Rep1, Period1>,
+ chrono::duration<Rep2, Period2> >;
+
+
+namespace chrono {
+
+ // customization traits
+ template <class Rep> struct treat_as_floating_point;
+ template <class Rep> struct duration_values;
+
+ // duration arithmetic
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
+// operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
+// operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+// template <class Rep1, class Period, class Rep2>
+// typename boost::enable_if_c
+// <
+// boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value
+// && boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value,
+// duration<typename common_type<Rep1, Rep2>::type, Period>
+// >::type
+// operator*(const duration<Rep1, Period>& d, const Rep2& s);
+// template <class Rep1, class Period, class Rep2>
+// typename boost::enable_if_c
+// <
+// boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value
+// && boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value,
+// duration<typename common_type<Rep1, Rep2>::type, Period>
+// >::type
+// operator*(const Rep1& s, const duration<Rep2, Period>& d);
+
+// template <class Rep1, class Period, class Rep2>
+// typename boost::disable_if <detail::is_duration<Rep2>,
+// typename detail::duration_divide_result<duration<Rep1, Period>, Rep2>::type
+// >::type
+// operator/(const duration<Rep1, Period>& d, const Rep2& s);
+
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// typename common_type<Rep1, Rep2>::type
+// operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+
+ // duration comparisons
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+// template <class Rep1, class Period1, class Rep2, class Period2>
+// bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
+
+ // duration_cast
+
+ //template <class ToDuration, class Rep, class Period>
+ // ToDuration duration_cast(const duration<Rep, Period>& d);
+
+ // convenience typedefs
+ typedef duration<boost::int_least64_t, boost::nano> nanoseconds; // at least 64 bits needed
+ typedef duration<boost::int_least64_t, boost::micro> microseconds; // at least 55 bits needed
+ typedef duration<boost::int_least64_t, boost::milli> milliseconds; // at least 45 bits needed
+ typedef duration<boost::int_least64_t> seconds; // at least 35 bits needed
+ typedef duration<boost::int_least32_t, ratio< 60> > minutes; // at least 29 bits needed
+ typedef duration<boost::int_least32_t, ratio<3600> > hours; // at least 23 bits needed
+
+//----------------------------------------------------------------------------//
+// duration helpers //
+//----------------------------------------------------------------------------//
+
+ namespace detail
+ {
+
+ // duration_cast
+
+ // duration_cast is the heart of this whole prototype. It can convert any
+ // duration to any other. It is also (implicitly) used in converting
+ // time_points. The conversion is always exact if possible. And it is
+ // always as efficient as hand written code. If different representations
+ // are involved, care is taken to never require implicit conversions.
+ // Instead static_cast is used explicitly for every required conversion.
+ // If there are a mixture of integral and floating point representations,
+ // the use of common_type ensures that the most logical "intermediate"
+ // representation is used.
+ template <class FromDuration, class ToDuration,
+ class Period = typename boost::ratio_divide<typename FromDuration::period,
+ typename ToDuration::period>::type,
+ bool = Period::num == 1,
+ bool = Period::den == 1>
+ struct duration_cast;
+
+ // When the two periods are the same, all that is left to do is static_cast from
+ // the source representation to the target representation (which may be a no-op).
+ // This conversion is always exact as long as the static_cast from the source
+ // representation to the destination representation is exact.
+ template <class FromDuration, class ToDuration, class Period>
+ struct duration_cast<FromDuration, ToDuration, Period, true, true>
+ {
+ ToDuration operator()(const FromDuration& fd) const
+ {
+ return ToDuration(static_cast<typename ToDuration::rep>(fd.count()));
+ }
+ };
+
+ // When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is
+ // divide by the denominator of FromPeriod / ToPeriod. The common_type of
+ // the two representations is used for the intermediate computation before
+ // static_cast'ing to the destination.
+ // This conversion is generally not exact because of the division (but could be
+ // if you get lucky on the run time value of fd.count()).
+ template <class FromDuration, class ToDuration, class Period>
+ struct duration_cast<FromDuration, ToDuration, Period, true, false>
+ {
+ ToDuration operator()(const FromDuration& fd) const
+ {
+ typedef typename common_type<
+ typename ToDuration::rep,
+ typename FromDuration::rep,
+ intmax_t>::type C;
+ return ToDuration(static_cast<typename ToDuration::rep>(
+ static_cast<C>(fd.count()) / static_cast<C>(Period::den)));
+ }
+ };
+
+ // When the denomenator of FromPeriod / ToPeriod is 1, then all we need to do is
+ // multiply by the numerator of FromPeriod / ToPeriod. The common_type of
+ // the two representations is used for the intermediate computation before
+ // static_cast'ing to the destination.
+ // This conversion is always exact as long as the static_cast's involved are exact.
+ template <class FromDuration, class ToDuration, class Period>
+ struct duration_cast<FromDuration, ToDuration, Period, false, true>
+ {
+ ToDuration operator()(const FromDuration& fd) const
+ {
+ typedef typename common_type<
+ typename ToDuration::rep,
+ typename FromDuration::rep,
+ intmax_t>::type C;
+ return ToDuration(static_cast<typename ToDuration::rep>(
+ static_cast<C>(fd.count()) * static_cast<C>(Period::num)));
+ }
+ };
+
+ // When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to
+ // multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod. The
+ // common_type of the two representations is used for the intermediate computation before
+ // static_cast'ing to the destination.
+ // This conversion is generally not exact because of the division (but could be
+ // if you get lucky on the run time value of fd.count()).
+ template <class FromDuration, class ToDuration, class Period>
+ struct duration_cast<FromDuration, ToDuration, Period, false, false>
+ {
+ ToDuration operator()(const FromDuration& fd) const
+ {
+ typedef typename common_type<
+ typename ToDuration::rep,
+ typename FromDuration::rep,
+ intmax_t>::type C;
+ return ToDuration(static_cast<typename ToDuration::rep>(
+ static_cast<C>(fd.count()) * static_cast<C>(Period::num)
+ / static_cast<C>(Period::den)));
+ }
+ };
+
+ } // namespace detail
+
+//----------------------------------------------------------------------------//
+// //
+// 20.9.2 Time-related traits [time.traits] //
+// //
+//----------------------------------------------------------------------------//
+//----------------------------------------------------------------------------//
+// 20.9.2.1 treat_as_floating_point [time.traits.is_fp] //
+// Probably should have been treat_as_floating_point. Editor notifed. //
+//----------------------------------------------------------------------------//
+
+ // Support bidirectional (non-exact) conversions for floating point rep types
+ // (or user defined rep types which specialize treat_as_floating_point).
+ template <class Rep>
+ struct treat_as_floating_point : boost::is_floating_point<Rep> {};
+
+//----------------------------------------------------------------------------//
+// 20.9.2.2 duration_values [time.traits.duration_values] //
+//----------------------------------------------------------------------------//
+
+ namespace detail {
+ template <class T, bool = boost::is_arithmetic<T>::value>
+ struct chrono_numeric_limits {
+ static T lowest() throw() {return (std::numeric_limits<T>::min) ();}
+ };
+
+ template <class T>
+ struct chrono_numeric_limits<T,true> {
+ static T lowest() throw() {return (std::numeric_limits<T>::min) ();}
+ };
+
+ template <>
+ struct chrono_numeric_limits<float,true> {
+ static float lowest() throw() {return -(std::numeric_limits<float>::max) ();}
+ };
+
+ template <>
+ struct chrono_numeric_limits<double,true> {
+ static double lowest() throw() {return -(std::numeric_limits<double>::max) ();}
+ };
+
+ template <>
+ struct chrono_numeric_limits<long double,true> {
+ static long double lowest() throw() {return -(std::numeric_limits<long double>::max)();}
+ };
+
+ template <class T>
+ struct numeric_limits : chrono_numeric_limits<typename boost::remove_cv<T>::type> {};
+
+ }
+ template <class Rep>
+ struct duration_values
+ {
+ static Rep zero() {return Rep(0);}
+ static Rep max BOOST_PREVENT_MACRO_SUBSTITUTION () {return (std::numeric_limits<Rep>::max)();}
+
+ static Rep min BOOST_PREVENT_MACRO_SUBSTITUTION () {return detail::numeric_limits<Rep>::lowest();}
+ };
+
+} // namespace chrono
+
+//----------------------------------------------------------------------------//
+// 20.9.2.3 Specializations of common_type [time.traits.specializations] //
+//----------------------------------------------------------------------------//
+
+template <class Rep1, class Period1, class Rep2, class Period2>
+struct common_type<chrono::duration<Rep1, Period1>,
+ chrono::duration<Rep2, Period2> >
+{
+ typedef chrono::duration<typename common_type<Rep1, Rep2>::type,
+ typename boost::ratio_gcd<Period1, Period2>::type> type;
+};
+
+
+//----------------------------------------------------------------------------//
+// //
+// 20.9.3 Class template duration [time.duration] //
+// //
+//----------------------------------------------------------------------------//
+
+
+namespace chrono {
+
+ template <class Rep, class Period>
+ class duration
+ {
+ BOOST_EX_CHRONO_STATIC_ASSERT(!boost_ex::chrono::detail::is_duration<Rep>::value, BOOST_EX_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION, ());
+ BOOST_EX_CHRONO_STATIC_ASSERT(boost::ratio_detail::is_ratio<Period>::value, BOOST_EX_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO, ());
+ BOOST_EX_CHRONO_STATIC_ASSERT(Period::num>0, BOOST_EX_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE, ());
+ public:
+ typedef Rep rep;
+ typedef Period period;
+ private:
+ rep rep_;
+ public:
+
+ duration() { } // = default;
+ template <class Rep2>
+ explicit duration(const Rep2& r,
+ typename boost::enable_if <
+ boost::mpl::and_ <
+ boost::is_convertible<Rep2, rep>,
+ boost::mpl::or_ <
+ treat_as_floating_point<rep>,
+ boost::mpl::and_ <
+ boost::mpl::not_ < treat_as_floating_point<rep> >,
+ boost::mpl::not_ < treat_as_floating_point<Rep2> >
+ >
+ >
+ >
+ >::type* = 0)
+ : rep_(r) { }
+ ~duration() {} //= default;
+ duration(const duration& rhs) : rep_(rhs.rep_) {} // = default;
+ duration& operator=(const duration& rhs) // = default;
+ {
+ if (&rhs != this) rep_= rhs.rep_;
+ return *this;
+ }
+
+ // conversions
+ template <class Rep2, class Period2>
+ duration(const duration<Rep2, Period2>& d,
+ typename boost::enable_if <
+ boost::mpl::or_ <
+ treat_as_floating_point<rep>,
+ boost::mpl::and_ <
+ boost::mpl::bool_ < boost::ratio_divide<Period2, period>::type::den == 1>,
+ boost::mpl::not_ < treat_as_floating_point<Rep2> >
+ >
+ >
+ >::type* = 0)
+#ifdef __GNUC__
+ // GCC 4.2.4 refused to accept a definition at this point,
+ // yet both VC++ 9.0 SP1 and Intel ia32 11.0 accepted the definition
+ // without complaint. VC++ 9.0 SP1 refused to accept a later definition,
+ // although that was fine with GCC 4.2.4 and Intel ia32 11.0. Thus we
+ // have to support both approaches.
+ ;
+#else
+ : rep_(duration_cast<duration>(d).count()) {}
+#endif
+
+ // observer
+
+ rep count() const {return rep_;}
+
+ // arithmetic
+
+ duration operator+() const {return *this;}
+ duration operator-() const {return duration(-rep_);}
+ duration& operator++() {++rep_; return *this;}
+ duration operator++(int) {return duration(rep_++);}
+ duration& operator--() {--rep_; return *this;}
+ duration operator--(int) {return duration(rep_--);}
+
+ duration& operator+=(const duration& d) {rep_ += d.count(); return *this;}
+ duration& operator-=(const duration& d) {rep_ -= d.count(); return *this;}
+
+ duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;}
+ duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;}
+ duration& operator%=(const rep& rhs) {rep_ %= rhs; return *this;}
+ duration& operator%=(const duration& rhs) {rep_ %= rhs.count(); return *this;};
+ // 20.9.3.4 duration special values [time.duration.special]
+
+ static duration zero() {return duration(duration_values<rep>::zero());}
+ static duration min BOOST_PREVENT_MACRO_SUBSTITUTION () {return duration((duration_values<rep>::min)());}
+ static duration max BOOST_PREVENT_MACRO_SUBSTITUTION () {return duration((duration_values<rep>::max)());}
+ };
+
+//----------------------------------------------------------------------------//
+// 20.9.3.5 duration non-member arithmetic [time.duration.nonmember] //
+//----------------------------------------------------------------------------//
+
+ // Duration +
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
+ operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ typename common_type<duration<Rep1, Period1>,
+ duration<Rep2, Period2> >::type result = lhs;
+ result += rhs;
+ return result;
+ }
+
+ // Duration -
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
+ operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ typename common_type<duration<Rep1, Period1>,
+ duration<Rep2, Period2> >::type result = lhs;
+ result -= rhs;
+ return result;
+ }
+
+ // Duration *
+
+ template <class Rep1, class Period, class Rep2>
+ inline
+ typename boost::enable_if <
+ boost::mpl::and_ <
+ boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
+ boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
+ >,
+ duration<typename common_type<Rep1, Rep2>::type, Period>
+ >::type
+ operator*(const duration<Rep1, Period>& d, const Rep2& s)
+ {
+ typedef typename common_type<Rep1, Rep2>::type CR;
+ duration<CR, Period> r = d;
+ r *= static_cast<CR>(s);
+ return r;
+ }
+
+ template <class Rep1, class Period, class Rep2>
+ inline
+ typename boost::enable_if <
+ boost::mpl::and_ <
+ boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
+ boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
+ >,
+ duration<typename common_type<Rep1, Rep2>::type, Period>
+ >::type
+ operator*(const Rep1& s, const duration<Rep2, Period>& d)
+ {
+ return d * s;
+ }
+
+ // Duration /
+
+ template <class Rep1, class Period, class Rep2>
+ inline
+ typename boost::disable_if <boost_ex::chrono::detail::is_duration<Rep2>,
+ typename boost_ex::chrono::detail::duration_divide_result<duration<Rep1, Period>, Rep2>::type
+ >::type
+ operator/(const duration<Rep1, Period>& d, const Rep2& s)
+ {
+ typedef typename common_type<Rep1, Rep2>::type CR;
+ duration<CR, Period> r = d;
+ r /= static_cast<CR>(s);
+ return r;
+ }
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ typename common_type<Rep1, Rep2>::type
+ operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ typedef typename common_type<duration<Rep1, Period1>,
+ duration<Rep2, Period2> >::type CD;
+ return CD(lhs).count() / CD(rhs).count();
+ }
+
+ template <class Rep1, class Rep2, class Period>
+ inline
+ typename boost::disable_if <boost_ex::chrono::detail::is_duration<Rep1>,
+ typename boost_ex::chrono::detail::duration_divide_result2<Rep1, duration<Rep2, Period> >::type
+ >::type
+ operator/(const Rep1& s, const duration<Rep2, Period>& d)
+ {
+ typedef typename common_type<Rep1, Rep2>::type CR;
+ duration<CR, Period> r = d;
+ //return static_cast<CR>(r.count()) / static_cast<CR>(s);
+ return static_cast<CR>(s)/r.count();
+ }
+
+ // Duration %
+
+ template <class Rep1, class Period, class Rep2>
+ typename boost::disable_if <boost_ex::chrono::detail::is_duration<Rep2>,
+ typename boost_ex::chrono::detail::duration_modulo_result<duration<Rep1, Period>, Rep2>::type
+ >::type
+ operator%(const duration<Rep1, Period>& d, const Rep2& s) {
+ typedef typename common_type<Rep1, Rep2>::type CR;
+ duration<CR, Period> r = d;
+ r %= static_cast<CR>(s);
+ return r;
+ }
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
+ operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) {
+ typedef typename common_type<duration<Rep1, Period1>,
+ duration<Rep2, Period2> >::type CD;
+ CD r(lhs);
+ r%=CD(rhs);
+ return r;
+ }
+
+
+//----------------------------------------------------------------------------//
+// 20.9.3.6 duration comparisons [time.duration.comparisons] //
+//----------------------------------------------------------------------------//
+
+ namespace detail
+ {
+ template <class LhsDuration, class RhsDuration>
+ struct duration_eq
+ {
+ bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
+ {
+ typedef typename common_type<LhsDuration, RhsDuration>::type CD;
+ return CD(lhs).count() == CD(rhs).count();
+ }
+ };
+
+ template <class LhsDuration>
+ struct duration_eq<LhsDuration, LhsDuration>
+ {
+ bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
+ {return lhs.count() == rhs.count();}
+ };
+
+ template <class LhsDuration, class RhsDuration>
+ struct duration_lt
+ {
+ bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
+ {
+ typedef typename common_type<LhsDuration, RhsDuration>::type CD;
+ return CD(lhs).count() < CD(rhs).count();
+ }
+ };
+
+ template <class LhsDuration>
+ struct duration_lt<LhsDuration, LhsDuration>
+ {
+ bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
+ {return lhs.count() < rhs.count();}
+ };
+
+ } // namespace detail
+
+ // Duration ==
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ bool
+ operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ return boost_ex::chrono::detail::duration_eq<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
+ }
+
+ // Duration !=
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ bool
+ operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
+ // Duration <
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ bool
+ operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ return boost_ex::chrono::detail::duration_lt<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
+ }
+
+ // Duration >
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ bool
+ operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ return rhs < lhs;
+ }
+
+ // Duration <=
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ bool
+ operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ return !(rhs < lhs);
+ }
+
+ // Duration >=
+
+ template <class Rep1, class Period1, class Rep2, class Period2>
+ inline
+ bool
+ operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
+ {
+ return !(lhs < rhs);
+ }
+
+//----------------------------------------------------------------------------//
+// 20.9.3.7 duration_cast [time.duration.cast] //
+//----------------------------------------------------------------------------//
+
+ // Compile-time select the most efficient algorithm for the conversion...
+ template <class ToDuration, class Rep, class Period>
+ inline
+ typename boost::enable_if <boost_ex::chrono::detail::is_duration<ToDuration>, ToDuration>::type
+ duration_cast(const duration<Rep, Period>& fd)
+ {
+ return boost_ex::chrono::detail::duration_cast<duration<Rep, Period>, ToDuration>()(fd);
+ }
+
+
+//----------------------------------------------------------------------------//
+// duration constructor implementation //
+// See comment in the class duration synopsis //
+//----------------------------------------------------------------------------//
+
+#ifdef __GNUC__
+ // see comment above in section 20.9.3 Class template duration [time.duration]
+ template <class Rep, class Period>
+ template <class Rep2, class Period2>
+ duration<Rep, Period>::duration(const duration<Rep2, Period2>& d,
+ typename boost::enable_if <
+ boost::mpl::or_ <
+ treat_as_floating_point<rep>,
+ boost::mpl::and_ <
+ boost::mpl::bool_ <boost::ratio_divide<Period2, period>::type::den == 1>,
+ boost::mpl::not_ <treat_as_floating_point<Rep2> >
+ >
+ >
+ >::type*)
+ : rep_(duration_cast<duration>(d).count()) {}
+#endif
+
+}
+}
+#endif // BOOST_EX_CHRONO_DURATION_HPP
Added: trunk/libs/ratio/example/si_physics.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/si_physics.cpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,236 @@
+// ratio_test.cpp ----------------------------------------------------------//
+
+// Copyright 2008 Howard Hinnant
+// Copyright 2008 Beman Dawes
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#include <iostream>
+#include <boost/ratio.hpp>
+#include "duration.hpp"
+
+namespace User1
+{
+// Example type-safe "physics" code interoperating with chrono::duration types
+// and taking advantage of the std::ratio infrastructure and design philosophy.
+
+// length - mimics chrono::duration except restricts representation to double.
+// Uses boost::ratio facilities for length units conversions.
+
+template <class Ratio>
+class length
+{
+public:
+ typedef Ratio ratio;
+private:
+ double len_;
+public:
+
+ length() : len_(1) {}
+ length(const double& len) : len_(len) {}
+
+ // conversions
+ template <class R>
+ length(const length<R>& d)
+ : len_(d.count() * boost::ratio_divide<Ratio, R>::type::den /
+ boost::ratio_divide<Ratio, R>::type::num) {}
+
+ // observer
+
+ double count() const {return len_;}
+
+ // arithmetic
+
+ length& operator+=(const length& d) {len_ += d.count(); return *this;}
+ length& operator-=(const length& d) {len_ -= d.count(); return *this;}
+
+ length operator+() const {return *this;}
+ length operator-() const {return length(-len_);}
+
+ length& operator*=(double rhs) {len_ *= rhs; return *this;}
+ length& operator/=(double rhs) {len_ /= rhs; return *this;}
+};
+
+// Sparse sampling of length units
+typedef length<boost::ratio<1> > meter; // set meter as "unity"
+typedef length<boost::centi> centimeter; // 1/100 meter
+typedef length<boost::kilo> kilometer; // 1000 meters
+typedef length<boost::ratio<254, 10000> > inch; // 254/10000 meters
+// length takes ratio instead of two integral types so that definitions can be made like so:
+typedef length<boost::ratio_multiply<boost::ratio<12>, inch::ratio>::type> foot; // 12 inchs
+typedef length<boost::ratio_multiply<boost::ratio<5280>, foot::ratio>::type> mile; // 5280 feet
+
+// Need a floating point definition of seconds
+typedef boost_ex::chrono::duration<double> seconds; // unity
+// Demo of (scientific) support for sub-nanosecond resolutions
+typedef boost_ex::chrono::duration<double, boost::pico> picosecond; // 10^-12 seconds
+typedef boost_ex::chrono::duration<double, boost::femto> femtosecond; // 10^-15 seconds
+typedef boost_ex::chrono::duration<double, boost::atto> attosecond; // 10^-18 seconds
+
+// A very brief proof-of-concept for SIUnits-like library
+// Hard-wired to floating point seconds and meters, but accepts other units (shown in testUser1())
+template <class R1, class R2>
+class quantity
+{
+ double q_;
+public:
+ typedef R1 time_dim;
+ typedef R2 distance_dim;
+ quantity() : q_(1) {}
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+};
+
+template <>
+class quantity<boost::ratio<1>, boost::ratio<0> >
+{
+ double q_;
+public:
+ quantity() : q_(1) {}
+ quantity(seconds d) : q_(d.count()) {} // note: only User1::seconds needed here
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+};
+
+template <>
+class quantity<boost::ratio<0>, boost::ratio<1> >
+{
+ double q_;
+public:
+ quantity() : q_(1) {}
+ quantity(meter d) : q_(d.count()) {} // note: only User1::meter needed here
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+};
+
+template <>
+class quantity<boost::ratio<0>, boost::ratio<0> >
+{
+ double q_;
+public:
+ quantity() : q_(1) {}
+ quantity(double d) : q_(d) {}
+
+ double get() const {return q_;}
+ void set(double q) {q_ = q;}
+};
+
+// Example SI-Units
+typedef quantity<boost::ratio<0>, boost::ratio<0> > Scalar;
+typedef quantity<boost::ratio<1>, boost::ratio<0> > Time; // second
+typedef quantity<boost::ratio<0>, boost::ratio<1> > Distance; // meter
+typedef quantity<boost::ratio<-1>, boost::ratio<1> > Speed; // meter/second
+typedef quantity<boost::ratio<-2>, boost::ratio<1> > Acceleration; // meter/second^2
+
+template <class R1, class R2, class R3, class R4>
+quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type>
+operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
+{
+ typedef quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type> R;
+ R r;
+ r.set(x.get() / y.get());
+ return r;
+}
+
+template <class R1, class R2, class R3, class R4>
+quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type>
+operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
+{
+ typedef quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type> R;
+ R r;
+ r.set(x.get() * y.get());
+ return r;
+}
+
+template <class R1, class R2>
+quantity<R1, R2>
+operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
+{
+ typedef quantity<R1, R2> R;
+ R r;
+ r.set(x.get() + y.get());
+ return r;
+}
+
+template <class R1, class R2>
+quantity<R1, R2>
+operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
+{
+ typedef quantity<R1, R2> R;
+ R r;
+ r.set(x.get() - y.get());
+ return r;
+}
+
+// Example type-safe physics function
+Distance
+compute_distance(Speed v0, Time t, Acceleration a)
+{
+ return v0 * t + Scalar(.5) * a * t * t; // if a units mistake is made here it won't compile
+}
+
+} // User1
+
+// Exercise example type-safe physics function and show interoperation
+// of custom time durations (User1::seconds) and standard time durations (std::hours).
+// Though input can be arbitrary (but type-safe) units, output is always in SI-units
+// (a limitation of the simplified Units lib demoed here).
+
+
+
+int main()
+{
+ //~ typedef boost::ratio<8, BOOST_INTMAX_C(0x7FFFFFFFD)> R1;
+ //~ typedef boost::ratio<3, BOOST_INTMAX_C(0x7FFFFFFFD)> R2;
+ typedef User1::quantity<boost::ratio_subtract<boost::ratio<0>, boost::ratio<1> >::type,
+ boost::ratio_subtract<boost::ratio<1>, boost::ratio<0> >::type > RR;
+ //~ typedef boost::ratio_subtract<R1, R2>::type RS;
+ //~ std::cout << RS::num << '/' << RS::den << '\n';
+
+
+ std::cout << "*************\n";
+ std::cout << "* testUser1 *\n";
+ std::cout << "*************\n";
+ User1::Distance d(( User1::mile(110) ));
+ boost_ex::chrono::hours h((2));
+ User1::Time t(( h ));
+ //~ boost_ex::chrono::seconds sss=boost_ex::chrono::duration_cast<boost_ex::chrono::seconds>(h);
+ //~ User1::seconds sss((120));
+ //~ User1::Time t(( sss ));
+
+ //typedef User1::quantity<boost::ratio_subtract<User1::Distance::time_dim, User1::Time::time_dim >::type,
+ // boost::ratio_subtract<User1::Distance::distance_dim, User1::Time::distance_dim >::type > R;
+ RR r=d / t;
+ //r.set(d.get() / t.get());
+
+ User1::Speed rc= r;
+
+ User1::Speed s = d / t;
+ std::cout << "Speed = " << s.get() << " meters/sec\n";
+ User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time();
+ std::cout << "Acceleration = " << a.get() << " meters/sec^2\n";
+ User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a);
+ std::cout << "Distance = " << df.get() << " meters\n";
+ std::cout << "There are " << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter";
+ User1::meter mt = 1;
+ User1::mile mi = mt;
+ std::cout << " which is approximately " << mi.count() << '\n';
+ std::cout << "There are " << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile";
+ mi = 1;
+ mt = mi;
+ std::cout << " which is approximately " << mt.count() << '\n';
+ User1::attosecond as(1);
+ User1::seconds sec = as;
+ std::cout << "1 attosecond is " << sec.count() << " seconds\n";
+ std::cout << "sec = as; // compiles\n";
+ sec = User1::seconds(1);
+ as = sec;
+ std::cout << "1 second is " << as.count() << " attoseconds\n";
+ std::cout << "as = sec; // compiles\n";
+ std::cout << "\n";
+ return 0;
+}
Added: trunk/libs/ratio/example/static_assert.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/static_assert.hpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,30 @@
+// static_assert.hpp --------------------------------------------------------------//
+
+// Copyright 2009-2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+
+#ifndef BOOST_EX_CHRONO_DETAIL_STATIC_ASSERT_HPP
+#define BOOST_EX_CHRONO_DETAIL_STATIC_ASSERT_HPP
+
+#include "config.hpp"
+
+#ifndef BOOST_NO_STATIC_ASSERT
+#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG)
+#elif defined(BOOST_CHRONO_USES_STATIC_ASSERT)
+#include <boost/static_assert.hpp>
+#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) BOOST_STATIC_ASSERT(CND)
+#elif defined(BOOST_CHRONO_USES_MPL_ASSERT)
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/bool.hpp>
+#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) \
+ BOOST_MPL_ASSERT_MSG(boost::mpl::bool_< (CND) >::type::value, MSG, TYPES)
+#else
+//~ #elif defined(BOOST_CHRONO_USES_ARRAY_ASSERT)
+#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) static char BOOST_JOIN(boost_chrono_test_,__LINE__)[(CND)?1:-1]
+//~ #define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES)
+#endif
+
+#endif // BOOST_EX_CHRONO_DETAIL_STATIC_ASSERT_HPP
Added: trunk/libs/ratio/example/type_traits/add_rvalue_reference.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/type_traits/add_rvalue_reference.hpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,67 @@
+// add_rvalue_reference.hpp ---------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_EX_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
+#define BOOST_EX_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
+
+#include <boost/config.hpp>
+
+//----------------------------------------------------------------------------//
+
+#include <boost/type_traits/is_void.hpp>
+#include <boost/type_traits/is_reference.hpp>
+
+// should be the last #include
+#include <boost/type_traits/detail/type_trait_def.hpp>
+
+//----------------------------------------------------------------------------//
+// //
+// C++03 implementation of //
+// 20.7.6.2 Reference modifications [meta.trans.ref] //
+// Written by Vicente J. Botet Escriba //
+// //
+// If T names an object or function type then the member typedef type
+// shall name T&&; otherwise, type shall name T. [ Note: This rule reflects
+// the semantics of reference collapsing. For example, when a type T names
+// a type T1&, the type add_rvalue_reference<T>::type is not an rvalue
+// reference. -end note ]
+//----------------------------------------------------------------------------//
+
+namespace boost_ex {
+
+namespace type_traits_detail {
+
+ template <typename T, bool b>
+ struct add_rvalue_reference_helper
+ { typedef T type; };
+
+ template <typename T>
+ struct add_rvalue_reference_helper<T, true>
+ {
+#if !defined(BOOST_NO_RVALUE_REFERENCES)
+ typedef T&& type;
+#else
+ typedef T type;
+#endif
+ };
+
+ template <typename T>
+ struct add_rvalue_reference_imp
+ {
+ typedef typename boost_ex::type_traits_detail::add_rvalue_reference_helper
+ <T, (!boost::is_void<T>::value && !boost::is_reference<T>::value) >::type type;
+ };
+
+}
+
+BOOST_TT_AUX_TYPE_TRAIT_DEF1(add_rvalue_reference,T,typename boost_ex::type_traits_detail::add_rvalue_reference_imp<T>::type)
+
+} // namespace boost_ex
+
+#include <boost/type_traits/detail/type_trait_undef.hpp>
+
+#endif // BOOST_EX_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
Added: trunk/libs/ratio/example/type_traits/common_type.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/type_traits/common_type.hpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,151 @@
+// common_type.hpp ---------------------------------------------------------//
+
+// Copyright 2008 Howard Hinnant
+// Copyright 2008 Beman Dawes
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_EX_TYPE_TRAITS_EXT_COMMON_TYPE_HPP
+#define BOOST_EX_TYPE_TRAITS_EXT_COMMON_TYPE_HPP
+
+#include <boost/config.hpp>
+
+//----------------------------------------------------------------------------//
+#if defined(BOOST_NO_VARIADIC_TEMPLATES)
+#define BOOST_EX_COMMON_TYPE_ARITY 3
+#endif
+
+//----------------------------------------------------------------------------//
+#if defined(BOOST_NO_DECLTYPE) && !defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
+#define BOOST_TYPEOF_SILENT
+#include <boost/typeof/typeof.hpp> // boost wonders never cease!
+#endif
+
+//----------------------------------------------------------------------------//
+#ifndef BOOST_NO_STATIC_ASSERT
+#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG)
+#elif defined(BOOST_EX_COMMON_TYPE_USES_STATIC_ASSERT)
+#include <boost/static_assert.hpp>
+#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) BOOST_STATIC_ASSERT(CND)
+#elif defined(BOOST_EX_COMMON_TYPE_USES_MPL_ASSERT)
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/bool.hpp>
+#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) \
+ BOOST_MPL_ASSERT_MSG(boost::mpl::bool_< (CND) >::type::value, MSG, TYPES)
+#else
+//~ #elif defined(BOOST_EX_COMMON_TYPE_USES_ARRAY_ASSERT)
+#define BOOST_EX_COMMON_TYPE_CONCAT(A,B) A##B
+#define BOOST_EX_COMMON_TYPE_NAME(A,B) BOOST_EX_COMMON_TYPE_CONCAT(A,B)
+#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) static char BOOST_EX_COMMON_TYPE_NAME(__boost_common_type_test_,__LINE__)[(CND)?1:-1]
+//~ #define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES)
+#endif
+
+#if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_EX_COMMON_TYPE_USES_MPL_ASSERT)
+#define BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE "must be complete type"
+#endif
+
+#if defined(BOOST_NO_DECLTYPE) && defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
+#include "detail/common_type.hpp"
+#include <boost/type_traits/remove_cv.hpp>
+#endif
+#include <boost/mpl/if.hpp>
+#include "declval.hpp"
+
+//----------------------------------------------------------------------------//
+// //
+// C++03 implementation of //
+// 20.6.7 Other transformations [meta.trans.other] //
+// Written by Howard Hinnant //
+// Adapted for Boost by Beman Dawes, Vicente Botet and Jeffrey Hellrung //
+// //
+//----------------------------------------------------------------------------//
+
+namespace boost_ex {
+
+// prototype
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ template<typename... T>
+ struct common_type;
+#else // or no specialization
+ template <class T, class U = void, class V = void>
+ struct common_type
+ {
+ public:
+ typedef typename common_type<typename common_type<T, U>::type, V>::type type;
+ };
+#endif
+
+
+// 1 arg
+ template<typename T>
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ struct common_type<T>
+#else
+ struct common_type<T, void, void>
+
+#endif
+ {
+ BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
+ public:
+ typedef T type;
+ };
+
+// 2 args
+namespace type_traits_detail {
+
+ template <class T, class U>
+ struct common_type_2
+ {
+ private:
+ BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
+ BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(U) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (U));
+ static bool declval_bool(); // workaround gcc bug; not required by std
+ static typename add_rvalue_reference<T>::type declval_T(); // workaround gcc bug; not required by std
+ static typename add_rvalue_reference<U>::type declval_U(); // workaround gcc bug; not required by std
+
+#if !defined(BOOST_NO_DECLTYPE)
+ public:
+ typedef decltype(declval<bool>() ? declval<T>() : declval<U>()) type;
+#elif defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
+ public:
+ typedef typename detail_type_traits_common_type::common_type_impl<
+ typename remove_cv<T>::type,
+ typename remove_cv<U>::type
+ >::type type;
+#else
+ public:
+ //~ typedef BOOST_TYPEOF_TPL(declval_bool() ? declval_T() : declval_U()) type;
+ typedef BOOST_TYPEOF_TPL(declval<bool>() ? declval<T>() : declval<U>()) type;
+#endif
+ };
+
+ template <class T>
+ struct common_type_2<T, T>
+ {
+ typedef T type;
+ };
+ }
+
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ template <class T, class U>
+ struct common_type<T, U>
+#else
+ template <class T, class U>
+ struct common_type<T, U, void>
+#endif
+ : type_traits_detail::common_type_2<T,U>
+ { };
+
+
+// 3 or more args
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+ template<typename T, typename U, typename... V>
+ struct common_type<T, U, V...> {
+ public:
+ typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
+ };
+#endif
+} // namespace boost_ex
+
+#endif // BOOST_TYPE_TRAITS_EXT_COMMON_TYPE_HPP
Added: trunk/libs/ratio/example/type_traits/declval.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/type_traits/declval.hpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,44 @@
+// common_type.hpp ---------------------------------------------------------//
+
+// Copyright 2010 Vicente J. Botet Escriba
+
+// Distributed under the Boost Software License, Version 1.0.
+// See http://www.boost.org/LICENSE_1_0.txt
+
+#ifndef BOOST_EX_TYPE_TRAITS_EXT_DECLVAL__HPP
+#define BOOST_EX_TYPE_TRAITS_EXT_DECLVAL__HPP
+
+#include <boost/config.hpp>
+
+//----------------------------------------------------------------------------//
+
+#include "add_rvalue_reference.hpp"
+
+//----------------------------------------------------------------------------//
+// //
+// C++03 implementation of //
+// Written by Vicente J. Botet Escriba //
+//~ 20.3.4 Function template declval [declval]
+//~ 1 The library provides the function template declval to simplify the definition of expressions which occur as
+//~ unevaluated operands.
+//~ 2 Remarks: If this function is used, the program is ill-formed.
+//~ 3 Remarks: The template parameter T of declval may be an incomplete type.
+//~ [ Example:
+
+//~ template <class To, class From>
+//~ decltype(static_cast<To>(declval<From>())) convert(From&&);
+
+//~ declares a function template convert which only participats in overloading if the type From can be
+//~ explicitly converted to type To. For another example see class template common_type (20.7.6.6). -end
+//~ example ]
+// //
+//----------------------------------------------------------------------------//
+
+namespace boost_ex {
+
+ template <typename T>
+ typename add_rvalue_reference<T>::type declval(); //noexcept; // as unevaluated operand
+
+} // namespace boost
+
+#endif // BOOST_EX_TYPE_TRAITS_EXT_DECLVAL__HPP
Added: trunk/libs/ratio/example/type_traits/detail/common_type.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/ratio/example/type_traits/detail/common_type.hpp 2011-01-02 11:26:51 EST (Sun, 02 Jan 2011)
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * boost/type_traits/detail/common_type.hpp
+ *
+ * Copyright 2010, Jeffrey Hellrung.
+ * Distributed under the Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * struct boost::common_type<T,U>
+ *
+ * common_type<T,U>::type is the type of the expression
+ * b() ? x() : y()
+ * where b() returns a bool, x() has return type T, and y() has return type U.
+ * See
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm#common_type
+ *
+ * Note that this evaluates to void if one or both of T and U is void.
+ ******************************************************************************/
+
+#ifndef BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP
+#define BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/begin_end.hpp>
+#include <boost/mpl/contains.hpp>
+#include <boost/mpl/copy.hpp>
+#include <boost/mpl/deref.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/inserter.hpp>
+#include <boost/mpl/next.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/push_back.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/vector/vector0.hpp>
+#include <boost/mpl/vector/vector10.hpp>
+#include <boost/type_traits/integral_constant.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/make_signed.hpp>
+#include <boost/type_traits/make_unsigned.hpp>
+#include <boost/type_traits/remove_cv.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/declval.hpp>
+
+namespace boost_ex
+{
+
+namespace detail_type_traits_common_type
+{
+
+/*******************************************************************************
+ * struct propagate_cv< From, To >
+ *
+ * This metafunction propagates cv-qualifiers on type From to type To.
+ ******************************************************************************/
+
+template< class From, class To >
+struct propagate_cv
+{ typedef To type; };
+template< class From, class To >
+struct propagate_cv< const From, To >
+{ typedef To const type; };
+template< class From, class To >
+struct propagate_cv< volatile From, To >
+{ typedef To volatile type; };
+template< class From, class To >
+struct propagate_cv< const volatile From, To >
+{ typedef To const volatile type; };
+
+/*******************************************************************************
+ * struct is_signable_integral<T>
+ *
+ * This metafunction determines if T is an integral type which can be made
+ * signed or unsigned.
+ ******************************************************************************/
+
+template< class T >
+struct is_signable_integral
+ : mpl::or_< is_integral<T>, is_enum<T> >
+{ };
+template<>
+struct is_signable_integral< bool >
+ : false_type
+{ };
+
+/*******************************************************************************
+ * struct sizeof_t<N>
+ * typedef ... yes_type
+ * typedef ... no_type
+ *
+ * These types are integral players in the use of the "sizeof trick", i.e., we
+ * can distinguish overload selection by inspecting the size of the return type
+ * of the overload.
+ ******************************************************************************/
+
+template< std::size_t N > struct sizeof_t { char _dummy[N]; };
+typedef sizeof_t<1> yes_type;
+typedef sizeof_t<2> no_type;
+BOOST_MPL_ASSERT_RELATION( sizeof( yes_type ), ==, 1 );
+BOOST_MPL_ASSERT_RELATION( sizeof( no_type ), ==, 2 );
+
+/*******************************************************************************
+ * rvalue_test(T&) -> no_type
+ * rvalue_test(...) -> yes_type
+ *
+ * These overloads are used to determine the rvalue-ness of an expression.
+ ******************************************************************************/
+
+template< class T > no_type rvalue_test(T&);
+yes_type rvalue_test(...);
+
+/*******************************************************************************
+ * struct conversion_test_overloads< Sequence >
+ *
+ * This struct has multiple overloads of the static member function apply, each
+ * one taking a single parameter of a type within the Boost.MPL sequence
+ * Sequence. Each such apply overload has a return type with sizeof equal to
+ * one plus the index of the parameter type within Sequence. Thus, we can
+ * deduce the type T of an expression as long as we can generate a finite set of
+ * candidate types containing T via these apply overloads and the "sizeof
+ * trick".
+ ******************************************************************************/
+
+template< class First, class Last, std::size_t Index >
+struct conversion_test_overloads_iterate
+ : conversion_test_overloads_iterate<
+ typename mpl::next< First >::type, Last, Index + 1
+ >
+{
+ using conversion_test_overloads_iterate<
+ typename mpl::next< First >::type, Last, Index + 1
+ >::apply;
+ static sizeof_t< Index + 1 >
+ apply(typename mpl::deref< First >::type);
+};
+
+template< class Last, std::size_t Index >
+struct conversion_test_overloads_iterate< Last, Last, Index >
+{ static sizeof_t< Index + 1 > apply(...); };
+
+template< class Sequence >
+struct conversion_test_overloads
+ : conversion_test_overloads_iterate<
+ typename mpl::begin< Sequence >::type,
+ typename mpl::end< Sequence >::type,
+ 0
+ >
+{ };
+
+/*******************************************************************************
+ * struct select< Sequence, Index >
+ *
+ * select is synonymous with mpl::at_c unless Index equals the size of the
+ * Boost.MPL Sequence, in which case this evaluates to void.
+ ******************************************************************************/
+
+template<
+ class Sequence, int Index,
+ int N = mpl::size< Sequence >::value
+>
+struct select
+ : mpl::at_c< Sequence, Index >
+{ };
+template< class Sequence, int N >
+struct select< Sequence, N, N >
+{ typedef void type; };
+
+/*******************************************************************************
+ * class deduce_common_type< T, U, NominalCandidates >
+ * struct nominal_candidates<T,U>
+ * struct common_type_dispatch_on_rvalueness<T,U>
+ * struct common_type_impl<T,U>
+ *
+ * These classes and structs implement the logic behind common_type, which goes
+ * roughly as follows. Let C be the type of the conditional expression
+ * declval< bool >() ? declval<T>() : declval<U>()
+ * if C is an rvalue, then:
+ * let T' and U' be T and U stripped of reference- and cv-qualifiers
+ * if T' and U' are pointer types, say, T' = V* and U' = W*, then:
+ * define the set of NominalCandidates to be
+ * { V*, W*, V'*, W'* }
+ * where V' is V with whatever cv-qualifiers are on W, and W' is W
+ * with whatever cv-qualifiers are on V
+ * else T' and U' are both "signable integral types" (integral and enum
+ * types excepting bool), then:
+ * define the set of NominalCandidates to be
+ * { unsigned(T'), unsigned(U'), signed(T'), signed(U') }
+ * where unsigned(X) is make_unsigned<X>::type and signed(X) is
+ * make_signed<X>::type
+ * else
+ * define the set of NominalCandidates to be
+ * { T', U' }
+ * else
+ * let V and W be T and U stripped of reference-qualifiers
+ * define the set of NominalCandidates to be
+ * { V&, W&, V'&, W'& }
+ * where V' is V with whatever cv-qualifiers are on W, and W' is W with
+ * whatever cv-qualifiers are on V
+ * define the set of Candidates to be equal to the set of NominalCandidates with
+ * duplicates removed, and use this set of Candidates to determine C using the
+ * conversion_test_overloads struct
+ ******************************************************************************/
+
+template< class T, class U, class NominalCandidates >
+class deduce_common_type
+{
+ typedef typename mpl::copy<
+ NominalCandidates,
+ mpl::inserter<
+ mpl::vector0<>,
+ mpl::if_<
+ mpl::contains< mpl::_1, mpl::_2 >,
+ mpl::_1,
+ mpl::push_back< mpl::_1, mpl::_2 >
+ >
+ >
+ >::type candidate_types;
+ static const int best_candidate_index =
+ sizeof( conversion_test_overloads< candidate_types >::apply(
+ declval< bool >() ? declval<T>() : declval<U>()
+ ) ) - 1;
+public:
+ typedef typename select< candidate_types, best_candidate_index >::type type;
+};
+
+template<
+ class T, class U,
+ class V = typename remove_cv< typename remove_reference<T>::type >::type,
+ class W = typename remove_cv< typename remove_reference<U>::type >::type,
+ bool = is_signable_integral<V>::value && is_signable_integral<W>::value
+>
+struct nominal_candidates;
+
+template< class T, class U, class V, class W >
+struct nominal_candidates< T, U, V, W, false >
+{ typedef mpl::vector2<V,W> type; };
+
+template< class T, class U, class V, class W >
+struct nominal_candidates< T, U, V, W, true >
+{
+ typedef mpl::vector4<
+ typename make_unsigned<V>::type,
+ typename make_unsigned<W>::type,
+ typename make_signed<V>::type,
+ typename make_signed<W>::type
+ > type;
+};
+
+template< class T, class U, class V, class W >
+struct nominal_candidates< T, U, V*, W*, false >
+{
+ typedef mpl::vector4<
+ V*, W*,
+ typename propagate_cv<W,V>::type *,
+ typename propagate_cv<V,W>::type *
+ > type;
+};
+
+template<
+ class T, class U,
+ bool = sizeof( ::boost::detail_type_traits_common_type::rvalue_test(
+ declval< bool >() ? declval<T>() : declval<U>()
+ ) ) == sizeof( yes_type )
+>
+struct common_type_dispatch_on_rvalueness;
+
+template< class T, class U >
+struct common_type_dispatch_on_rvalueness< T, U, true >
+ : deduce_common_type< T, U, typename nominal_candidates<T,U>::type >
+{ };
+
+template< class T, class U >
+struct common_type_dispatch_on_rvalueness< T, U, false >
+{
+private:
+ typedef typename remove_reference<T>::type unrefed_T_type;
+ typedef typename remove_reference<U>::type unrefed_U_type;
+public:
+ typedef typename deduce_common_type<
+ T, U,
+ mpl::vector4<
+ unrefed_T_type &,
+ unrefed_U_type &,
+ typename propagate_cv< unrefed_U_type, unrefed_T_type >::type &,
+ typename propagate_cv< unrefed_T_type, unrefed_U_type >::type &
+ >
+ >::type type;
+};
+
+template< class T, class U >
+struct common_type_impl
+ : common_type_dispatch_on_rvalueness<T,U>
+{ };
+
+template< class T > struct common_type_impl< T, void > { typedef void type; };
+template< class T > struct common_type_impl< void, T > { typedef void type; };
+template<> struct common_type_impl< void, void > { typedef void type; };
+template< > struct common_type_impl< char, short> { typedef int type; };
+template< > struct common_type_impl< short, char> { typedef int type; };
+template< > struct common_type_impl< unsigned char, short> { typedef int type; };
+template< > struct common_type_impl< short, unsigned char> { typedef int type; };
+template< > struct common_type_impl< unsigned char, unsigned short> { typedef int type; };
+template< > struct common_type_impl< unsigned short, unsigned char> { typedef int type; };
+template< > struct common_type_impl< char, unsigned short> { typedef int type; };
+template< > struct common_type_impl< unsigned short, char> { typedef int type; };
+
+} // namespace detail_type_traits_common_type
+
+
+} // namespace boost_ex
+
+#endif // BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk