]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/ratio/example/si_physics.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / ratio / example / si_physics.cpp
1 // ratio_test.cpp ----------------------------------------------------------//
2
3 // Copyright 2008 Howard Hinnant
4 // Copyright 2008 Beman Dawes
5
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
8
9 #include <iostream>
10 #include <boost/ratio/ratio.hpp>
11 #include "duration.hpp"
12
13 namespace User1
14 {
15 // Example type-safe "physics" code interoperating with chrono::duration types
16 // and taking advantage of the std::ratio infrastructure and design philosophy.
17
18 // length - mimics chrono::duration except restricts representation to double.
19 // Uses boost::ratio facilities for length units conversions.
20
21 template <class Ratio>
22 class length
23 {
24 public:
25 typedef Ratio ratio;
26 private:
27 double len_;
28 public:
29
30 length() : len_(1) {}
31 length(const double& len) : len_(len) {}
32
33 // conversions
34 template <class R>
35 length(const length<R>& d)
36 : len_(d.count() * boost::ratio_divide<Ratio, R>::type::den /
37 boost::ratio_divide<Ratio, R>::type::num) {}
38
39 // observer
40
41 double count() const {return len_;}
42
43 // arithmetic
44
45 length& operator+=(const length& d) {len_ += d.count(); return *this;}
46 length& operator-=(const length& d) {len_ -= d.count(); return *this;}
47
48 length operator+() const {return *this;}
49 length operator-() const {return length(-len_);}
50
51 length& operator*=(double rhs) {len_ *= rhs; return *this;}
52 length& operator/=(double rhs) {len_ /= rhs; return *this;}
53 };
54
55 // Sparse sampling of length units
56 typedef length<boost::ratio<1> > meter; // set meter as "unity"
57 typedef length<boost::centi> centimeter; // 1/100 meter
58 typedef length<boost::kilo> kilometer; // 1000 meters
59 typedef length<boost::ratio<254, 10000> > inch; // 254/10000 meters
60 // length takes ratio instead of two integral types so that definitions can be made like so:
61 typedef length<boost::ratio_multiply<boost::ratio<12>, inch::ratio>::type> foot; // 12 inchs
62 typedef length<boost::ratio_multiply<boost::ratio<5280>, foot::ratio>::type> mile; // 5280 feet
63
64 // Need a floating point definition of seconds
65 typedef boost_ex::chrono::duration<double> seconds; // unity
66 // Demo of (scientific) support for sub-nanosecond resolutions
67 typedef boost_ex::chrono::duration<double, boost::pico> picosecond; // 10^-12 seconds
68 typedef boost_ex::chrono::duration<double, boost::femto> femtosecond; // 10^-15 seconds
69 typedef boost_ex::chrono::duration<double, boost::atto> attosecond; // 10^-18 seconds
70
71 // A very brief proof-of-concept for SIUnits-like library
72 // Hard-wired to floating point seconds and meters, but accepts other units (shown in testUser1())
73 template <class R1, class R2>
74 class quantity
75 {
76 double q_;
77 public:
78 typedef R1 time_dim;
79 typedef R2 distance_dim;
80 quantity() : q_(1) {}
81
82 double get() const {return q_;}
83 void set(double q) {q_ = q;}
84 };
85
86 template <>
87 class quantity<boost::ratio<1>, boost::ratio<0> >
88 {
89 double q_;
90 public:
91 quantity() : q_(1) {}
92 quantity(seconds d) : q_(d.count()) {} // note: only User1::seconds needed here
93
94 double get() const {return q_;}
95 void set(double q) {q_ = q;}
96 };
97
98 template <>
99 class quantity<boost::ratio<0>, boost::ratio<1> >
100 {
101 double q_;
102 public:
103 quantity() : q_(1) {}
104 quantity(meter d) : q_(d.count()) {} // note: only User1::meter needed here
105
106 double get() const {return q_;}
107 void set(double q) {q_ = q;}
108 };
109
110 template <>
111 class quantity<boost::ratio<0>, boost::ratio<0> >
112 {
113 double q_;
114 public:
115 quantity() : q_(1) {}
116 quantity(double d) : q_(d) {}
117
118 double get() const {return q_;}
119 void set(double q) {q_ = q;}
120 };
121
122 // Example SI-Units
123 typedef quantity<boost::ratio<0>, boost::ratio<0> > Scalar;
124 typedef quantity<boost::ratio<1>, boost::ratio<0> > Time; // second
125 typedef quantity<boost::ratio<0>, boost::ratio<1> > Distance; // meter
126 typedef quantity<boost::ratio<-1>, boost::ratio<1> > Speed; // meter/second
127 typedef quantity<boost::ratio<-2>, boost::ratio<1> > Acceleration; // meter/second^2
128
129 template <class R1, class R2, class R3, class R4>
130 quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type>
131 operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
132 {
133 typedef quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type> R;
134 R r;
135 r.set(x.get() / y.get());
136 return r;
137 }
138
139 template <class R1, class R2, class R3, class R4>
140 quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type>
141 operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
142 {
143 typedef quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type> R;
144 R r;
145 r.set(x.get() * y.get());
146 return r;
147 }
148
149 template <class R1, class R2>
150 quantity<R1, R2>
151 operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
152 {
153 typedef quantity<R1, R2> R;
154 R r;
155 r.set(x.get() + y.get());
156 return r;
157 }
158
159 template <class R1, class R2>
160 quantity<R1, R2>
161 operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
162 {
163 typedef quantity<R1, R2> R;
164 R r;
165 r.set(x.get() - y.get());
166 return r;
167 }
168
169 // Example type-safe physics function
170 Distance
171 compute_distance(Speed v0, Time t, Acceleration a)
172 {
173 return v0 * t + Scalar(.5) * a * t * t; // if a units mistake is made here it won't compile
174 }
175
176 } // User1
177
178 // Exercise example type-safe physics function and show interoperation
179 // of custom time durations (User1::seconds) and standard time durations (std::hours).
180 // Though input can be arbitrary (but type-safe) units, output is always in SI-units
181 // (a limitation of the simplified Units lib demoed here).
182
183
184
185 int main()
186 {
187 //~ typedef boost::ratio<8, BOOST_INTMAX_C(0x7FFFFFFFD)> R1;
188 //~ typedef boost::ratio<3, BOOST_INTMAX_C(0x7FFFFFFFD)> R2;
189 typedef User1::quantity<boost::ratio_subtract<boost::ratio<0>, boost::ratio<1> >::type,
190 boost::ratio_subtract<boost::ratio<1>, boost::ratio<0> >::type > RR;
191 //~ typedef boost::ratio_subtract<R1, R2>::type RS;
192 //~ std::cout << RS::num << '/' << RS::den << '\n';
193
194
195 std::cout << "*************\n";
196 std::cout << "* testUser1 *\n";
197 std::cout << "*************\n";
198 User1::Distance d(( User1::mile(110) ));
199 boost_ex::chrono::hours h((2));
200 User1::Time t(( h ));
201 //~ boost_ex::chrono::seconds sss=boost_ex::chrono::duration_cast<boost_ex::chrono::seconds>(h);
202 //~ User1::seconds sss((120));
203 //~ User1::Time t(( sss ));
204
205 //typedef User1::quantity<boost::ratio_subtract<User1::Distance::time_dim, User1::Time::time_dim >::type,
206 // boost::ratio_subtract<User1::Distance::distance_dim, User1::Time::distance_dim >::type > R;
207 RR r=d / t;
208 //r.set(d.get() / t.get());
209
210 User1::Speed rc= r;
211 (void)rc;
212 User1::Speed s = d / t;
213 std::cout << "Speed = " << s.get() << " meters/sec\n";
214 User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time();
215 std::cout << "Acceleration = " << a.get() << " meters/sec^2\n";
216 User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a);
217 std::cout << "Distance = " << df.get() << " meters\n";
218 std::cout << "There are " << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter";
219 User1::meter mt = 1;
220 User1::mile mi = mt;
221 std::cout << " which is approximately " << mi.count() << '\n';
222 std::cout << "There are " << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile";
223 mi = 1;
224 mt = mi;
225 std::cout << " which is approximately " << mt.count() << '\n';
226 User1::attosecond as(1);
227 User1::seconds sec = as;
228 std::cout << "1 attosecond is " << sec.count() << " seconds\n";
229 std::cout << "sec = as; // compiles\n";
230 sec = User1::seconds(1);
231 as = sec;
232 std::cout << "1 second is " << as.count() << " attoseconds\n";
233 std::cout << "as = sec; // compiles\n";
234 std::cout << "\n";
235 return 0;
236 }