1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
3 //
4 // Copyright (C) 2003-2008 Matthias Christian Schabel
5 // Copyright (C) 2007-2008 Steven Watanabe
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 /**
12 \file
13 
14 \brief quaternion.cpp
15 
16 \details
17 Demonstrate interoperability with Boost.Quaternion.
18 
19 Output:
20 @verbatim
21 
22 //[quaternion_output_1
23 +L      = (4,3,2,1) m
24 -L      = (-4,-3,-2,-1) m
25 L+L     = (8,6,4,2) m
26 L-L     = (0,0,0,0) m
27 L*L     = (2,24,16,8) m^2
28 L/L     = (1,0,0,0) dimensionless
29 L^3     = (-104,102,68,34) m^3
30 //]
31 
32 //[quaternion_output_2
33 +L      = (4 m,3 m,2 m,1 m)
34 -L      = (-4 m,-3 m,-2 m,-1 m)
35 L+L     = (8 m,6 m,4 m,2 m)
36 L-L     = (0 m,0 m,0 m,0 m)
37 L^3     = (-104 m^3,102 m^3,68 m^3,34 m^3)
38 //]
39 
40 @endverbatim
41 **/
42 
43 #include <iostream>
44 
45 #include <boost/math/quaternion.hpp>
46 #include <boost/mpl/list.hpp>
47 
48 #include <boost/units/pow.hpp>
49 #include <boost/units/quantity.hpp>
50 #include <boost/units/io.hpp>
51 
52 #include "test_system.hpp"
53 
54 #if BOOST_UNITS_HAS_BOOST_TYPEOF
55 
56 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
57 
58 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::math::quaternion, 1)
59 
60 #endif
61 
62 namespace boost {
63 
64 namespace units {
65 
66 //[quaternion_class_snippet_1a
67 /// specialize power typeof helper
68 template<class Y,long N,long D>
69 struct power_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D> >
70 {
71     // boost::math::quaternion only supports integer powers
72     BOOST_STATIC_ASSERT(D==1);
73 
74     typedef boost::math::quaternion<
75         typename power_typeof_helper<Y,static_rational<N,D> >::type
76     > type;
77 
valueboost::units::power_typeof_helper78     static type value(const boost::math::quaternion<Y>& x)
79     {
80         return boost::math::pow(x,static_cast<int>(N));
81     }
82 };
83 //]
84 
85 //[quaternion_class_snippet_1b
86 /// specialize root typeof helper
87 template<class Y,long N,long D>
88 struct root_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D> >
89 {
90     // boost::math::quaternion only supports integer powers
91     BOOST_STATIC_ASSERT(N==1);
92 
93     typedef boost::math::quaternion<
94         typename root_typeof_helper<Y,static_rational<N,D> >::type
95     > type;
96 
valueboost::units::root_typeof_helper97     static type value(const boost::math::quaternion<Y>& x)
98     {
99         return boost::math::pow(x,static_cast<int>(D));
100     }
101 };
102 //]
103 
104 //[quaternion_class_snippet_2a
105 /// specialize power typeof helper for quaternion<quantity<Unit,Y> >
106 template<class Unit,long N,long D,class Y>
107 struct power_typeof_helper<
108     boost::math::quaternion<quantity<Unit,Y> >,
109     static_rational<N,D> >
110 {
111     typedef typename power_typeof_helper<
112         Y,
113         static_rational<N,D>
114     >::type     value_type;
115 
116     typedef typename power_typeof_helper<
117         Unit,
118         static_rational<N,D>
119     >::type  unit_type;
120 
121     typedef quantity<unit_type,value_type>         quantity_type;
122     typedef boost::math::quaternion<quantity_type> type;
123 
valueboost::units::power_typeof_helper124     static type value(const boost::math::quaternion<quantity<Unit,Y> >& x)
125     {
126         const boost::math::quaternion<value_type>   tmp =
127             pow<static_rational<N,D> >(boost::math::quaternion<Y>(
128                 x.R_component_1().value(),
129                 x.R_component_2().value(),
130                 x.R_component_3().value(),
131                 x.R_component_4().value()));
132 
133         return type(quantity_type::from_value(tmp.R_component_1()),
134                     quantity_type::from_value(tmp.R_component_2()),
135                     quantity_type::from_value(tmp.R_component_3()),
136                     quantity_type::from_value(tmp.R_component_4()));
137     }
138 };
139 //]
140 
141 //[quaternion_class_snippet_2b
142 /// specialize root typeof helper for quaternion<quantity<Unit,Y> >
143 template<class Unit,long N,long D,class Y>
144 struct root_typeof_helper<
145     boost::math::quaternion<quantity<Unit,Y> >,
146     static_rational<N,D> >
147 {
148     typedef typename root_typeof_helper<
149         Y,
150         static_rational<N,D>
151     >::type      value_type;
152 
153     typedef typename root_typeof_helper<
154         Unit,
155         static_rational<N,D>
156     >::type   unit_type;
157 
158     typedef quantity<unit_type,value_type>         quantity_type;
159     typedef boost::math::quaternion<quantity_type> type;
160 
valueboost::units::root_typeof_helper161     static type value(const boost::math::quaternion<quantity<Unit,Y> >& x)
162     {
163         const boost::math::quaternion<value_type>   tmp =
164             root<static_rational<N,D> >(boost::math::quaternion<Y>(
165                 x.R_component_1().value(),
166                 x.R_component_2().value(),
167                 x.R_component_3().value(),
168                 x.R_component_4().value()));
169 
170         return type(quantity_type::from_value(tmp.R_component_1()),
171                     quantity_type::from_value(tmp.R_component_2()),
172                     quantity_type::from_value(tmp.R_component_3()),
173                     quantity_type::from_value(tmp.R_component_4()));
174     }
175 };
176 //]
177 
178 } // namespace units
179 
180 } // namespace boost
181 
main(void)182 int main(void)
183 {
184     using boost::math::quaternion;
185     using namespace boost::units;
186     using namespace boost::units::test;
187     using boost::units::pow;
188 
189     {
190     //[quaternion_snippet_1
191     typedef quantity<length,quaternion<double> >     length_dimension;
192 
193     length_dimension    L(quaternion<double>(4.0,3.0,2.0,1.0)*meters);
194     //]
195 
196     std::cout << "+L      = " << +L << std::endl
197               << "-L      = " << -L << std::endl
198               << "L+L     = " << L+L << std::endl
199               << "L-L     = " << L-L << std::endl
200               << "L*L     = " << L*L << std::endl
201               << "L/L     = " << L/L << std::endl
202               // unfortunately, without qualification msvc still
203               // finds boost::math::pow by ADL.
204               << "L^3     = " << boost::units::pow<3>(L) << std::endl
205 //              << "L^(3/2) = " << pow< static_rational<3,2> >(L) << std::endl
206 //              << "3vL     = " << root<3>(L) << std::endl
207 //              << "(3/2)vL = " << root< static_rational<3,2> >(L) << std::endl
208               << std::endl;
209     }
210 
211     {
212     //[quaternion_snippet_2
213     typedef quaternion<quantity<length> >     length_dimension;
214 
215     length_dimension    L(4.0*meters,3.0*meters,2.0*meters,1.0*meters);
216     //]
217 
218     std::cout << "+L      = " << +L << std::endl
219               << "-L      = " << -L << std::endl
220               << "L+L     = " << L+L << std::endl
221               << "L-L     = " << L-L << std::endl
222 //              << "L*L     = " << L*L << std::endl
223 //              << "L/L     = " << L/L << std::endl
224               << "L^3     = " << boost::units::pow<3>(L) << std::endl
225 //              << "L^(3/2) = " << pow< static_rational<3,2> >(L) << std::endl
226 //              << "3vL     = " << root<3>(L) << std::endl
227 //              << "(3/2)vL = " << root< static_rational<3,2> >(L) << std::endl
228               << std::endl;
229     }
230 
231     return 0;
232 }
233