Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:45

0001 #ifndef BOOST_QVM_GEN_MAT_OPERATIONS4_HPP_INCLUDED
0002 #define BOOST_QVM_GEN_MAT_OPERATIONS4_HPP_INCLUDED
0003 
0004 // Copyright 2008-2022 Emil Dotchevski and Reverge Studios, Inc.
0005 
0006 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0007 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 // This file was generated by a program. Do not edit manually.
0010 
0011 #include <boost/qvm/assert.hpp>
0012 #include <boost/qvm/deduce_mat.hpp>
0013 #include <boost/qvm/deduce_vec.hpp>
0014 #include <boost/qvm/error.hpp>
0015 #include <boost/qvm/gen/mat_assign4.hpp>
0016 #include <boost/qvm/quat_traits.hpp>
0017 #include <boost/qvm/scalar_traits.hpp>
0018 #include <boost/qvm/throw_exception.hpp>
0019 
0020 namespace boost { namespace qvm {
0021 
0022 template <class A,class B>
0023 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0024 typename lazy_enable_if_c<
0025     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0026     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0027     deduce_mat2<A,B,4,4> >::type
0028 operator+( A const & a, B const & b )
0029     {
0030     typedef typename deduce_mat2<A,B,4,4>::type R;
0031     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==4);
0032     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==4);
0033     R r;
0034     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)+mat_traits<B>::template read_element<0,0>(b));
0035     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)+mat_traits<B>::template read_element<0,1>(b));
0036     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)+mat_traits<B>::template read_element<0,2>(b));
0037     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)+mat_traits<B>::template read_element<0,3>(b));
0038     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)+mat_traits<B>::template read_element<1,0>(b));
0039     write_mat_element<1,1>(r,mat_traits<A>::template read_element<1,1>(a)+mat_traits<B>::template read_element<1,1>(b));
0040     write_mat_element<1,2>(r,mat_traits<A>::template read_element<1,2>(a)+mat_traits<B>::template read_element<1,2>(b));
0041     write_mat_element<1,3>(r,mat_traits<A>::template read_element<1,3>(a)+mat_traits<B>::template read_element<1,3>(b));
0042     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)+mat_traits<B>::template read_element<2,0>(b));
0043     write_mat_element<2,1>(r,mat_traits<A>::template read_element<2,1>(a)+mat_traits<B>::template read_element<2,1>(b));
0044     write_mat_element<2,2>(r,mat_traits<A>::template read_element<2,2>(a)+mat_traits<B>::template read_element<2,2>(b));
0045     write_mat_element<2,3>(r,mat_traits<A>::template read_element<2,3>(a)+mat_traits<B>::template read_element<2,3>(b));
0046     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)+mat_traits<B>::template read_element<3,0>(b));
0047     write_mat_element<3,1>(r,mat_traits<A>::template read_element<3,1>(a)+mat_traits<B>::template read_element<3,1>(b));
0048     write_mat_element<3,2>(r,mat_traits<A>::template read_element<3,2>(a)+mat_traits<B>::template read_element<3,2>(b));
0049     write_mat_element<3,3>(r,mat_traits<A>::template read_element<3,3>(a)+mat_traits<B>::template read_element<3,3>(b));
0050     return r;
0051     }
0052 
0053 namespace
0054 sfinae
0055     {
0056     using ::boost::qvm::operator+;
0057     }
0058 
0059 namespace
0060 qvm_detail
0061     {
0062     template <int R,int C>
0063     struct plus_mm_defined;
0064 
0065     template <>
0066     struct
0067     plus_mm_defined<4,4>
0068         {
0069         static bool const value=true;
0070         };
0071     }
0072 
0073 template <class A,class B>
0074 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0075 typename lazy_enable_if_c<
0076     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0077     mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
0078     deduce_mat2<A,B,4,1> >::type
0079 operator+( A const & a, B const & b )
0080     {
0081     typedef typename deduce_mat2<A,B,4,1>::type R;
0082     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==4);
0083     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==1);
0084     R r;
0085     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)+mat_traits<B>::template read_element<0,0>(b));
0086     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)+mat_traits<B>::template read_element<1,0>(b));
0087     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)+mat_traits<B>::template read_element<2,0>(b));
0088     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)+mat_traits<B>::template read_element<3,0>(b));
0089     return r;
0090     }
0091 
0092 namespace
0093 sfinae
0094     {
0095     using ::boost::qvm::operator+;
0096     }
0097 
0098 namespace
0099 qvm_detail
0100     {
0101     template <int R,int C>
0102     struct plus_mm_defined;
0103 
0104     template <>
0105     struct
0106     plus_mm_defined<4,1>
0107         {
0108         static bool const value=true;
0109         };
0110     }
0111 
0112 template <class A,class B>
0113 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0114 typename lazy_enable_if_c<
0115     mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
0116     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0117     deduce_mat2<A,B,1,4> >::type
0118 operator+( A const & a, B const & b )
0119     {
0120     typedef typename deduce_mat2<A,B,1,4>::type R;
0121     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==1);
0122     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==4);
0123     R r;
0124     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)+mat_traits<B>::template read_element<0,0>(b));
0125     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)+mat_traits<B>::template read_element<0,1>(b));
0126     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)+mat_traits<B>::template read_element<0,2>(b));
0127     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)+mat_traits<B>::template read_element<0,3>(b));
0128     return r;
0129     }
0130 
0131 namespace
0132 sfinae
0133     {
0134     using ::boost::qvm::operator+;
0135     }
0136 
0137 namespace
0138 qvm_detail
0139     {
0140     template <int R,int C>
0141     struct plus_mm_defined;
0142 
0143     template <>
0144     struct
0145     plus_mm_defined<1,4>
0146         {
0147         static bool const value=true;
0148         };
0149     }
0150 
0151 template <class A,class B>
0152 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0153 typename lazy_enable_if_c<
0154     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0155     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0156     deduce_mat2<A,B,4,4> >::type
0157 operator-( A const & a, B const & b )
0158     {
0159     typedef typename deduce_mat2<A,B,4,4>::type R;
0160     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==4);
0161     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==4);
0162     R r;
0163     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)-mat_traits<B>::template read_element<0,0>(b));
0164     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)-mat_traits<B>::template read_element<0,1>(b));
0165     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)-mat_traits<B>::template read_element<0,2>(b));
0166     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)-mat_traits<B>::template read_element<0,3>(b));
0167     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)-mat_traits<B>::template read_element<1,0>(b));
0168     write_mat_element<1,1>(r,mat_traits<A>::template read_element<1,1>(a)-mat_traits<B>::template read_element<1,1>(b));
0169     write_mat_element<1,2>(r,mat_traits<A>::template read_element<1,2>(a)-mat_traits<B>::template read_element<1,2>(b));
0170     write_mat_element<1,3>(r,mat_traits<A>::template read_element<1,3>(a)-mat_traits<B>::template read_element<1,3>(b));
0171     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)-mat_traits<B>::template read_element<2,0>(b));
0172     write_mat_element<2,1>(r,mat_traits<A>::template read_element<2,1>(a)-mat_traits<B>::template read_element<2,1>(b));
0173     write_mat_element<2,2>(r,mat_traits<A>::template read_element<2,2>(a)-mat_traits<B>::template read_element<2,2>(b));
0174     write_mat_element<2,3>(r,mat_traits<A>::template read_element<2,3>(a)-mat_traits<B>::template read_element<2,3>(b));
0175     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)-mat_traits<B>::template read_element<3,0>(b));
0176     write_mat_element<3,1>(r,mat_traits<A>::template read_element<3,1>(a)-mat_traits<B>::template read_element<3,1>(b));
0177     write_mat_element<3,2>(r,mat_traits<A>::template read_element<3,2>(a)-mat_traits<B>::template read_element<3,2>(b));
0178     write_mat_element<3,3>(r,mat_traits<A>::template read_element<3,3>(a)-mat_traits<B>::template read_element<3,3>(b));
0179     return r;
0180     }
0181 
0182 namespace
0183 sfinae
0184     {
0185     using ::boost::qvm::operator-;
0186     }
0187 
0188 namespace
0189 qvm_detail
0190     {
0191     template <int R,int C>
0192     struct minus_mm_defined;
0193 
0194     template <>
0195     struct
0196     minus_mm_defined<4,4>
0197         {
0198         static bool const value=true;
0199         };
0200     }
0201 
0202 template <class A,class B>
0203 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0204 typename lazy_enable_if_c<
0205     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0206     mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
0207     deduce_mat2<A,B,4,1> >::type
0208 operator-( A const & a, B const & b )
0209     {
0210     typedef typename deduce_mat2<A,B,4,1>::type R;
0211     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==4);
0212     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==1);
0213     R r;
0214     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)-mat_traits<B>::template read_element<0,0>(b));
0215     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)-mat_traits<B>::template read_element<1,0>(b));
0216     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)-mat_traits<B>::template read_element<2,0>(b));
0217     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)-mat_traits<B>::template read_element<3,0>(b));
0218     return r;
0219     }
0220 
0221 namespace
0222 sfinae
0223     {
0224     using ::boost::qvm::operator-;
0225     }
0226 
0227 namespace
0228 qvm_detail
0229     {
0230     template <int R,int C>
0231     struct minus_mm_defined;
0232 
0233     template <>
0234     struct
0235     minus_mm_defined<4,1>
0236         {
0237         static bool const value=true;
0238         };
0239     }
0240 
0241 template <class A,class B>
0242 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0243 typename lazy_enable_if_c<
0244     mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
0245     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0246     deduce_mat2<A,B,1,4> >::type
0247 operator-( A const & a, B const & b )
0248     {
0249     typedef typename deduce_mat2<A,B,1,4>::type R;
0250     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==1);
0251     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==4);
0252     R r;
0253     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)-mat_traits<B>::template read_element<0,0>(b));
0254     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)-mat_traits<B>::template read_element<0,1>(b));
0255     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)-mat_traits<B>::template read_element<0,2>(b));
0256     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)-mat_traits<B>::template read_element<0,3>(b));
0257     return r;
0258     }
0259 
0260 namespace
0261 sfinae
0262     {
0263     using ::boost::qvm::operator-;
0264     }
0265 
0266 namespace
0267 qvm_detail
0268     {
0269     template <int R,int C>
0270     struct minus_mm_defined;
0271 
0272     template <>
0273     struct
0274     minus_mm_defined<1,4>
0275         {
0276         static bool const value=true;
0277         };
0278     }
0279 
0280 template <class A,class B>
0281 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0282 typename enable_if_c<
0283     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0284     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0285     A &>::type
0286 operator+=( A & a, B const & b )
0287     {
0288     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)+mat_traits<B>::template read_element<0,0>(b));
0289     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)+mat_traits<B>::template read_element<0,1>(b));
0290     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)+mat_traits<B>::template read_element<0,2>(b));
0291     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)+mat_traits<B>::template read_element<0,3>(b));
0292     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)+mat_traits<B>::template read_element<1,0>(b));
0293     write_mat_element<1,1>(a,mat_traits<A>::template read_element<1,1>(a)+mat_traits<B>::template read_element<1,1>(b));
0294     write_mat_element<1,2>(a,mat_traits<A>::template read_element<1,2>(a)+mat_traits<B>::template read_element<1,2>(b));
0295     write_mat_element<1,3>(a,mat_traits<A>::template read_element<1,3>(a)+mat_traits<B>::template read_element<1,3>(b));
0296     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)+mat_traits<B>::template read_element<2,0>(b));
0297     write_mat_element<2,1>(a,mat_traits<A>::template read_element<2,1>(a)+mat_traits<B>::template read_element<2,1>(b));
0298     write_mat_element<2,2>(a,mat_traits<A>::template read_element<2,2>(a)+mat_traits<B>::template read_element<2,2>(b));
0299     write_mat_element<2,3>(a,mat_traits<A>::template read_element<2,3>(a)+mat_traits<B>::template read_element<2,3>(b));
0300     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)+mat_traits<B>::template read_element<3,0>(b));
0301     write_mat_element<3,1>(a,mat_traits<A>::template read_element<3,1>(a)+mat_traits<B>::template read_element<3,1>(b));
0302     write_mat_element<3,2>(a,mat_traits<A>::template read_element<3,2>(a)+mat_traits<B>::template read_element<3,2>(b));
0303     write_mat_element<3,3>(a,mat_traits<A>::template read_element<3,3>(a)+mat_traits<B>::template read_element<3,3>(b));
0304     return a;
0305     }
0306 
0307 namespace
0308 sfinae
0309     {
0310     using ::boost::qvm::operator+=;
0311     }
0312 
0313 namespace
0314 qvm_detail
0315     {
0316     template <int R,int C>
0317     struct plus_eq_mm_defined;
0318 
0319     template <>
0320     struct
0321     plus_eq_mm_defined<4,4>
0322         {
0323         static bool const value=true;
0324         };
0325     }
0326 
0327 template <class A,class B>
0328 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0329 typename enable_if_c<
0330     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0331     mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
0332     A &>::type
0333 operator+=( A & a, B const & b )
0334     {
0335     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)+mat_traits<B>::template read_element<0,0>(b));
0336     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)+mat_traits<B>::template read_element<1,0>(b));
0337     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)+mat_traits<B>::template read_element<2,0>(b));
0338     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)+mat_traits<B>::template read_element<3,0>(b));
0339     return a;
0340     }
0341 
0342 namespace
0343 sfinae
0344     {
0345     using ::boost::qvm::operator+=;
0346     }
0347 
0348 namespace
0349 qvm_detail
0350     {
0351     template <int R,int C>
0352     struct plus_eq_mm_defined;
0353 
0354     template <>
0355     struct
0356     plus_eq_mm_defined<4,1>
0357         {
0358         static bool const value=true;
0359         };
0360     }
0361 
0362 template <class A,class B>
0363 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0364 typename enable_if_c<
0365     mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
0366     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0367     A &>::type
0368 operator+=( A & a, B const & b )
0369     {
0370     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)+mat_traits<B>::template read_element<0,0>(b));
0371     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)+mat_traits<B>::template read_element<0,1>(b));
0372     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)+mat_traits<B>::template read_element<0,2>(b));
0373     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)+mat_traits<B>::template read_element<0,3>(b));
0374     return a;
0375     }
0376 
0377 namespace
0378 sfinae
0379     {
0380     using ::boost::qvm::operator+=;
0381     }
0382 
0383 namespace
0384 qvm_detail
0385     {
0386     template <int R,int C>
0387     struct plus_eq_mm_defined;
0388 
0389     template <>
0390     struct
0391     plus_eq_mm_defined<1,4>
0392         {
0393         static bool const value=true;
0394         };
0395     }
0396 
0397 template <class A,class B>
0398 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0399 typename enable_if_c<
0400     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0401     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0402     A &>::type
0403 operator-=( A & a, B const & b )
0404     {
0405     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)-mat_traits<B>::template read_element<0,0>(b));
0406     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)-mat_traits<B>::template read_element<0,1>(b));
0407     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)-mat_traits<B>::template read_element<0,2>(b));
0408     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)-mat_traits<B>::template read_element<0,3>(b));
0409     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)-mat_traits<B>::template read_element<1,0>(b));
0410     write_mat_element<1,1>(a,mat_traits<A>::template read_element<1,1>(a)-mat_traits<B>::template read_element<1,1>(b));
0411     write_mat_element<1,2>(a,mat_traits<A>::template read_element<1,2>(a)-mat_traits<B>::template read_element<1,2>(b));
0412     write_mat_element<1,3>(a,mat_traits<A>::template read_element<1,3>(a)-mat_traits<B>::template read_element<1,3>(b));
0413     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)-mat_traits<B>::template read_element<2,0>(b));
0414     write_mat_element<2,1>(a,mat_traits<A>::template read_element<2,1>(a)-mat_traits<B>::template read_element<2,1>(b));
0415     write_mat_element<2,2>(a,mat_traits<A>::template read_element<2,2>(a)-mat_traits<B>::template read_element<2,2>(b));
0416     write_mat_element<2,3>(a,mat_traits<A>::template read_element<2,3>(a)-mat_traits<B>::template read_element<2,3>(b));
0417     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)-mat_traits<B>::template read_element<3,0>(b));
0418     write_mat_element<3,1>(a,mat_traits<A>::template read_element<3,1>(a)-mat_traits<B>::template read_element<3,1>(b));
0419     write_mat_element<3,2>(a,mat_traits<A>::template read_element<3,2>(a)-mat_traits<B>::template read_element<3,2>(b));
0420     write_mat_element<3,3>(a,mat_traits<A>::template read_element<3,3>(a)-mat_traits<B>::template read_element<3,3>(b));
0421     return a;
0422     }
0423 
0424 namespace
0425 sfinae
0426     {
0427     using ::boost::qvm::operator-=;
0428     }
0429 
0430 namespace
0431 qvm_detail
0432     {
0433     template <int R,int C>
0434     struct minus_eq_mm_defined;
0435 
0436     template <>
0437     struct
0438     minus_eq_mm_defined<4,4>
0439         {
0440         static bool const value=true;
0441         };
0442     }
0443 
0444 template <class A,class B>
0445 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0446 typename enable_if_c<
0447     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
0448     mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
0449     A &>::type
0450 operator-=( A & a, B const & b )
0451     {
0452     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)-mat_traits<B>::template read_element<0,0>(b));
0453     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)-mat_traits<B>::template read_element<1,0>(b));
0454     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)-mat_traits<B>::template read_element<2,0>(b));
0455     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)-mat_traits<B>::template read_element<3,0>(b));
0456     return a;
0457     }
0458 
0459 namespace
0460 sfinae
0461     {
0462     using ::boost::qvm::operator-=;
0463     }
0464 
0465 namespace
0466 qvm_detail
0467     {
0468     template <int R,int C>
0469     struct minus_eq_mm_defined;
0470 
0471     template <>
0472     struct
0473     minus_eq_mm_defined<4,1>
0474         {
0475         static bool const value=true;
0476         };
0477     }
0478 
0479 template <class A,class B>
0480 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0481 typename enable_if_c<
0482     mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
0483     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
0484     A &>::type
0485 operator-=( A & a, B const & b )
0486     {
0487     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)-mat_traits<B>::template read_element<0,0>(b));
0488     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)-mat_traits<B>::template read_element<0,1>(b));
0489     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)-mat_traits<B>::template read_element<0,2>(b));
0490     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)-mat_traits<B>::template read_element<0,3>(b));
0491     return a;
0492     }
0493 
0494 namespace
0495 sfinae
0496     {
0497     using ::boost::qvm::operator-=;
0498     }
0499 
0500 namespace
0501 qvm_detail
0502     {
0503     template <int R,int C>
0504     struct minus_eq_mm_defined;
0505 
0506     template <>
0507     struct
0508     minus_eq_mm_defined<1,4>
0509         {
0510         static bool const value=true;
0511         };
0512     }
0513 
0514 template <class A,class B>
0515 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0516 typename lazy_enable_if_c<
0517     mat_traits<A>::rows==4 && mat_traits<A>::cols==4 && is_scalar<B>::value,
0518     deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
0519 operator*( A const & a, B b )
0520     {
0521     typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
0522     R r;
0523     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)*b);
0524     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)*b);
0525     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)*b);
0526     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)*b);
0527     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)*b);
0528     write_mat_element<1,1>(r,mat_traits<A>::template read_element<1,1>(a)*b);
0529     write_mat_element<1,2>(r,mat_traits<A>::template read_element<1,2>(a)*b);
0530     write_mat_element<1,3>(r,mat_traits<A>::template read_element<1,3>(a)*b);
0531     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)*b);
0532     write_mat_element<2,1>(r,mat_traits<A>::template read_element<2,1>(a)*b);
0533     write_mat_element<2,2>(r,mat_traits<A>::template read_element<2,2>(a)*b);
0534     write_mat_element<2,3>(r,mat_traits<A>::template read_element<2,3>(a)*b);
0535     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)*b);
0536     write_mat_element<3,1>(r,mat_traits<A>::template read_element<3,1>(a)*b);
0537     write_mat_element<3,2>(r,mat_traits<A>::template read_element<3,2>(a)*b);
0538     write_mat_element<3,3>(r,mat_traits<A>::template read_element<3,3>(a)*b);
0539     return r;
0540     }
0541 
0542 namespace
0543 sfinae
0544     {
0545     using ::boost::qvm::operator*;
0546     }
0547 
0548 namespace
0549 qvm_detail
0550     {
0551     template <int R,int C>
0552     struct mul_ms_defined;
0553 
0554     template <>
0555     struct
0556     mul_ms_defined<4,4>
0557         {
0558         static bool const value=true;
0559         };
0560     }
0561 
0562 template <class A,class B>
0563 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0564 typename lazy_enable_if_c<
0565     is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==4,
0566     deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols> >::type
0567 operator*( A a, B const & b )
0568     {
0569     typedef typename deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols>::type R;
0570     R r;
0571     write_mat_element<0,0>(r,a*mat_traits<B>::template read_element<0,0>(b));
0572     write_mat_element<0,1>(r,a*mat_traits<B>::template read_element<0,1>(b));
0573     write_mat_element<0,2>(r,a*mat_traits<B>::template read_element<0,2>(b));
0574     write_mat_element<0,3>(r,a*mat_traits<B>::template read_element<0,3>(b));
0575     write_mat_element<1,0>(r,a*mat_traits<B>::template read_element<1,0>(b));
0576     write_mat_element<1,1>(r,a*mat_traits<B>::template read_element<1,1>(b));
0577     write_mat_element<1,2>(r,a*mat_traits<B>::template read_element<1,2>(b));
0578     write_mat_element<1,3>(r,a*mat_traits<B>::template read_element<1,3>(b));
0579     write_mat_element<2,0>(r,a*mat_traits<B>::template read_element<2,0>(b));
0580     write_mat_element<2,1>(r,a*mat_traits<B>::template read_element<2,1>(b));
0581     write_mat_element<2,2>(r,a*mat_traits<B>::template read_element<2,2>(b));
0582     write_mat_element<2,3>(r,a*mat_traits<B>::template read_element<2,3>(b));
0583     write_mat_element<3,0>(r,a*mat_traits<B>::template read_element<3,0>(b));
0584     write_mat_element<3,1>(r,a*mat_traits<B>::template read_element<3,1>(b));
0585     write_mat_element<3,2>(r,a*mat_traits<B>::template read_element<3,2>(b));
0586     write_mat_element<3,3>(r,a*mat_traits<B>::template read_element<3,3>(b));
0587     return r;
0588     }
0589 
0590 namespace
0591 sfinae
0592     {
0593     using ::boost::qvm::operator*;
0594     }
0595 
0596 namespace
0597 qvm_detail
0598     {
0599     template <int R,int C>
0600     struct mul_sm_defined;
0601 
0602     template <>
0603     struct
0604     mul_sm_defined<4,4>
0605         {
0606         static bool const value=true;
0607         };
0608     }
0609 
0610 template <class A,class B>
0611 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0612 typename lazy_enable_if_c<
0613     mat_traits<A>::rows==4 && mat_traits<A>::cols==1 && is_scalar<B>::value,
0614     deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
0615 operator*( A const & a, B b )
0616     {
0617     typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
0618     R r;
0619     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)*b);
0620     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)*b);
0621     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)*b);
0622     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)*b);
0623     return r;
0624     }
0625 
0626 namespace
0627 sfinae
0628     {
0629     using ::boost::qvm::operator*;
0630     }
0631 
0632 namespace
0633 qvm_detail
0634     {
0635     template <int R,int C>
0636     struct mul_ms_defined;
0637 
0638     template <>
0639     struct
0640     mul_ms_defined<4,1>
0641         {
0642         static bool const value=true;
0643         };
0644     }
0645 
0646 template <class A,class B>
0647 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0648 typename lazy_enable_if_c<
0649     is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==1,
0650     deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols> >::type
0651 operator*( A a, B const & b )
0652     {
0653     typedef typename deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols>::type R;
0654     R r;
0655     write_mat_element<0,0>(r,a*mat_traits<B>::template read_element<0,0>(b));
0656     write_mat_element<1,0>(r,a*mat_traits<B>::template read_element<1,0>(b));
0657     write_mat_element<2,0>(r,a*mat_traits<B>::template read_element<2,0>(b));
0658     write_mat_element<3,0>(r,a*mat_traits<B>::template read_element<3,0>(b));
0659     return r;
0660     }
0661 
0662 namespace
0663 sfinae
0664     {
0665     using ::boost::qvm::operator*;
0666     }
0667 
0668 namespace
0669 qvm_detail
0670     {
0671     template <int R,int C>
0672     struct mul_sm_defined;
0673 
0674     template <>
0675     struct
0676     mul_sm_defined<4,1>
0677         {
0678         static bool const value=true;
0679         };
0680     }
0681 
0682 template <class A,class B>
0683 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0684 typename lazy_enable_if_c<
0685     mat_traits<A>::rows==1 && mat_traits<A>::cols==4 && is_scalar<B>::value,
0686     deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
0687 operator*( A const & a, B b )
0688     {
0689     typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
0690     R r;
0691     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)*b);
0692     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)*b);
0693     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)*b);
0694     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)*b);
0695     return r;
0696     }
0697 
0698 namespace
0699 sfinae
0700     {
0701     using ::boost::qvm::operator*;
0702     }
0703 
0704 namespace
0705 qvm_detail
0706     {
0707     template <int R,int C>
0708     struct mul_ms_defined;
0709 
0710     template <>
0711     struct
0712     mul_ms_defined<1,4>
0713         {
0714         static bool const value=true;
0715         };
0716     }
0717 
0718 template <class A,class B>
0719 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0720 typename lazy_enable_if_c<
0721     is_scalar<A>::value && mat_traits<B>::rows==1 && mat_traits<B>::cols==4,
0722     deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols> >::type
0723 operator*( A a, B const & b )
0724     {
0725     typedef typename deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols>::type R;
0726     R r;
0727     write_mat_element<0,0>(r,a*mat_traits<B>::template read_element<0,0>(b));
0728     write_mat_element<0,1>(r,a*mat_traits<B>::template read_element<0,1>(b));
0729     write_mat_element<0,2>(r,a*mat_traits<B>::template read_element<0,2>(b));
0730     write_mat_element<0,3>(r,a*mat_traits<B>::template read_element<0,3>(b));
0731     return r;
0732     }
0733 
0734 namespace
0735 sfinae
0736     {
0737     using ::boost::qvm::operator*;
0738     }
0739 
0740 namespace
0741 qvm_detail
0742     {
0743     template <int R,int C>
0744     struct mul_sm_defined;
0745 
0746     template <>
0747     struct
0748     mul_sm_defined<1,4>
0749         {
0750         static bool const value=true;
0751         };
0752     }
0753 
0754 template <class A,class B>
0755 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0756 typename enable_if_c<
0757     mat_traits<A>::rows==4 && mat_traits<A>::cols==4 && is_scalar<B>::value,
0758     A &>::type
0759 operator*=( A & a, B b )
0760     {
0761     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)*b);
0762     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)*b);
0763     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)*b);
0764     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)*b);
0765     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)*b);
0766     write_mat_element<1,1>(a,mat_traits<A>::template read_element<1,1>(a)*b);
0767     write_mat_element<1,2>(a,mat_traits<A>::template read_element<1,2>(a)*b);
0768     write_mat_element<1,3>(a,mat_traits<A>::template read_element<1,3>(a)*b);
0769     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)*b);
0770     write_mat_element<2,1>(a,mat_traits<A>::template read_element<2,1>(a)*b);
0771     write_mat_element<2,2>(a,mat_traits<A>::template read_element<2,2>(a)*b);
0772     write_mat_element<2,3>(a,mat_traits<A>::template read_element<2,3>(a)*b);
0773     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)*b);
0774     write_mat_element<3,1>(a,mat_traits<A>::template read_element<3,1>(a)*b);
0775     write_mat_element<3,2>(a,mat_traits<A>::template read_element<3,2>(a)*b);
0776     write_mat_element<3,3>(a,mat_traits<A>::template read_element<3,3>(a)*b);
0777     return a;
0778     }
0779 
0780 namespace
0781 sfinae
0782     {
0783     using ::boost::qvm::operator*=;
0784     }
0785 
0786 namespace
0787 qvm_detail
0788     {
0789     template <int R,int C>
0790     struct mul_eq_ms_defined;
0791 
0792     template <>
0793     struct
0794     mul_eq_ms_defined<4,4>
0795         {
0796         static bool const value=true;
0797         };
0798     }
0799 
0800 template <class A,class B>
0801 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0802 typename enable_if_c<
0803     mat_traits<A>::rows==4 && mat_traits<A>::cols==1 && is_scalar<B>::value,
0804     A &>::type
0805 operator*=( A & a, B b )
0806     {
0807     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)*b);
0808     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)*b);
0809     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)*b);
0810     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)*b);
0811     return a;
0812     }
0813 
0814 namespace
0815 sfinae
0816     {
0817     using ::boost::qvm::operator*=;
0818     }
0819 
0820 namespace
0821 qvm_detail
0822     {
0823     template <int R,int C>
0824     struct mul_eq_ms_defined;
0825 
0826     template <>
0827     struct
0828     mul_eq_ms_defined<4,1>
0829         {
0830         static bool const value=true;
0831         };
0832     }
0833 
0834 template <class A,class B>
0835 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0836 typename enable_if_c<
0837     mat_traits<A>::rows==1 && mat_traits<A>::cols==4 && is_scalar<B>::value,
0838     A &>::type
0839 operator*=( A & a, B b )
0840     {
0841     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)*b);
0842     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)*b);
0843     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)*b);
0844     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)*b);
0845     return a;
0846     }
0847 
0848 namespace
0849 sfinae
0850     {
0851     using ::boost::qvm::operator*=;
0852     }
0853 
0854 namespace
0855 qvm_detail
0856     {
0857     template <int R,int C>
0858     struct mul_eq_ms_defined;
0859 
0860     template <>
0861     struct
0862     mul_eq_ms_defined<1,4>
0863         {
0864         static bool const value=true;
0865         };
0866     }
0867 
0868 template <class A,class B>
0869 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0870 typename lazy_enable_if_c<
0871     mat_traits<A>::rows==4 && mat_traits<A>::cols==4 && is_scalar<B>::value,
0872     deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
0873 operator/( A const & a, B b )
0874     {
0875     typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
0876     R r;
0877     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)/b);
0878     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)/b);
0879     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)/b);
0880     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)/b);
0881     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)/b);
0882     write_mat_element<1,1>(r,mat_traits<A>::template read_element<1,1>(a)/b);
0883     write_mat_element<1,2>(r,mat_traits<A>::template read_element<1,2>(a)/b);
0884     write_mat_element<1,3>(r,mat_traits<A>::template read_element<1,3>(a)/b);
0885     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)/b);
0886     write_mat_element<2,1>(r,mat_traits<A>::template read_element<2,1>(a)/b);
0887     write_mat_element<2,2>(r,mat_traits<A>::template read_element<2,2>(a)/b);
0888     write_mat_element<2,3>(r,mat_traits<A>::template read_element<2,3>(a)/b);
0889     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)/b);
0890     write_mat_element<3,1>(r,mat_traits<A>::template read_element<3,1>(a)/b);
0891     write_mat_element<3,2>(r,mat_traits<A>::template read_element<3,2>(a)/b);
0892     write_mat_element<3,3>(r,mat_traits<A>::template read_element<3,3>(a)/b);
0893     return r;
0894     }
0895 
0896 namespace
0897 sfinae
0898     {
0899     using ::boost::qvm::operator/;
0900     }
0901 
0902 namespace
0903 qvm_detail
0904     {
0905     template <int R,int C>
0906     struct div_ms_defined;
0907 
0908     template <>
0909     struct
0910     div_ms_defined<4,4>
0911         {
0912         static bool const value=true;
0913         };
0914     }
0915 
0916 template <class A,class B>
0917 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0918 typename lazy_enable_if_c<
0919     is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==4,
0920     deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols> >::type
0921 operator/( A a, B const & b )
0922     {
0923     typedef typename deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols>::type R;
0924     R r;
0925     write_mat_element<0,0>(r,a/mat_traits<B>::template read_element<0,0>(b));
0926     write_mat_element<0,1>(r,a/mat_traits<B>::template read_element<0,1>(b));
0927     write_mat_element<0,2>(r,a/mat_traits<B>::template read_element<0,2>(b));
0928     write_mat_element<0,3>(r,a/mat_traits<B>::template read_element<0,3>(b));
0929     write_mat_element<1,0>(r,a/mat_traits<B>::template read_element<1,0>(b));
0930     write_mat_element<1,1>(r,a/mat_traits<B>::template read_element<1,1>(b));
0931     write_mat_element<1,2>(r,a/mat_traits<B>::template read_element<1,2>(b));
0932     write_mat_element<1,3>(r,a/mat_traits<B>::template read_element<1,3>(b));
0933     write_mat_element<2,0>(r,a/mat_traits<B>::template read_element<2,0>(b));
0934     write_mat_element<2,1>(r,a/mat_traits<B>::template read_element<2,1>(b));
0935     write_mat_element<2,2>(r,a/mat_traits<B>::template read_element<2,2>(b));
0936     write_mat_element<2,3>(r,a/mat_traits<B>::template read_element<2,3>(b));
0937     write_mat_element<3,0>(r,a/mat_traits<B>::template read_element<3,0>(b));
0938     write_mat_element<3,1>(r,a/mat_traits<B>::template read_element<3,1>(b));
0939     write_mat_element<3,2>(r,a/mat_traits<B>::template read_element<3,2>(b));
0940     write_mat_element<3,3>(r,a/mat_traits<B>::template read_element<3,3>(b));
0941     return r;
0942     }
0943 
0944 namespace
0945 sfinae
0946     {
0947     using ::boost::qvm::operator/;
0948     }
0949 
0950 namespace
0951 qvm_detail
0952     {
0953     template <int R,int C>
0954     struct div_sm_defined;
0955 
0956     template <>
0957     struct
0958     div_sm_defined<4,4>
0959         {
0960         static bool const value=true;
0961         };
0962     }
0963 
0964 template <class A,class B>
0965 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
0966 typename lazy_enable_if_c<
0967     mat_traits<A>::rows==4 && mat_traits<A>::cols==1 && is_scalar<B>::value,
0968     deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
0969 operator/( A const & a, B b )
0970     {
0971     typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
0972     R r;
0973     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)/b);
0974     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a)/b);
0975     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a)/b);
0976     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a)/b);
0977     return r;
0978     }
0979 
0980 namespace
0981 sfinae
0982     {
0983     using ::boost::qvm::operator/;
0984     }
0985 
0986 namespace
0987 qvm_detail
0988     {
0989     template <int R,int C>
0990     struct div_ms_defined;
0991 
0992     template <>
0993     struct
0994     div_ms_defined<4,1>
0995         {
0996         static bool const value=true;
0997         };
0998     }
0999 
1000 template <class A,class B>
1001 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1002 typename lazy_enable_if_c<
1003     is_scalar<A>::value && mat_traits<B>::rows==4 && mat_traits<B>::cols==1,
1004     deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols> >::type
1005 operator/( A a, B const & b )
1006     {
1007     typedef typename deduce_mat2<A,B,mat_traits<B>::rows,mat_traits<B>::cols>::type R;
1008     R r;
1009     write_mat_element<0,0>(r,a/mat_traits<B>::template read_element<0,0>(b));
1010     write_mat_element<1,0>(r,a/mat_traits<B>::template read_element<1,0>(b));
1011     write_mat_element<2,0>(r,a/mat_traits<B>::template read_element<2,0>(b));
1012     write_mat_element<3,0>(r,a/mat_traits<B>::template read_element<3,0>(b));
1013     return r;
1014     }
1015 
1016 namespace
1017 sfinae
1018     {
1019     using ::boost::qvm::operator/;
1020     }
1021 
1022 namespace
1023 qvm_detail
1024     {
1025     template <int R,int C>
1026     struct div_sm_defined;
1027 
1028     template <>
1029     struct
1030     div_sm_defined<4,1>
1031         {
1032         static bool const value=true;
1033         };
1034     }
1035 
1036 template <class A,class B>
1037 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1038 typename lazy_enable_if_c<
1039     mat_traits<A>::rows==1 && mat_traits<A>::cols==4 && is_scalar<B>::value,
1040     deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
1041 operator/( A const & a, B b )
1042     {
1043     typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
1044     R r;
1045     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a)/b);
1046     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a)/b);
1047     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a)/b);
1048     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a)/b);
1049     return r;
1050     }
1051 
1052 namespace
1053 sfinae
1054     {
1055     using ::boost::qvm::operator/;
1056     }
1057 
1058 namespace
1059 qvm_detail
1060     {
1061     template <int R,int C>
1062     struct div_ms_defined;
1063 
1064     template <>
1065     struct
1066     div_ms_defined<1,4>
1067         {
1068         static bool const value=true;
1069         };
1070     }
1071 
1072 template <class A,class B>
1073 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1074 typename enable_if_c<
1075     mat_traits<A>::rows==4 && mat_traits<A>::cols==4 && is_scalar<B>::value,
1076     A &>::type
1077 operator/=( A & a, B b )
1078     {
1079     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)/b);
1080     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)/b);
1081     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)/b);
1082     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)/b);
1083     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)/b);
1084     write_mat_element<1,1>(a,mat_traits<A>::template read_element<1,1>(a)/b);
1085     write_mat_element<1,2>(a,mat_traits<A>::template read_element<1,2>(a)/b);
1086     write_mat_element<1,3>(a,mat_traits<A>::template read_element<1,3>(a)/b);
1087     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)/b);
1088     write_mat_element<2,1>(a,mat_traits<A>::template read_element<2,1>(a)/b);
1089     write_mat_element<2,2>(a,mat_traits<A>::template read_element<2,2>(a)/b);
1090     write_mat_element<2,3>(a,mat_traits<A>::template read_element<2,3>(a)/b);
1091     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)/b);
1092     write_mat_element<3,1>(a,mat_traits<A>::template read_element<3,1>(a)/b);
1093     write_mat_element<3,2>(a,mat_traits<A>::template read_element<3,2>(a)/b);
1094     write_mat_element<3,3>(a,mat_traits<A>::template read_element<3,3>(a)/b);
1095     return a;
1096     }
1097 
1098 namespace
1099 sfinae
1100     {
1101     using ::boost::qvm::operator/=;
1102     }
1103 
1104 namespace
1105 qvm_detail
1106     {
1107     template <int R,int C>
1108     struct div_eq_ms_defined;
1109 
1110     template <>
1111     struct
1112     div_eq_ms_defined<4,4>
1113         {
1114         static bool const value=true;
1115         };
1116     }
1117 
1118 template <class A,class B>
1119 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1120 typename enable_if_c<
1121     mat_traits<A>::rows==4 && mat_traits<A>::cols==1 && is_scalar<B>::value,
1122     A &>::type
1123 operator/=( A & a, B b )
1124     {
1125     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)/b);
1126     write_mat_element<1,0>(a,mat_traits<A>::template read_element<1,0>(a)/b);
1127     write_mat_element<2,0>(a,mat_traits<A>::template read_element<2,0>(a)/b);
1128     write_mat_element<3,0>(a,mat_traits<A>::template read_element<3,0>(a)/b);
1129     return a;
1130     }
1131 
1132 namespace
1133 sfinae
1134     {
1135     using ::boost::qvm::operator/=;
1136     }
1137 
1138 namespace
1139 qvm_detail
1140     {
1141     template <int R,int C>
1142     struct div_eq_ms_defined;
1143 
1144     template <>
1145     struct
1146     div_eq_ms_defined<4,1>
1147         {
1148         static bool const value=true;
1149         };
1150     }
1151 
1152 template <class A,class B>
1153 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1154 typename enable_if_c<
1155     mat_traits<A>::rows==1 && mat_traits<A>::cols==4 && is_scalar<B>::value,
1156     A &>::type
1157 operator/=( A & a, B b )
1158     {
1159     write_mat_element<0,0>(a,mat_traits<A>::template read_element<0,0>(a)/b);
1160     write_mat_element<0,1>(a,mat_traits<A>::template read_element<0,1>(a)/b);
1161     write_mat_element<0,2>(a,mat_traits<A>::template read_element<0,2>(a)/b);
1162     write_mat_element<0,3>(a,mat_traits<A>::template read_element<0,3>(a)/b);
1163     return a;
1164     }
1165 
1166 namespace
1167 sfinae
1168     {
1169     using ::boost::qvm::operator/=;
1170     }
1171 
1172 namespace
1173 qvm_detail
1174     {
1175     template <int R,int C>
1176     struct div_eq_ms_defined;
1177 
1178     template <>
1179     struct
1180     div_eq_ms_defined<1,4>
1181         {
1182         static bool const value=true;
1183         };
1184     }
1185 
1186 template <class R,class A>
1187 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1188 typename enable_if_c<
1189     mat_traits<R>::rows==4 && mat_traits<A>::rows==4 &&
1190     mat_traits<R>::cols==4 && mat_traits<A>::cols==4,
1191     R>::type
1192 convert_to( A const & a )
1193     {
1194     R r;
1195     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a));
1196     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a));
1197     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a));
1198     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a));
1199     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a));
1200     write_mat_element<1,1>(r,mat_traits<A>::template read_element<1,1>(a));
1201     write_mat_element<1,2>(r,mat_traits<A>::template read_element<1,2>(a));
1202     write_mat_element<1,3>(r,mat_traits<A>::template read_element<1,3>(a));
1203     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a));
1204     write_mat_element<2,1>(r,mat_traits<A>::template read_element<2,1>(a));
1205     write_mat_element<2,2>(r,mat_traits<A>::template read_element<2,2>(a));
1206     write_mat_element<2,3>(r,mat_traits<A>::template read_element<2,3>(a));
1207     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a));
1208     write_mat_element<3,1>(r,mat_traits<A>::template read_element<3,1>(a));
1209     write_mat_element<3,2>(r,mat_traits<A>::template read_element<3,2>(a));
1210     write_mat_element<3,3>(r,mat_traits<A>::template read_element<3,3>(a));
1211     return r;
1212     }
1213 
1214 template <class R,class A>
1215 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE
1216 typename enable_if_c<
1217     is_mat<R>::value && is_quat<A>::value &&
1218     mat_traits<R>::rows==4 && mat_traits<R>::cols==4,
1219     R>::type
1220 convert_to( A const & q )
1221     {
1222     typedef typename mat_traits<R>::scalar_type T;
1223     T const a=quat_traits<A>::template read_element<0>(q);
1224     T const b=quat_traits<A>::template read_element<1>(q);
1225     T const c=quat_traits<A>::template read_element<2>(q);
1226     T const d=quat_traits<A>::template read_element<3>(q);
1227     T const bb = b*b;
1228     T const cc = c*c;
1229     T const dd = d*d;
1230     T const bc = b*c;
1231     T const bd = b*d;
1232     T const cd = c*d;
1233     T const ab = a*b;
1234     T const ac = a*c;
1235     T const ad = a*d;
1236     T const zero = scalar_traits<T>::value(0);
1237     T const one = scalar_traits<T>::value(1);
1238     T const two = one+one;
1239     R r;
1240     write_mat_element<0,0>(r,one - two*(cc+dd));
1241     write_mat_element<0,1>(r,two*(bc-ad));
1242     write_mat_element<0,2>(r,two*(bd+ac));
1243     write_mat_element<0,3>(r,zero);
1244     write_mat_element<1,0>(r,two*(bc+ad));
1245     write_mat_element<1,1>(r,one - two*(bb+dd));
1246     write_mat_element<1,2>(r,two*(cd-ab));
1247     write_mat_element<1,3>(r,zero);
1248     write_mat_element<2,0>(r,two*(bd-ac));
1249     write_mat_element<2,1>(r,two*(cd+ab));
1250     write_mat_element<2,2>(r,one - two*(bb+cc));
1251     write_mat_element<2,3>(r,zero);
1252     write_mat_element<3,0>(r,zero);
1253     write_mat_element<3,1>(r,zero);
1254     write_mat_element<3,2>(r,zero);
1255     write_mat_element<3,3>(r,one);
1256     return r;
1257     }
1258 
1259 namespace
1260 sfinae
1261     {
1262     using ::boost::qvm::convert_to;
1263     }
1264 
1265 namespace
1266 qvm_detail
1267     {
1268     template <int R,int C>
1269     struct convert_to_m_defined;
1270 
1271     template <>
1272     struct
1273     convert_to_m_defined<4,4>
1274         {
1275         static bool const value=true;
1276         };
1277     }
1278 
1279 template <class R,class A>
1280 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1281 typename enable_if_c<
1282     mat_traits<R>::rows==4 && mat_traits<A>::rows==4 &&
1283     mat_traits<R>::cols==1 && mat_traits<A>::cols==1,
1284     R>::type
1285 convert_to( A const & a )
1286     {
1287     R r;
1288     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a));
1289     write_mat_element<1,0>(r,mat_traits<A>::template read_element<1,0>(a));
1290     write_mat_element<2,0>(r,mat_traits<A>::template read_element<2,0>(a));
1291     write_mat_element<3,0>(r,mat_traits<A>::template read_element<3,0>(a));
1292     return r;
1293     }
1294 
1295 namespace
1296 sfinae
1297     {
1298     using ::boost::qvm::convert_to;
1299     }
1300 
1301 namespace
1302 qvm_detail
1303     {
1304     template <int R,int C>
1305     struct convert_to_m_defined;
1306 
1307     template <>
1308     struct
1309     convert_to_m_defined<4,1>
1310         {
1311         static bool const value=true;
1312         };
1313     }
1314 
1315 template <class R,class A>
1316 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1317 typename enable_if_c<
1318     mat_traits<R>::rows==1 && mat_traits<A>::rows==1 &&
1319     mat_traits<R>::cols==4 && mat_traits<A>::cols==4,
1320     R>::type
1321 convert_to( A const & a )
1322     {
1323     R r;
1324     write_mat_element<0,0>(r,mat_traits<A>::template read_element<0,0>(a));
1325     write_mat_element<0,1>(r,mat_traits<A>::template read_element<0,1>(a));
1326     write_mat_element<0,2>(r,mat_traits<A>::template read_element<0,2>(a));
1327     write_mat_element<0,3>(r,mat_traits<A>::template read_element<0,3>(a));
1328     return r;
1329     }
1330 
1331 namespace
1332 sfinae
1333     {
1334     using ::boost::qvm::convert_to;
1335     }
1336 
1337 namespace
1338 qvm_detail
1339     {
1340     template <int R,int C>
1341     struct convert_to_m_defined;
1342 
1343     template <>
1344     struct
1345     convert_to_m_defined<1,4>
1346         {
1347         static bool const value=true;
1348         };
1349     }
1350 
1351 template <class A,class B>
1352 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1353 typename enable_if_c<
1354     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
1355     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
1356     bool>::type
1357 operator==( A const & a, B const & b )
1358     {
1359     return
1360         mat_traits<A>::template read_element<0,0>(a)==mat_traits<B>::template read_element<0,0>(b) &&
1361         mat_traits<A>::template read_element<0,1>(a)==mat_traits<B>::template read_element<0,1>(b) &&
1362         mat_traits<A>::template read_element<0,2>(a)==mat_traits<B>::template read_element<0,2>(b) &&
1363         mat_traits<A>::template read_element<0,3>(a)==mat_traits<B>::template read_element<0,3>(b) &&
1364         mat_traits<A>::template read_element<1,0>(a)==mat_traits<B>::template read_element<1,0>(b) &&
1365         mat_traits<A>::template read_element<1,1>(a)==mat_traits<B>::template read_element<1,1>(b) &&
1366         mat_traits<A>::template read_element<1,2>(a)==mat_traits<B>::template read_element<1,2>(b) &&
1367         mat_traits<A>::template read_element<1,3>(a)==mat_traits<B>::template read_element<1,3>(b) &&
1368         mat_traits<A>::template read_element<2,0>(a)==mat_traits<B>::template read_element<2,0>(b) &&
1369         mat_traits<A>::template read_element<2,1>(a)==mat_traits<B>::template read_element<2,1>(b) &&
1370         mat_traits<A>::template read_element<2,2>(a)==mat_traits<B>::template read_element<2,2>(b) &&
1371         mat_traits<A>::template read_element<2,3>(a)==mat_traits<B>::template read_element<2,3>(b) &&
1372         mat_traits<A>::template read_element<3,0>(a)==mat_traits<B>::template read_element<3,0>(b) &&
1373         mat_traits<A>::template read_element<3,1>(a)==mat_traits<B>::template read_element<3,1>(b) &&
1374         mat_traits<A>::template read_element<3,2>(a)==mat_traits<B>::template read_element<3,2>(b) &&
1375         mat_traits<A>::template read_element<3,3>(a)==mat_traits<B>::template read_element<3,3>(b);
1376     }
1377 
1378 namespace
1379 sfinae
1380     {
1381     using ::boost::qvm::operator==;
1382     }
1383 
1384 namespace
1385 qvm_detail
1386     {
1387     template <int R,int C>
1388     struct eq_mm_defined;
1389 
1390     template <>
1391     struct
1392     eq_mm_defined<4,4>
1393         {
1394         static bool const value=true;
1395         };
1396     }
1397 
1398 template <class A,class B>
1399 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1400 typename enable_if_c<
1401     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
1402     mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
1403     bool>::type
1404 operator==( A const & a, B const & b )
1405     {
1406     return
1407         mat_traits<A>::template read_element<0,0>(a)==mat_traits<B>::template read_element<0,0>(b) &&
1408         mat_traits<A>::template read_element<1,0>(a)==mat_traits<B>::template read_element<1,0>(b) &&
1409         mat_traits<A>::template read_element<2,0>(a)==mat_traits<B>::template read_element<2,0>(b) &&
1410         mat_traits<A>::template read_element<3,0>(a)==mat_traits<B>::template read_element<3,0>(b);
1411     }
1412 
1413 namespace
1414 sfinae
1415     {
1416     using ::boost::qvm::operator==;
1417     }
1418 
1419 namespace
1420 qvm_detail
1421     {
1422     template <int R,int C>
1423     struct eq_mm_defined;
1424 
1425     template <>
1426     struct
1427     eq_mm_defined<4,1>
1428         {
1429         static bool const value=true;
1430         };
1431     }
1432 
1433 template <class A,class B>
1434 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1435 typename enable_if_c<
1436     mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
1437     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
1438     bool>::type
1439 operator==( A const & a, B const & b )
1440     {
1441     return
1442         mat_traits<A>::template read_element<0,0>(a)==mat_traits<B>::template read_element<0,0>(b) &&
1443         mat_traits<A>::template read_element<0,1>(a)==mat_traits<B>::template read_element<0,1>(b) &&
1444         mat_traits<A>::template read_element<0,2>(a)==mat_traits<B>::template read_element<0,2>(b) &&
1445         mat_traits<A>::template read_element<0,3>(a)==mat_traits<B>::template read_element<0,3>(b);
1446     }
1447 
1448 namespace
1449 sfinae
1450     {
1451     using ::boost::qvm::operator==;
1452     }
1453 
1454 namespace
1455 qvm_detail
1456     {
1457     template <int R,int C>
1458     struct eq_mm_defined;
1459 
1460     template <>
1461     struct
1462     eq_mm_defined<1,4>
1463         {
1464         static bool const value=true;
1465         };
1466     }
1467 
1468 template <class A,class B>
1469 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1470 typename enable_if_c<
1471     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
1472     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
1473     bool>::type
1474 operator!=( A const & a, B const & b )
1475     {
1476     return
1477         !(mat_traits<A>::template read_element<0,0>(a)==mat_traits<B>::template read_element<0,0>(b)) ||
1478         !(mat_traits<A>::template read_element<0,1>(a)==mat_traits<B>::template read_element<0,1>(b)) ||
1479         !(mat_traits<A>::template read_element<0,2>(a)==mat_traits<B>::template read_element<0,2>(b)) ||
1480         !(mat_traits<A>::template read_element<0,3>(a)==mat_traits<B>::template read_element<0,3>(b)) ||
1481         !(mat_traits<A>::template read_element<1,0>(a)==mat_traits<B>::template read_element<1,0>(b)) ||
1482         !(mat_traits<A>::template read_element<1,1>(a)==mat_traits<B>::template read_element<1,1>(b)) ||
1483         !(mat_traits<A>::template read_element<1,2>(a)==mat_traits<B>::template read_element<1,2>(b)) ||
1484         !(mat_traits<A>::template read_element<1,3>(a)==mat_traits<B>::template read_element<1,3>(b)) ||
1485         !(mat_traits<A>::template read_element<2,0>(a)==mat_traits<B>::template read_element<2,0>(b)) ||
1486         !(mat_traits<A>::template read_element<2,1>(a)==mat_traits<B>::template read_element<2,1>(b)) ||
1487         !(mat_traits<A>::template read_element<2,2>(a)==mat_traits<B>::template read_element<2,2>(b)) ||
1488         !(mat_traits<A>::template read_element<2,3>(a)==mat_traits<B>::template read_element<2,3>(b)) ||
1489         !(mat_traits<A>::template read_element<3,0>(a)==mat_traits<B>::template read_element<3,0>(b)) ||
1490         !(mat_traits<A>::template read_element<3,1>(a)==mat_traits<B>::template read_element<3,1>(b)) ||
1491         !(mat_traits<A>::template read_element<3,2>(a)==mat_traits<B>::template read_element<3,2>(b)) ||
1492         !(mat_traits<A>::template read_element<3,3>(a)==mat_traits<B>::template read_element<3,3>(b));
1493     }
1494 
1495 namespace
1496 sfinae
1497     {
1498     using ::boost::qvm::operator!=;
1499     }
1500 
1501 namespace
1502 qvm_detail
1503     {
1504     template <int R,int C>
1505     struct neq_mm_defined;
1506 
1507     template <>
1508     struct
1509     neq_mm_defined<4,4>
1510         {
1511         static bool const value=true;
1512         };
1513     }
1514 
1515 template <class A,class B>
1516 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1517 typename enable_if_c<
1518     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
1519     mat_traits<A>::cols==1 && mat_traits<B>::cols==1,
1520     bool>::type
1521 operator!=( A const & a, B const & b )
1522     {
1523     return
1524         !(mat_traits<A>::template read_element<0,0>(a)==mat_traits<B>::template read_element<0,0>(b)) ||
1525         !(mat_traits<A>::template read_element<1,0>(a)==mat_traits<B>::template read_element<1,0>(b)) ||
1526         !(mat_traits<A>::template read_element<2,0>(a)==mat_traits<B>::template read_element<2,0>(b)) ||
1527         !(mat_traits<A>::template read_element<3,0>(a)==mat_traits<B>::template read_element<3,0>(b));
1528     }
1529 
1530 namespace
1531 sfinae
1532     {
1533     using ::boost::qvm::operator!=;
1534     }
1535 
1536 namespace
1537 qvm_detail
1538     {
1539     template <int R,int C>
1540     struct neq_mm_defined;
1541 
1542     template <>
1543     struct
1544     neq_mm_defined<4,1>
1545         {
1546         static bool const value=true;
1547         };
1548     }
1549 
1550 template <class A,class B>
1551 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1552 typename enable_if_c<
1553     mat_traits<A>::rows==1 && mat_traits<B>::rows==1 &&
1554     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
1555     bool>::type
1556 operator!=( A const & a, B const & b )
1557     {
1558     return
1559         !(mat_traits<A>::template read_element<0,0>(a)==mat_traits<B>::template read_element<0,0>(b)) ||
1560         !(mat_traits<A>::template read_element<0,1>(a)==mat_traits<B>::template read_element<0,1>(b)) ||
1561         !(mat_traits<A>::template read_element<0,2>(a)==mat_traits<B>::template read_element<0,2>(b)) ||
1562         !(mat_traits<A>::template read_element<0,3>(a)==mat_traits<B>::template read_element<0,3>(b));
1563     }
1564 
1565 namespace
1566 sfinae
1567     {
1568     using ::boost::qvm::operator!=;
1569     }
1570 
1571 namespace
1572 qvm_detail
1573     {
1574     template <int R,int C>
1575     struct neq_mm_defined;
1576 
1577     template <>
1578     struct
1579     neq_mm_defined<1,4>
1580         {
1581         static bool const value=true;
1582         };
1583     }
1584 
1585 template <class A>
1586 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1587 typename lazy_enable_if_c<
1588     mat_traits<A>::rows==4 && mat_traits<A>::cols==4,
1589     deduce_mat<A> >::type
1590 operator-( A const & a )
1591     {
1592     typedef typename deduce_mat<A>::type R;
1593     R r;
1594     write_mat_element<0,0>(r,-mat_traits<A>::template read_element<0,0>(a));
1595     write_mat_element<0,1>(r,-mat_traits<A>::template read_element<0,1>(a));
1596     write_mat_element<0,2>(r,-mat_traits<A>::template read_element<0,2>(a));
1597     write_mat_element<0,3>(r,-mat_traits<A>::template read_element<0,3>(a));
1598     write_mat_element<1,0>(r,-mat_traits<A>::template read_element<1,0>(a));
1599     write_mat_element<1,1>(r,-mat_traits<A>::template read_element<1,1>(a));
1600     write_mat_element<1,2>(r,-mat_traits<A>::template read_element<1,2>(a));
1601     write_mat_element<1,3>(r,-mat_traits<A>::template read_element<1,3>(a));
1602     write_mat_element<2,0>(r,-mat_traits<A>::template read_element<2,0>(a));
1603     write_mat_element<2,1>(r,-mat_traits<A>::template read_element<2,1>(a));
1604     write_mat_element<2,2>(r,-mat_traits<A>::template read_element<2,2>(a));
1605     write_mat_element<2,3>(r,-mat_traits<A>::template read_element<2,3>(a));
1606     write_mat_element<3,0>(r,-mat_traits<A>::template read_element<3,0>(a));
1607     write_mat_element<3,1>(r,-mat_traits<A>::template read_element<3,1>(a));
1608     write_mat_element<3,2>(r,-mat_traits<A>::template read_element<3,2>(a));
1609     write_mat_element<3,3>(r,-mat_traits<A>::template read_element<3,3>(a));
1610     return r;
1611     }
1612 
1613 namespace
1614 sfinae
1615     {
1616     using ::boost::qvm::operator-;
1617     }
1618 
1619 namespace
1620 qvm_detail
1621     {
1622     template <int R,int C>
1623     struct minus_m_defined;
1624 
1625     template <>
1626     struct
1627     minus_m_defined<4,4>
1628         {
1629         static bool const value=true;
1630         };
1631     }
1632 
1633 template <class A>
1634 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1635 typename lazy_enable_if_c<
1636     mat_traits<A>::rows==4 && mat_traits<A>::cols==1,
1637     deduce_mat<A> >::type
1638 operator-( A const & a )
1639     {
1640     typedef typename deduce_mat<A>::type R;
1641     R r;
1642     write_mat_element<0,0>(r,-mat_traits<A>::template read_element<0,0>(a));
1643     write_mat_element<1,0>(r,-mat_traits<A>::template read_element<1,0>(a));
1644     write_mat_element<2,0>(r,-mat_traits<A>::template read_element<2,0>(a));
1645     write_mat_element<3,0>(r,-mat_traits<A>::template read_element<3,0>(a));
1646     return r;
1647     }
1648 
1649 namespace
1650 sfinae
1651     {
1652     using ::boost::qvm::operator-;
1653     }
1654 
1655 namespace
1656 qvm_detail
1657     {
1658     template <int R,int C>
1659     struct minus_m_defined;
1660 
1661     template <>
1662     struct
1663     minus_m_defined<4,1>
1664         {
1665         static bool const value=true;
1666         };
1667     }
1668 
1669 template <class A>
1670 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1671 typename lazy_enable_if_c<
1672     mat_traits<A>::rows==1 && mat_traits<A>::cols==4,
1673     deduce_mat<A> >::type
1674 operator-( A const & a )
1675     {
1676     typedef typename deduce_mat<A>::type R;
1677     R r;
1678     write_mat_element<0,0>(r,-mat_traits<A>::template read_element<0,0>(a));
1679     write_mat_element<0,1>(r,-mat_traits<A>::template read_element<0,1>(a));
1680     write_mat_element<0,2>(r,-mat_traits<A>::template read_element<0,2>(a));
1681     write_mat_element<0,3>(r,-mat_traits<A>::template read_element<0,3>(a));
1682     return r;
1683     }
1684 
1685 namespace
1686 sfinae
1687     {
1688     using ::boost::qvm::operator-;
1689     }
1690 
1691 namespace
1692 qvm_detail
1693     {
1694     template <int R,int C>
1695     struct minus_m_defined;
1696 
1697     template <>
1698     struct
1699     minus_m_defined<1,4>
1700         {
1701         static bool const value=true;
1702         };
1703     }
1704 
1705 template <class A>
1706 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1707 typename enable_if_c<
1708     mat_traits<A>::rows==4 && mat_traits<A>::cols==4,
1709     typename mat_traits<A>::scalar_type>::type
1710 determinant( A const & a )
1711     {
1712     typedef typename mat_traits<A>::scalar_type T;
1713     T const a00=mat_traits<A>::template read_element<0,0>(a);
1714     T const a01=mat_traits<A>::template read_element<0,1>(a);
1715     T const a02=mat_traits<A>::template read_element<0,2>(a);
1716     T const a03=mat_traits<A>::template read_element<0,3>(a);
1717     T const a10=mat_traits<A>::template read_element<1,0>(a);
1718     T const a11=mat_traits<A>::template read_element<1,1>(a);
1719     T const a12=mat_traits<A>::template read_element<1,2>(a);
1720     T const a13=mat_traits<A>::template read_element<1,3>(a);
1721     T const a20=mat_traits<A>::template read_element<2,0>(a);
1722     T const a21=mat_traits<A>::template read_element<2,1>(a);
1723     T const a22=mat_traits<A>::template read_element<2,2>(a);
1724     T const a23=mat_traits<A>::template read_element<2,3>(a);
1725     T const a30=mat_traits<A>::template read_element<3,0>(a);
1726     T const a31=mat_traits<A>::template read_element<3,1>(a);
1727     T const a32=mat_traits<A>::template read_element<3,2>(a);
1728     T const a33=mat_traits<A>::template read_element<3,3>(a);
1729     T det=(a00*(a11*(a22*a33-a23*a32)-a12*(a21*a33-a23*a31)+a13*(a21*a32-a22*a31))-a01*(a10*(a22*a33-a23*a32)-a12*(a20*a33-a23*a30)+a13*(a20*a32-a22*a30))+a02*(a10*(a21*a33-a23*a31)-a11*(a20*a33-a23*a30)+a13*(a20*a31-a21*a30))-a03*(a10*(a21*a32-a22*a31)-a11*(a20*a32-a22*a30)+a12*(a20*a31-a21*a30)));
1730     return det;
1731     }
1732 
1733 namespace
1734 sfinae
1735     {
1736     using ::boost::qvm::determinant;
1737     }
1738 
1739 namespace
1740 qvm_detail
1741     {
1742     template <int D>
1743     struct determinant_defined;
1744 
1745     template <>
1746     struct
1747     determinant_defined<4>
1748         {
1749         static bool const value=true;
1750         };
1751     }
1752 
1753 template <class A,class B>
1754 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1755 typename lazy_enable_if_c<
1756     mat_traits<A>::rows==4 && mat_traits<A>::cols==4 && is_scalar<B>::value,
1757     deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols> >::type
1758 inverse( A const & a, B det )
1759     {
1760     typedef typename mat_traits<A>::scalar_type T;
1761     BOOST_QVM_ASSERT(det!=scalar_traits<B>::value(0));
1762     T const a00=mat_traits<A>::template read_element<0,0>(a);
1763     T const a01=mat_traits<A>::template read_element<0,1>(a);
1764     T const a02=mat_traits<A>::template read_element<0,2>(a);
1765     T const a03=mat_traits<A>::template read_element<0,3>(a);
1766     T const a10=mat_traits<A>::template read_element<1,0>(a);
1767     T const a11=mat_traits<A>::template read_element<1,1>(a);
1768     T const a12=mat_traits<A>::template read_element<1,2>(a);
1769     T const a13=mat_traits<A>::template read_element<1,3>(a);
1770     T const a20=mat_traits<A>::template read_element<2,0>(a);
1771     T const a21=mat_traits<A>::template read_element<2,1>(a);
1772     T const a22=mat_traits<A>::template read_element<2,2>(a);
1773     T const a23=mat_traits<A>::template read_element<2,3>(a);
1774     T const a30=mat_traits<A>::template read_element<3,0>(a);
1775     T const a31=mat_traits<A>::template read_element<3,1>(a);
1776     T const a32=mat_traits<A>::template read_element<3,2>(a);
1777     T const a33=mat_traits<A>::template read_element<3,3>(a);
1778     T const f=scalar_traits<T>::value(1)/det;
1779     typedef typename deduce_mat2<A,B,mat_traits<A>::rows,mat_traits<A>::cols>::type R;
1780     R r;
1781     write_mat_element<0,0>(r, f*(a11*(a22*a33-a23*a32)-a12*(a21*a33-a23*a31)+a13*(a21*a32-a22*a31)));
1782     write_mat_element<0,1>(r,-f*(a01*(a22*a33-a23*a32)-a02*(a21*a33-a23*a31)+a03*(a21*a32-a22*a31)));
1783     write_mat_element<0,2>(r, f*(a01*(a12*a33-a13*a32)-a02*(a11*a33-a13*a31)+a03*(a11*a32-a12*a31)));
1784     write_mat_element<0,3>(r,-f*(a01*(a12*a23-a13*a22)-a02*(a11*a23-a13*a21)+a03*(a11*a22-a12*a21)));
1785     write_mat_element<1,0>(r,-f*(a10*(a22*a33-a23*a32)-a12*(a20*a33-a23*a30)+a13*(a20*a32-a22*a30)));
1786     write_mat_element<1,1>(r, f*(a00*(a22*a33-a23*a32)-a02*(a20*a33-a23*a30)+a03*(a20*a32-a22*a30)));
1787     write_mat_element<1,2>(r,-f*(a00*(a12*a33-a13*a32)-a02*(a10*a33-a13*a30)+a03*(a10*a32-a12*a30)));
1788     write_mat_element<1,3>(r, f*(a00*(a12*a23-a13*a22)-a02*(a10*a23-a13*a20)+a03*(a10*a22-a12*a20)));
1789     write_mat_element<2,0>(r, f*(a10*(a21*a33-a23*a31)-a11*(a20*a33-a23*a30)+a13*(a20*a31-a21*a30)));
1790     write_mat_element<2,1>(r,-f*(a00*(a21*a33-a23*a31)-a01*(a20*a33-a23*a30)+a03*(a20*a31-a21*a30)));
1791     write_mat_element<2,2>(r, f*(a00*(a11*a33-a13*a31)-a01*(a10*a33-a13*a30)+a03*(a10*a31-a11*a30)));
1792     write_mat_element<2,3>(r,-f*(a00*(a11*a23-a13*a21)-a01*(a10*a23-a13*a20)+a03*(a10*a21-a11*a20)));
1793     write_mat_element<3,0>(r,-f*(a10*(a21*a32-a22*a31)-a11*(a20*a32-a22*a30)+a12*(a20*a31-a21*a30)));
1794     write_mat_element<3,1>(r, f*(a00*(a21*a32-a22*a31)-a01*(a20*a32-a22*a30)+a02*(a20*a31-a21*a30)));
1795     write_mat_element<3,2>(r,-f*(a00*(a11*a32-a12*a31)-a01*(a10*a32-a12*a30)+a02*(a10*a31-a11*a30)));
1796     write_mat_element<3,3>(r, f*(a00*(a11*a22-a12*a21)-a01*(a10*a22-a12*a20)+a02*(a10*a21-a11*a20)));
1797     return r;
1798     }
1799 
1800 template <class A>
1801 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1802 typename lazy_enable_if_c<
1803     mat_traits<A>::rows==4 && mat_traits<A>::cols==4,
1804     deduce_mat<A> >::type
1805 inverse( A const & a )
1806     {
1807     typedef typename mat_traits<A>::scalar_type T;
1808     T det=determinant(a);
1809     if( det==scalar_traits<T>::value(0) )
1810         BOOST_QVM_THROW_EXCEPTION(zero_determinant_error());
1811     return inverse(a,det);
1812     }
1813 
1814 namespace
1815 sfinae
1816     {
1817     using ::boost::qvm::inverse;
1818     }
1819 
1820 namespace
1821 qvm_detail
1822     {
1823     template <int D>
1824     struct inverse_m_defined;
1825 
1826     template <>
1827     struct
1828     inverse_m_defined<4>
1829         {
1830         static bool const value=true;
1831         };
1832     }
1833 
1834 template <class A,class B>
1835 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1836 typename lazy_enable_if_c<
1837     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
1838     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
1839     deduce_mat2<A,B,4,4> >::type
1840 operator*( A const & a, B const & b )
1841     {
1842     typedef typename mat_traits<A>::scalar_type Ta;
1843     typedef typename mat_traits<B>::scalar_type Tb;
1844     Ta const a00 = mat_traits<A>::template read_element<0,0>(a);
1845     Ta const a01 = mat_traits<A>::template read_element<0,1>(a);
1846     Ta const a02 = mat_traits<A>::template read_element<0,2>(a);
1847     Ta const a03 = mat_traits<A>::template read_element<0,3>(a);
1848     Ta const a10 = mat_traits<A>::template read_element<1,0>(a);
1849     Ta const a11 = mat_traits<A>::template read_element<1,1>(a);
1850     Ta const a12 = mat_traits<A>::template read_element<1,2>(a);
1851     Ta const a13 = mat_traits<A>::template read_element<1,3>(a);
1852     Ta const a20 = mat_traits<A>::template read_element<2,0>(a);
1853     Ta const a21 = mat_traits<A>::template read_element<2,1>(a);
1854     Ta const a22 = mat_traits<A>::template read_element<2,2>(a);
1855     Ta const a23 = mat_traits<A>::template read_element<2,3>(a);
1856     Ta const a30 = mat_traits<A>::template read_element<3,0>(a);
1857     Ta const a31 = mat_traits<A>::template read_element<3,1>(a);
1858     Ta const a32 = mat_traits<A>::template read_element<3,2>(a);
1859     Ta const a33 = mat_traits<A>::template read_element<3,3>(a);
1860     Tb const b00 = mat_traits<B>::template read_element<0,0>(b);
1861     Tb const b01 = mat_traits<B>::template read_element<0,1>(b);
1862     Tb const b02 = mat_traits<B>::template read_element<0,2>(b);
1863     Tb const b03 = mat_traits<B>::template read_element<0,3>(b);
1864     Tb const b10 = mat_traits<B>::template read_element<1,0>(b);
1865     Tb const b11 = mat_traits<B>::template read_element<1,1>(b);
1866     Tb const b12 = mat_traits<B>::template read_element<1,2>(b);
1867     Tb const b13 = mat_traits<B>::template read_element<1,3>(b);
1868     Tb const b20 = mat_traits<B>::template read_element<2,0>(b);
1869     Tb const b21 = mat_traits<B>::template read_element<2,1>(b);
1870     Tb const b22 = mat_traits<B>::template read_element<2,2>(b);
1871     Tb const b23 = mat_traits<B>::template read_element<2,3>(b);
1872     Tb const b30 = mat_traits<B>::template read_element<3,0>(b);
1873     Tb const b31 = mat_traits<B>::template read_element<3,1>(b);
1874     Tb const b32 = mat_traits<B>::template read_element<3,2>(b);
1875     Tb const b33 = mat_traits<B>::template read_element<3,3>(b);
1876     typedef typename deduce_mat2<A,B,4,4>::type R;
1877     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==4);
1878     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==4);
1879     R r;
1880     write_mat_element<0,0>(r,a00*b00+a01*b10+a02*b20+a03*b30);
1881     write_mat_element<0,1>(r,a00*b01+a01*b11+a02*b21+a03*b31);
1882     write_mat_element<0,2>(r,a00*b02+a01*b12+a02*b22+a03*b32);
1883     write_mat_element<0,3>(r,a00*b03+a01*b13+a02*b23+a03*b33);
1884     write_mat_element<1,0>(r,a10*b00+a11*b10+a12*b20+a13*b30);
1885     write_mat_element<1,1>(r,a10*b01+a11*b11+a12*b21+a13*b31);
1886     write_mat_element<1,2>(r,a10*b02+a11*b12+a12*b22+a13*b32);
1887     write_mat_element<1,3>(r,a10*b03+a11*b13+a12*b23+a13*b33);
1888     write_mat_element<2,0>(r,a20*b00+a21*b10+a22*b20+a23*b30);
1889     write_mat_element<2,1>(r,a20*b01+a21*b11+a22*b21+a23*b31);
1890     write_mat_element<2,2>(r,a20*b02+a21*b12+a22*b22+a23*b32);
1891     write_mat_element<2,3>(r,a20*b03+a21*b13+a22*b23+a23*b33);
1892     write_mat_element<3,0>(r,a30*b00+a31*b10+a32*b20+a33*b30);
1893     write_mat_element<3,1>(r,a30*b01+a31*b11+a32*b21+a33*b31);
1894     write_mat_element<3,2>(r,a30*b02+a31*b12+a32*b22+a33*b32);
1895     write_mat_element<3,3>(r,a30*b03+a31*b13+a32*b23+a33*b33);
1896     return r;
1897     }
1898 
1899 namespace
1900 sfinae
1901     {
1902     using ::boost::qvm::operator*;
1903     }
1904 
1905 namespace
1906 qvm_detail
1907     {
1908     template <int R,int /*CR*/,int C>
1909     struct mul_mm_defined;
1910 
1911     template <>
1912     struct
1913     mul_mm_defined<4,4,4>
1914         {
1915         static bool const value=true;
1916         };
1917     }
1918 
1919 template <class A,class B>
1920 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
1921 typename enable_if_c<
1922     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
1923     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
1924     A &>::type
1925 operator*=( A & a, B const & b )
1926     {
1927     typedef typename mat_traits<A>::scalar_type Ta;
1928     typedef typename mat_traits<B>::scalar_type Tb;
1929     Ta const a00 = mat_traits<A>::template read_element<0,0>(a);
1930     Ta const a01 = mat_traits<A>::template read_element<0,1>(a);
1931     Ta const a02 = mat_traits<A>::template read_element<0,2>(a);
1932     Ta const a03 = mat_traits<A>::template read_element<0,3>(a);
1933     Ta const a10 = mat_traits<A>::template read_element<1,0>(a);
1934     Ta const a11 = mat_traits<A>::template read_element<1,1>(a);
1935     Ta const a12 = mat_traits<A>::template read_element<1,2>(a);
1936     Ta const a13 = mat_traits<A>::template read_element<1,3>(a);
1937     Ta const a20 = mat_traits<A>::template read_element<2,0>(a);
1938     Ta const a21 = mat_traits<A>::template read_element<2,1>(a);
1939     Ta const a22 = mat_traits<A>::template read_element<2,2>(a);
1940     Ta const a23 = mat_traits<A>::template read_element<2,3>(a);
1941     Ta const a30 = mat_traits<A>::template read_element<3,0>(a);
1942     Ta const a31 = mat_traits<A>::template read_element<3,1>(a);
1943     Ta const a32 = mat_traits<A>::template read_element<3,2>(a);
1944     Ta const a33 = mat_traits<A>::template read_element<3,3>(a);
1945     Tb const b00 = mat_traits<B>::template read_element<0,0>(b);
1946     Tb const b01 = mat_traits<B>::template read_element<0,1>(b);
1947     Tb const b02 = mat_traits<B>::template read_element<0,2>(b);
1948     Tb const b03 = mat_traits<B>::template read_element<0,3>(b);
1949     Tb const b10 = mat_traits<B>::template read_element<1,0>(b);
1950     Tb const b11 = mat_traits<B>::template read_element<1,1>(b);
1951     Tb const b12 = mat_traits<B>::template read_element<1,2>(b);
1952     Tb const b13 = mat_traits<B>::template read_element<1,3>(b);
1953     Tb const b20 = mat_traits<B>::template read_element<2,0>(b);
1954     Tb const b21 = mat_traits<B>::template read_element<2,1>(b);
1955     Tb const b22 = mat_traits<B>::template read_element<2,2>(b);
1956     Tb const b23 = mat_traits<B>::template read_element<2,3>(b);
1957     Tb const b30 = mat_traits<B>::template read_element<3,0>(b);
1958     Tb const b31 = mat_traits<B>::template read_element<3,1>(b);
1959     Tb const b32 = mat_traits<B>::template read_element<3,2>(b);
1960     Tb const b33 = mat_traits<B>::template read_element<3,3>(b);
1961     write_mat_element<0,0>(a,a00*b00+a01*b10+a02*b20+a03*b30);
1962     write_mat_element<0,1>(a,a00*b01+a01*b11+a02*b21+a03*b31);
1963     write_mat_element<0,2>(a,a00*b02+a01*b12+a02*b22+a03*b32);
1964     write_mat_element<0,3>(a,a00*b03+a01*b13+a02*b23+a03*b33);
1965     write_mat_element<1,0>(a,a10*b00+a11*b10+a12*b20+a13*b30);
1966     write_mat_element<1,1>(a,a10*b01+a11*b11+a12*b21+a13*b31);
1967     write_mat_element<1,2>(a,a10*b02+a11*b12+a12*b22+a13*b32);
1968     write_mat_element<1,3>(a,a10*b03+a11*b13+a12*b23+a13*b33);
1969     write_mat_element<2,0>(a,a20*b00+a21*b10+a22*b20+a23*b30);
1970     write_mat_element<2,1>(a,a20*b01+a21*b11+a22*b21+a23*b31);
1971     write_mat_element<2,2>(a,a20*b02+a21*b12+a22*b22+a23*b32);
1972     write_mat_element<2,3>(a,a20*b03+a21*b13+a22*b23+a23*b33);
1973     write_mat_element<3,0>(a,a30*b00+a31*b10+a32*b20+a33*b30);
1974     write_mat_element<3,1>(a,a30*b01+a31*b11+a32*b21+a33*b31);
1975     write_mat_element<3,2>(a,a30*b02+a31*b12+a32*b22+a33*b32);
1976     write_mat_element<3,3>(a,a30*b03+a31*b13+a32*b23+a33*b33);
1977     return a;
1978     }
1979 
1980 namespace
1981 sfinae
1982     {
1983     using ::boost::qvm::operator*=;
1984     }
1985 
1986 namespace
1987 qvm_detail
1988     {
1989     template <int D>
1990     struct mul_eq_mm_defined;
1991 
1992     template <>
1993     struct
1994     mul_eq_mm_defined<4>
1995         {
1996         static bool const value=true;
1997         };
1998     }
1999 
2000 template <class A,class B>
2001 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
2002 typename lazy_enable_if_c<
2003     mat_traits<A>::rows==4 && mat_traits<B>::rows==4 &&
2004     mat_traits<A>::cols==4 && mat_traits<B>::cols==1,
2005     deduce_mat2<A,B,4,1> >::type
2006 operator*( A const & a, B const & b )
2007     {
2008     typedef typename mat_traits<A>::scalar_type Ta;
2009     typedef typename mat_traits<B>::scalar_type Tb;
2010     Ta const a00 = mat_traits<A>::template read_element<0,0>(a);
2011     Ta const a01 = mat_traits<A>::template read_element<0,1>(a);
2012     Ta const a02 = mat_traits<A>::template read_element<0,2>(a);
2013     Ta const a03 = mat_traits<A>::template read_element<0,3>(a);
2014     Ta const a10 = mat_traits<A>::template read_element<1,0>(a);
2015     Ta const a11 = mat_traits<A>::template read_element<1,1>(a);
2016     Ta const a12 = mat_traits<A>::template read_element<1,2>(a);
2017     Ta const a13 = mat_traits<A>::template read_element<1,3>(a);
2018     Ta const a20 = mat_traits<A>::template read_element<2,0>(a);
2019     Ta const a21 = mat_traits<A>::template read_element<2,1>(a);
2020     Ta const a22 = mat_traits<A>::template read_element<2,2>(a);
2021     Ta const a23 = mat_traits<A>::template read_element<2,3>(a);
2022     Ta const a30 = mat_traits<A>::template read_element<3,0>(a);
2023     Ta const a31 = mat_traits<A>::template read_element<3,1>(a);
2024     Ta const a32 = mat_traits<A>::template read_element<3,2>(a);
2025     Ta const a33 = mat_traits<A>::template read_element<3,3>(a);
2026     Tb const b00 = mat_traits<B>::template read_element<0,0>(b);
2027     Tb const b10 = mat_traits<B>::template read_element<1,0>(b);
2028     Tb const b20 = mat_traits<B>::template read_element<2,0>(b);
2029     Tb const b30 = mat_traits<B>::template read_element<3,0>(b);
2030     typedef typename deduce_mat2<A,B,4,1>::type R;
2031     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==4);
2032     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==1);
2033     R r;
2034     write_mat_element<0,0>(r,a00*b00+a01*b10+a02*b20+a03*b30);
2035     write_mat_element<1,0>(r,a10*b00+a11*b10+a12*b20+a13*b30);
2036     write_mat_element<2,0>(r,a20*b00+a21*b10+a22*b20+a23*b30);
2037     write_mat_element<3,0>(r,a30*b00+a31*b10+a32*b20+a33*b30);
2038     return r;
2039     }
2040 
2041 namespace
2042 sfinae
2043     {
2044     using ::boost::qvm::operator*;
2045     }
2046 
2047 namespace
2048 qvm_detail
2049     {
2050     template <int R,int /*CR*/,int C>
2051     struct mul_mm_defined;
2052 
2053     template <>
2054     struct
2055     mul_mm_defined<4,4,1>
2056         {
2057         static bool const value=true;
2058         };
2059     }
2060 
2061 template <class A,class B>
2062 BOOST_QVM_CONSTEXPR BOOST_QVM_INLINE_OPERATIONS
2063 typename lazy_enable_if_c<
2064     mat_traits<A>::rows==1 && mat_traits<B>::rows==4 &&
2065     mat_traits<A>::cols==4 && mat_traits<B>::cols==4,
2066     deduce_mat2<A,B,1,4> >::type
2067 operator*( A const & a, B const & b )
2068     {
2069     typedef typename mat_traits<A>::scalar_type Ta;
2070     typedef typename mat_traits<B>::scalar_type Tb;
2071     Ta const a00 = mat_traits<A>::template read_element<0,0>(a);
2072     Ta const a01 = mat_traits<A>::template read_element<0,1>(a);
2073     Ta const a02 = mat_traits<A>::template read_element<0,2>(a);
2074     Ta const a03 = mat_traits<A>::template read_element<0,3>(a);
2075     Tb const b00 = mat_traits<B>::template read_element<0,0>(b);
2076     Tb const b01 = mat_traits<B>::template read_element<0,1>(b);
2077     Tb const b02 = mat_traits<B>::template read_element<0,2>(b);
2078     Tb const b03 = mat_traits<B>::template read_element<0,3>(b);
2079     Tb const b10 = mat_traits<B>::template read_element<1,0>(b);
2080     Tb const b11 = mat_traits<B>::template read_element<1,1>(b);
2081     Tb const b12 = mat_traits<B>::template read_element<1,2>(b);
2082     Tb const b13 = mat_traits<B>::template read_element<1,3>(b);
2083     Tb const b20 = mat_traits<B>::template read_element<2,0>(b);
2084     Tb const b21 = mat_traits<B>::template read_element<2,1>(b);
2085     Tb const b22 = mat_traits<B>::template read_element<2,2>(b);
2086     Tb const b23 = mat_traits<B>::template read_element<2,3>(b);
2087     Tb const b30 = mat_traits<B>::template read_element<3,0>(b);
2088     Tb const b31 = mat_traits<B>::template read_element<3,1>(b);
2089     Tb const b32 = mat_traits<B>::template read_element<3,2>(b);
2090     Tb const b33 = mat_traits<B>::template read_element<3,3>(b);
2091     typedef typename deduce_mat2<A,B,1,4>::type R;
2092     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows==1);
2093     BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols==4);
2094     R r;
2095     write_mat_element<0,0>(r,a00*b00+a01*b10+a02*b20+a03*b30);
2096     write_mat_element<0,1>(r,a00*b01+a01*b11+a02*b21+a03*b31);
2097     write_mat_element<0,2>(r,a00*b02+a01*b12+a02*b22+a03*b32);
2098     write_mat_element<0,3>(r,a00*b03+a01*b13+a02*b23+a03*b33);
2099     return r;
2100     }
2101 
2102 namespace
2103 sfinae
2104     {
2105     using ::boost::qvm::operator*;
2106     }
2107 
2108 namespace
2109 qvm_detail
2110     {
2111     template <int R,int /*CR*/,int C>
2112     struct mul_mm_defined;
2113 
2114     template <>
2115     struct
2116     mul_mm_defined<1,4,4>
2117         {
2118         static bool const value=true;
2119         };
2120     }
2121 
2122 } }
2123 
2124 #endif