![]() |
Home | Libraries | People | FAQ | More |
This example demonstrates the use of boost::math::quaternion
as a value type for quantity
and the converse. For the first case, we first define specializations of
power_typeof_helper
and root_typeof_helper
for powers and roots, respectively:
/// specialize power typeof helper template<class Y,long N,long D> struct power_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D> > { // boost::math::quaternion only supports integer powers BOOST_STATIC_ASSERT(D==1); typedef boost::math::quaternion< typename power_typeof_helper<Y,static_rational<N,D> >::type > type; static type value(const boost::math::quaternion<Y>& x) { return boost::math::pow(x,static_cast<int>(N)); } };
/// specialize root typeof helper template<class Y,long N,long D> struct root_typeof_helper<boost::math::quaternion<Y>,static_rational<N,D> > { // boost::math::quaternion only supports integer powers BOOST_STATIC_ASSERT(N==1); typedef boost::math::quaternion< typename root_typeof_helper<Y,static_rational<N,D> >::type > type; static type value(const boost::math::quaternion<Y>& x) { return boost::math::pow(x,static_cast<int>(D)); } };
We can now declare a quantity
of a quaternion
:
typedef quantity<length,quaternion<double> > length_dimension; length_dimension L(quaternion<double>(4.0,3.0,2.0,1.0)*meters);
so that all operations that are defined in the quaternion
class behave correctly. If rational powers were defined for this class, it
would be possible to compute rational powers and roots with no additional
changes.
+L = (4,3,2,1) m -L = (-4,-3,-2,-1) m L+L = (8,6,4,2) m L-L = (0,0,0,0) m L*L = (2,24,16,8) m^2 L/L = (1,0,0,0) dimensionless L^3 = (-104,102,68,34) m^3
Now, if for some reason we preferred the quantity
to be the value
type of the quaternion
class
we would have :
typedef quaternion<quantity<length> > length_dimension; length_dimension L(4.0*meters,3.0*meters,2.0*meters,1.0*meters);
Here, the unary plus and minus and addition and subtraction operators function
correctly. Unfortunately, the multiplication and division operations fail
because quaternion
implements
them in terms of the *=
and
/=
operators, respectively,
which are incapable of representing the heterogeneous unit algebra needed
for quantities (an identical problem occurs with std::complex<T>
,
for the same reason). In order to compute rational powers and roots, we need
to specialize power_typeof_helper
and root_typeof_helper
as follows:
/// specialize power typeof helper for quaternion<quantity<Unit,Y> > template<class Unit,long N,long D,class Y> struct power_typeof_helper< boost::math::quaternion<quantity<Unit,Y> >, static_rational<N,D> > { typedef typename power_typeof_helper< Y, static_rational<N,D> >::type value_type; typedef typename power_typeof_helper< Unit, static_rational<N,D> >::type unit_type; typedef quantity<unit_type,value_type> quantity_type; typedef boost::math::quaternion<quantity_type> type; static type value(const boost::math::quaternion<quantity<Unit,Y> >& x) { const boost::math::quaternion<value_type> tmp = pow<static_rational<N,D> >(boost::math::quaternion<Y>( x.R_component_1().value(), x.R_component_2().value(), x.R_component_3().value(), x.R_component_4().value())); return type(quantity_type::from_value(tmp.R_component_1()), quantity_type::from_value(tmp.R_component_2()), quantity_type::from_value(tmp.R_component_3()), quantity_type::from_value(tmp.R_component_4())); } };
/// specialize root typeof helper for quaternion<quantity<Unit,Y> > template<class Unit,long N,long D,class Y> struct root_typeof_helper< boost::math::quaternion<quantity<Unit,Y> >, static_rational<N,D> > { typedef typename root_typeof_helper< Y, static_rational<N,D> >::type value_type; typedef typename root_typeof_helper< Unit, static_rational<N,D> >::type unit_type; typedef quantity<unit_type,value_type> quantity_type; typedef boost::math::quaternion<quantity_type> type; static type value(const boost::math::quaternion<quantity<Unit,Y> >& x) { const boost::math::quaternion<value_type> tmp = root<static_rational<N,D> >(boost::math::quaternion<Y>( x.R_component_1().value(), x.R_component_2().value(), x.R_component_3().value(), x.R_component_4().value())); return type(quantity_type::from_value(tmp.R_component_1()), quantity_type::from_value(tmp.R_component_2()), quantity_type::from_value(tmp.R_component_3()), quantity_type::from_value(tmp.R_component_4())); } };
giving:
+L = (4 m,3 m,2 m,1 m) -L = (-4 m,-3 m,-2 m,-1 m) L+L = (8 m,6 m,4 m,2 m) L-L = (0 m,0 m,0 m,0 m) L^3 = (-104 m^3,102 m^3,68 m^3,34 m^3)