I am trying use boost::qvm
with boost::multiprecision
. I built a user-defined quaternion, but I am not able to scale the quaternion. I would like to scale it by a number of type boost::multiprecision::cpp_dec_float_100
. Bellow is my code. I also tried it with the out commented code.
#include <bits/stdc .h>
#include <boost/numeric/odeint.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/qvm.hpp>
using namespace std;
typedef boost::multiprecision::cpp_dec_float_100 fl;
struct fquat { fl a[4]; };
namespace boost { namespace qvm {
template <>
struct quat_traits<fquat>: quat_traits_defaults<fquat,fl> {
template <int I>
static inline scalar_type & write_element( fquat & q ) {
return q.a[I];
}
};
template <> struct is_scalar<fl> { static bool const value=true; };
template <> struct scalar_traits<fl>
{ BOOST_QVM_INLINE_CRITICAL static fl value( int v ) { return fl(v); }};
/*
template <>
struct deduce_quat<fquat, fl> {
typedef fquat type;
};
template <>
struct deduce_quat2<fquat, fquat, fl> {
typedef fquat type;
};
*/
} }
int main()
{
fquat q = {fl(1),fl(1),fl(1),fl(1)};
fl x = fl(3);
q *= x;
return 0;
}
The error I get is:
test2.cpp: In function ‘int main()’:
test2.cpp:48:7: error: no match for ‘operator*=’ (operand types are ‘fquat’ and ‘fl’ {aka ‘boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<100> >’})
48 | q *= x;
| ~~^~~~
CodePudding user response:
I realized that it is possible to simply overload the operator, but is this the by boost intended solution? Code:
fquat operator* (fquat const &q, fl y)
{
return fquat {boost::qvm::S(q)*y , boost::qvm::X(q)*y , boost::qvm::Y(q)*y , boost::qvm::Z(q)*y} ;
}
CodePudding user response:
The QVM defined operators do not get found with ADL, you need to help the compiler:
using boost::qvm::operator*=;
q *= x;
You can make ADL work, probably in various ways.
One way would to make boost::qvm
an associated namespace for your type(s). Another would be to using
the appropriate operators in your own namespace.
Explicit Using in Your Own Namespace
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/numeric/odeint.hpp>
#include <boost/qvm.hpp>
namespace MyLib {
using fl = boost::multiprecision::cpp_dec_float_100;
struct fquat {
fl a[4];
};
using boost::qvm::operator*=;
} // namespace MyLib
namespace boost::qvm {
template <>
struct quat_traits<MyLib::fquat>
: quat_traits_defaults<MyLib::fquat, MyLib::fl> {
template <int I>
static inline scalar_type& write_element(MyLib::fquat& q)
{
return q.a[I];
}
};
template <> struct is_scalar<MyLib::fl> {
static bool const value = true;
};
template <> struct scalar_traits<MyLib::fl> {
BOOST_QVM_INLINE_CRITICAL static MyLib::fl value(int v)
{
return MyLib::fl(v);
}
};
template <> struct deduce_quat<MyLib::fquat, MyLib::fl> {
using type = MyLib::fquat;
};
template <> struct deduce_quat2<MyLib::fquat, MyLib::fquat, MyLib::fl> {
using type = MyLib::fquat;
};
} // namespace boost::qvm
using MyLib::fl;
using MyLib::fquat;
int main()
{
fquat q = {fl(1), fl(1), fl(1), fl(1)};
fl x = fl(3);
q *= x;
}
Hack ADL
Alternatively, using ADL-hook like e.g.
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/numeric/odeint.hpp>
#include <boost/qvm.hpp>
namespace boost::qvm {
struct my_ADL_hook {
};
} // namespace boost::qvm
using fl = boost::multiprecision::cpp_dec_float_100;
template <typename = boost::qvm::my_ADL_hook> struct fquat_t {
fl a[4];
};
using fquat = fquat_t<>;
namespace boost::qvm {
template <> struct quat_traits<fquat> : quat_traits_defaults<fquat, fl> {
template <int I> static inline scalar_type& write_element(fquat& q)
{
return q.a[I];
}
};
template <> struct is_scalar<fl> {
static bool const value = true;
};
template <> struct scalar_traits<fl> {
BOOST_QVM_INLINE_CRITICAL static fl value(int v) { return fl(v); }
};
//template <> struct deduce_quat<fquat, fl> { using type = fquat; } ;
//template <> struct deduce_quat2<fquat, fquat, fl> { using type = fquat; } ;
} // namespace boost::qvm
int main()
{
fquat q = {1, 1, 1, 1};
fl x = 3;
q *= x;
}