Home > Enterprise >  QVM - user-defined quaternion and scalar
QVM - user-defined quaternion and scalar

Time:12-26

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

Live On Coliru

#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.

Live On Coliru

#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;
}
  • Related