QVM - 用户定义的四元数和标量

QVM - user-defined quaternion and scalar

我正在尝试将 boost::qvmboost::multiprecision 结合使用。我构建了一个用户定义的四元数,但无法缩放四元数。我想按 boost::multiprecision::cpp_dec_float_100 的数量来缩放它。贝娄是我的代码。我也用注释掉的代码试了一下。

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

我得到的错误是:

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;
      |     ~~^~~~

我意识到可以简单地重载运算符,但这是 by boost 预期的解决方案吗? 代码:

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}  ;
}

ADL 找不到 QVM 定义的运算符,您需要帮助编译器:

using boost::qvm::operator*=;
q *= x;

您可以使 ADL 工作,可能有多种方式。

一种方法是使 boost::qvm 成为您的类型的关联命名空间。另一个是 using 您自己的命名空间中的适当运算符。

在您自己的命名空间中显式使用

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;
}

破解 ADL

或者,使用 ADL-hook,例如

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;
}