//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc. //Distributed under the Boost Software License, Version 1.0. (See accompanying //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "boost/throw_exception.hpp" #include "boost/exception/info.hpp" #include "boost/exception/diagnostic_information.hpp" #include "boost/bind.hpp" #include #include #include #include #include #include #include #include #include #include #define NL "\n" #define TAB " " #define TAB1 TAB #define TAB2 TAB TAB #define TAB3 TAB TAB TAB #define TAB4 TAB TAB TAB TAB #define TAB5 TAB TAB TAB TAB TAB #define INCLUDE_MAT_ASSIGN "boost/qvm/gen/mat_assign%d.hpp" #define INCLUDE_VEC_ASSIGN "boost/qvm/gen/vec_assign%d.hpp" #define INCLUDE_STATIC_ASSERT "boost/qvm/static_assert.hpp" #define INCLUDE_MATH "boost/qvm/math.hpp" #define INCLUDE_THROW_EXCEPTION "boost/qvm/throw_exception.hpp" #define INCLUDE_ERROR "boost/qvm/error.hpp" #define INCLUDE_INLINE "boost/qvm/inline.hpp" #define INCLUDE_M_TRAITS "boost/qvm/mat_traits.hpp" #define INCLUDE_V_TRAITS "boost/qvm/vec_traits.hpp" #define INCLUDE_Q_TRAITS "boost/qvm/quat_traits.hpp" #define INCLUDE_S_TRAITS "boost/qvm/scalar_traits.hpp" #define INCLUDE_DEDUCE_M "boost/qvm/deduce_mat.hpp" #define INCLUDE_DEDUCE_V "boost/qvm/deduce_vec.hpp" #define INCLUDE_DEDUCE_Q "boost/qvm/deduce_quat.hpp" #define INCLUDE_DEDUCE_S "boost/qvm/deduce_scalar.hpp" #define INCLUDE_SWIZZLE_TRAITS "boost/qvm/detail/swizzle_traits.hpp" #define INCLUDE_ENABLE_IF "boost/qvm/enable_if.hpp" #define INCLUDE_ASSERT "boost/qvm/assert.hpp" namespace { struct exception_base: virtual std::exception, virtual boost::exception { }; struct bad_command_line: virtual exception_base { }; typedef boost::error_info cmd_arg; struct null_deleter { template void operator()( T * ) const { } }; std::string get_include_guard() { std::ostringstream s; s << std::setw(2) << std::setfill('0') << std::hex << std::uppercase; s<<"BOOST_QVM_"; for( int i=0; i!=16; ++i ) s<<(rand()%256); return s.str(); } template std::string to_string( T const & x ) { std::ostringstream s; s< includes_; public: explicit output_file( command_line_options const & opt ): output_directory(opt.output_directory), con(opt.con) { } void require_include( std::string const & fn ) { assert(!strchr(fn.c_str(),'%')); includes_.insert(fn); }; std::ostream & stream() { return out_; } void dump( std::string const & name ) const { std::ostream * out = &std::cout; boost::shared_ptr f; if( !con ) { std::string path; if( !output_directory.empty() ) { path+=output_directory; path+='/'; path+=name; } boost::shared_ptr(new std::ofstream(path.c_str())).swap(f); out = f.get(); std::cout << "Writing " << path << "..." << std::endl; } out->exceptions(std::ofstream::eofbit|std::ofstream::failbit|std::ofstream::badbit); std::string include_guard=get_include_guard(); *out << "//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc." NL NL "//Distributed under the Boost Software License, Version 1.0. (See accompanying" NL "//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)" NL NL "#ifndef " << include_guard << NL "#define " << include_guard << NL NL "//This file was generated by a program. Do not edit manually." NL NL ; for( std::set::const_iterator i=includes_.begin(),e=includes_.end(); i!=e; ++i ) *out << "#include <" << *i << ">" NL; *out << NL "namespace" NL "boost" NL TAB1 "{" NL TAB1 "namespace" NL TAB1 "qvm" NL TAB2 "{" NL << out_.str() << TAB2 "}" NL TAB1 "}" NL NL "#endif" NL ; } }; void replace( std::string & s, char const * substr, char const * newstr ) { assert(substr && *substr); assert(newstr && *newstr); std::string::size_type f=s.find(substr); if( s.npos!=f ) s.replace(f,f+strlen(substr),newstr); } std::string deduce_name( std::string const & fn, char const * suffix ) { std::string s=fn; replace(s,"operator==","eq"); replace(s,"operator!=","neq"); replace(s,"operator+=","plus_eq"); replace(s,"operator-=","minus_eq"); replace(s,"operator*=","mul_eq"); replace(s,"operator/=","div_eq"); replace(s,"operator+","plus"); replace(s,"operator-","minus"); replace(s,"operator*","mul"); replace(s,"operator/","div"); if( suffix ) { s += '_'; s += suffix; } return s; } void header_mr_ma_mb_same_size( output_file & out, int r, int c, std::string const & name ) { assert(r>0); assert(c>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_M); out.stream() << TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::rows=="<::cols=="<::cols=="< >::type" NL TAB2<0); assert(n>0); assert(p>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_M); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::rows=="<::cols=="<::cols=="< >::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="<::dim=="< >::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="<::dim=="< >::type" NL TAB2<0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits::dim=="<::dim=="< >::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits::rows=="<::rows=="<::cols=="<::cols=="<::type" NL TAB2<0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits::dim=="<::dim=="<::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits::rows=="<::rows=="<::cols=="<::cols=="<::type" NL TAB2<0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits::dim=="<::dim=="<::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="<::scalar_type>::type" NL TAB2<0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_S); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits::dim=="<::dim=="<::scalar_type,typename vec_traits::scalar_type> >::type" NL TAB2<0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "is_vec::value && vec_traits::dim=="<::scalar_type>::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_M); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="< >::type" NL TAB2<0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits::dim=="< >::type" NL TAB2<0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "is_vec::value &&" NL TAB3 "vec_traits::dim=="<::dim=="<::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_M); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="<::value," NL TAB3 "deduce_mat >::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_M); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "is_scalar::value && mat_traits::rows=="<::cols=="< >::type" NL TAB2<0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits::dim=="<::value," NL TAB3 "deduce_vec >::type" NL TAB2<0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "is_scalar::value && vec_traits::dim=="< >::type" NL TAB2<0); assert(c>0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="<::value," NL TAB3 "A &>::type" NL TAB2<0); assert(!name.empty()); out.stream()<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits::dim=="<::value," NL TAB3 "A &>::type" NL TAB2<0); assert(cr>0); assert(c>0); assert(!fn.empty()); std::string dn=deduce_name(fn,suffix); std::string name=dn+"_defined"; g<< NL TAB2 "namespace" NL TAB2 "sfinae" NL TAB3 "{" NL TAB3 "using ::boost::qvm::"<" NL TAB3 "struct "<" NL TAB3 "struct" NL TAB3<" NL TAB4"{" NL TAB4"static bool const value=true;" NL TAB4"};" NL TAB3 "}" NL NL ; } void defined( std::ostream & g, int r, int c, std::string const & fn, char const * suffix ) { assert(r>0); assert(c>0); assert(!fn.empty()); std::string dn=deduce_name(fn,suffix); std::string name=dn+"_defined"; g<< NL TAB2 "namespace" NL TAB2 "sfinae" NL TAB3 "{" NL TAB3 "using ::boost::qvm::"<" NL TAB3 "struct "<" NL TAB3 "struct" NL TAB3<" NL TAB4"{" NL TAB4"static bool const value=true;" NL TAB4"};" NL TAB3 "}" NL NL ; } void defined( std::ostream & g, int d, std::string const & fn, char const * suffix ) { assert(d>0); assert(!fn.empty()); std::string dn=deduce_name(fn,suffix); std::string name=dn+"_defined"; g<< NL TAB2 "namespace" NL TAB2 "sfinae" NL TAB3 "{" NL TAB3 "using ::boost::qvm::"<" NL TAB3 "struct "<" NL TAB3 "struct" NL TAB3<" NL TAB4"{" NL TAB4"static bool const value=true;" NL TAB4"};" NL TAB3 "}" NL NL ; } void mr_mult_ma_mb( output_file & out, int m, int n, int p, char const * suffix ) { assert(m>0); assert(n>0); assert(p>0); header_mr_ma_mb_mult(out,m,n,p,"operator*"); out.require_include(INCLUDE_DEDUCE_M); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename mat_traits::scalar_type Ta;" NL TAB3 "typedef typename mat_traits::scalar_type Tb;" NL ; for( int i=0; i!=m; ++i ) for( int j=0; j!=n; ++j ) g<::template read_element<"<(a);" NL; for( int i=0; i!=n; ++i ) for( int j=0; j!=p; ++j ) g<::template read_element<"<(b);" NL; g<< TAB3 "typedef typename deduce_mat2::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits::rows=="<::cols=="<::template write_element<"<(r)="; for( int k=0; k!=n; ++k ) { if( k ) g<<'+'; g<<'a'<0); header_ma_mb_same_size(out,d,d,"operator*="); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename mat_traits::scalar_type Ta;" NL TAB3 "typedef typename mat_traits::scalar_type Tb;" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<::template read_element<"<(a);" NL; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<::template read_element<"<(b);" NL; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) { g<::template write_element<"<(a)="; for( int k=0; k!=d; ++k ) { if( k ) g<<'+'; g<<'a'<::scalar_type Ta;" NL TAB3 "typedef typename vec_traits::scalar_type Tb;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template read_element<"<(a);" NL; for( int i=0; i!=c; ++i ) g<::template read_element<"<(b);" NL; g<< TAB3 "typedef typename deduce_vec2::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits::dim=="<::template write_element<"<(r)="; for( int j=0; j!=c; ++j ) { if( j ) g<<'+'; g<<'a'<0); assert(c>0); header_vr_va_mb_mult(out,r,c,"operator*"); out.require_include(INCLUDE_INLINE); out.require_include(INCLUDE_V_TRAITS); out.require_include(INCLUDE_M_TRAITS); out.require_include(INCLUDE_ENABLE_IF); out.require_include(INCLUDE_DEDUCE_V); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename vec_traits::scalar_type Ta;" NL TAB3 "typedef typename mat_traits::scalar_type Tb;" NL ; for( int i=0; i!=r; ++i ) g<::template read_element<"<(a);" NL; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template read_element<"<(b);" NL; g<< TAB3 "typedef typename deduce_vec2::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits::dim=="<::template write_element<"<(r)="; for( int j=0; j!=r; ++j ) { if( j ) g<<'+'; g<<'a'<::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits::dim=="<::template write_element<"<(r)=vec_traits::template read_element<"<(a)"<::template read_element<"<(b);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,d,fn,suffix); } void bool_eq_ma_mb( output_file & out, int r, int c, char const * suffix ) { header_bool_ma_mb_same_size(out,r,c,"operator=="); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "return" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<< TAB4"mat_traits::template read_element<"<(a)==mat_traits::template read_element<"<(b)"<<(i!=r-1||j!=c-1?" &&":";")<::template read_element<"<(a)==vec_traits::template read_element<"<(b)"<<(i!=d-1?" &&":";")<::template read_element<"<(a)==mat_traits::template read_element<"<(b))"<<(i!=r-1||j!=c-1?" ||":";")<::template read_element<"<(a)==vec_traits::template read_element<"<(b))"<<(i!=d-1?" ||":";")<::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits::rows=="<::cols=="<::template write_element<"<(r)=mat_traits::template read_element<"<(a)"<::template read_element<"<(b);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,r,c,fn,suffix); } void ma_op_ma_mb_same_size( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_ma_mb_same_size(out,r,c,fn); std::ostream & g=out.stream(); g<::template write_element<"<(a)"<::template read_element<"<(b);" NL; g<< TAB3 "return a;" NL TAB3 "}" NL ; defined(g,r,c,fn,suffix); } void va_op_va_vb_same_size( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_va_vb_same_size(out,d,fn); std::ostream & g=out.stream(); g<::template write_element<"<(a)"<::template read_element<"<(b);" NL; g<< TAB3 "return a;" NL TAB3 "}" NL ; defined(g,d,fn,suffix); } void mr_op_ma( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_mr_ma(out,r,c,fn); out.require_include(INCLUDE_DEDUCE_M); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename deduce_mat::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template write_element<"<(r)="<::template read_element<"<(a);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,r,c,fn,suffix); } void vr_op_va( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_vr_va(out,d,fn); out.require_include(INCLUDE_DEDUCE_V); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename deduce_vec::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<::template write_element<"<(r)="<::template read_element<"<(a);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,d,fn,suffix); } void mr_op_ma_sb( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_mr_ma_sb(out,r,c,fn); out.require_include(INCLUDE_DEDUCE_M); out.require_include(INCLUDE_DEDUCE_V); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename deduce_mat::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template write_element<"<(r)=mat_traits::template read_element<"<(a)"<::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template write_element<"<(r)=a"<::template read_element<"<(b);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,r,c,fn,suffix); } void vr_op_va_sb( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_vr_va_sb(out,d,fn); out.require_include(INCLUDE_DEDUCE_V); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename deduce_vec::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<::template write_element<"<(r)=vec_traits::template read_element<"<(a)"<::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<::template write_element<"<(r)=a"<::template read_element<"<(b);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,d,fn,suffix); } void ma_op_ma_sb( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_ma_sb(out,r,c,fn); std::ostream & g=out.stream(); g<< TAB3 "{" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template write_element<"<(a)"<::template write_element<"<(a)"<::template write_element<"<(a)=mat_traits::template read_element<"<(b);" NL; g<< TAB3 "return a;" NL TAB3 "}" NL ; defined(g,r,c,"assign",suffix); } void va_assign_va_vb( output_file & out, int d, char const * suffix ) { header_va_vb_same_size(out,d,"assign"); out.require_include(INCLUDE_V_TRAITS); out.require_include(INCLUDE_INLINE); out.require_include(INCLUDE_ENABLE_IF); std::ostream & g=out.stream(); g<::template write_element<"<(a)=vec_traits::template read_element<"<(b);" NL; g<< TAB3 "return a;" NL TAB3 "}" NL ; defined(g,d,"assign",suffix); } void mr_convert_to_ma( output_file & out, int r, int c, char const * suffix ) { if( r==c && r>=3 ) { out.require_include(INCLUDE_Q_TRAITS); out.require_include(INCLUDE_S_TRAITS); } std::ostream & g=out.stream(); g<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits::rows=="<::rows=="<::cols=="<::cols=="<::type" NL TAB2<<"convert_to( A const & a )" NL TAB3 "{" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template write_element<"<(r) = mat_traits::template read_element<"<(a);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; if( r==c && r>=3 ) { g<< NL TAB2 "template " NL TAB2 "BOOST_QVM_INLINE" NL TAB2 "typename enable_if_c<" NL TAB3 "is_mat::value && is_quat::value &&" NL TAB3 "mat_traits::rows=="<::cols=="<::type" NL TAB2 "convert_to( A const & q )" NL TAB3 "{" NL TAB3 "typedef typename mat_traits::scalar_type T;" NL TAB3 "T const a=quat_traits::template read_element<0>(q);" NL TAB3 "T const b=quat_traits::template read_element<1>(q);" NL TAB3 "T const c=quat_traits::template read_element<2>(q);" NL TAB3 "T const d=quat_traits::template read_element<3>(q);" NL TAB3 "T const bb = b*b;" NL TAB3 "T const cc = c*c;" NL TAB3 "T const dd = d*d;" NL TAB3 "T const bc = b*c;" NL TAB3 "T const bd = b*d;" NL TAB3 "T const cd = c*d;" NL TAB3 "T const ab = a*b;" NL TAB3 "T const ac = a*c;" NL TAB3 "T const ad = a*d;" NL<< (r>3?TAB3 "T const zero = scalar_traits::value(0);" NL:"")<< TAB3 "T const one = scalar_traits::value(1);" NL TAB3 "T const two = one+one;" NL TAB3 "R r;" NL TAB3 "mat_traits::template write_element<0,0>(r) = one - two*(cc+dd);" NL TAB3 "mat_traits::template write_element<0,1>(r) = two*(bc-ad);" NL TAB3 "mat_traits::template write_element<0,2>(r) = two*(bd+ac);" NL ; for( int i=3; i!=c; ++i ) g<::template write_element<0,"<(r) = zero;" NL; g<< TAB3 "mat_traits::template write_element<1,0>(r) = two*(bc+ad);" NL TAB3 "mat_traits::template write_element<1,1>(r) = one - two*(bb+dd);" NL TAB3 "mat_traits::template write_element<1,2>(r) = two*(cd-ab);" NL ; for( int i=3; i!=c; ++i ) g<::template write_element<1,"<(r) = zero;" NL; g<< TAB3 "mat_traits::template write_element<2,0>(r) = two*(bd-ac);" NL TAB3 "mat_traits::template write_element<2,1>(r) = two*(cd+ab);" NL TAB3 "mat_traits::template write_element<2,2>(r) = one - two*(bb+cc);" NL ; for( int i=3; i!=c; ++i ) g<::template write_element<2,"<(r) = zero;" NL; for( int i=3; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<::template write_element<"<(r) = "<<(i==j?"one":"zero")<<";" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; } defined(g,r,c,"convert_to",suffix); } void vr_convert_to_va( output_file & out, int d, char const * suffix ) { header_vr_va_same_size(out,d,"convert_to"); std::ostream & g=out.stream(); g<::template write_element<"<(r)=vec_traits::template read_element<"<(a);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,d,"convert_to",suffix); } struct del_row_col { del_row_col const * next; int i, j; char var; explicit del_row_col( char var ): next(0), i(std::numeric_limits::max()), j(std::numeric_limits::max()), var(var) { } del_row_col( del_row_col const & next, int i, int j ): next(&next), i(i), j(j), var(next.var) { } std::pair idx( std::pair const & x ) const { std::pair r(x.first+(x.first>=i),x.second+(x.second>=j)); if( next ) return next->idx(r); else return r; } void operator()( std::ostream & g, int r, int c ) const { std::pair p=idx(std::make_pair(r,c)); g << var << p.first << p.second; } }; void determinant_impl( std::ostream & g, int n, del_row_col const & a ) { if( n==1 ) return a(g,0,0); g << "("; char const * plus=""; for( int i=0; i!=n; ++i,plus="+" ) { g<<((i&1)?"-":plus); a(g,0,i); g<<'*'; determinant_impl(g,n-1,del_row_col(a,0,i)); } g << ")"; } void determinant( output_file & out, int d, char const * suffix ) { header_sr_ma(out,d,d,"determinant"); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename mat_traits::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<::template read_element<"<(a);" NL; g<1); out.require_include(INCLUDE_DEDUCE_M); out.require_include(INCLUDE_ASSERT); out.require_include(INCLUDE_THROW_EXCEPTION); out.require_include(INCLUDE_ERROR); std::ostream & g=out.stream(); g<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="<::value," NL TAB3 "deduce_mat >::type" NL TAB2 "inverse( A const & a, B det )" NL TAB3 "{" NL TAB3 "typedef typename mat_traits::scalar_type T;" NL TAB3 "BOOST_QVM_ASSERT(det!=scalar_traits::value(0));" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<::template read_element<"<(a);" NL; g<< TAB3 "T const f=scalar_traits::value(1)/det;" NL TAB3 "typedef typename deduce_mat::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) { g<::template write_element<"<(r)="<<(((i+j)&1)?'-':' ')<<"f*"; determinant_impl(g,d-1,del_row_col(del_row_col('a'),j,i)); g<<";" NL; } g<< TAB3 "return r;" NL TAB3 "}" NL NL TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits::rows=="<::cols=="< >::type" NL TAB2 "inverse( A const & a )" NL TAB3 "{" NL TAB3 "typedef typename mat_traits::scalar_type T;" NL TAB3 "T det=determinant(a);" NL TAB3 "if( det==scalar_traits::value(0) )" NL TAB4"BOOST_QVM_THROW_EXCEPTION(zero_determinant_error());" NL TAB3 "return inverse(a,det);" NL TAB3 "}" NL ; defined(g,d,"inverse",suffix); } void mag_sqr( output_file & out, int d, char const * suffix ) { header_sr_va(out,d,"mag_sqr"); out.require_include(INCLUDE_MATH); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename vec_traits::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<::template read_element<"<(a);" NL; g<::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<::template read_element<"<(a);" NL; g<(m2);" NL TAB3 "return mag;" NL TAB3 "}" NL ; defined(g,d,"mag",suffix); } void normalize( output_file & out, int d, char const * suffix ) { header_vr_va(out,d,"normalized"); out.require_include(INCLUDE_MATH); out.require_include(INCLUDE_THROW_EXCEPTION); out.require_include(INCLUDE_ERROR); out.require_include(INCLUDE_DEDUCE_V); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename vec_traits::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<::template read_element<"<(a);" NL; g<::scalar_type>::value(0) )" NL TAB4"BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());" NL TAB3 "T const rm=scalar_traits::value(1)/sqrt(m2);" NL TAB3 "typedef typename deduce_vec::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<::template write_element<"<(r)=a"<" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits::dim=="<::type" NL TAB2<<"normalize( A & a )" NL TAB3 "{" NL TAB3 "typedef typename vec_traits::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<::template read_element<"<(a);" NL; g<::scalar_type>::value(0) )" NL TAB4"BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());" NL TAB3 "T const rm=scalar_traits::value(1)/sqrt(m2);" NL ; for( int i=0; i!=d; ++i ) g<::template write_element<"<(a)*=rm;" NL; g<::scalar_type Ta;" NL TAB3 "typedef typename vec_traits::scalar_type Tb;" NL TAB3 "typedef typename deduce_scalar::type Tr;" NL ; for( int i=0; i!=d; ++i ) g<::template read_element<"<(a);" NL; for( int i=0; i!=d; ++i ) g<::template read_element<"<(b);" NL; g< void swizzle_impl( std::ostream & g, int d, swizzle_pair const (&ids)[N], std::vector const & initial_count ) { assert(d>=2); std::vector count(initial_count); for( char const * const ref_id[2] = { " const &", " &" };; ) { int max_dim=-100; for( int i=0; i!=d; ++i ) max_dim=std::max(max_dim,ids[count[i]-1].idx); if( max_dim<0 ) { g<< TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL TAB2 "qvm_detail::sw01_<"; for( int k=0; k!=d; ++k ) g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<"; g<< " > const &" NL TAB2 "_"; for( int k=0; k!=d; ++k ) { char f=ids[count[k]-1].ch; assert(f>='0' && f<='9'); g<"; g<< " > const *>(qvm_detail::get_null());" NL TAB3 "}" NL; } else for( int rfid=0; rfid<2; ++rfid ) { for( int scalar=0; scalar!=2; ++scalar ) { if( scalar && max_dim>0 ) break; if( scalar ) g<< TAB2 "template " NL TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL TAB2 "typename enable_if_c<" NL TAB3 "is_scalar::value," NL TAB3 "qvm_detail::sws_" NL TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL TAB2 "typename enable_if_c<" NL TAB3 "is_vec::value && vec_traits::dim>="<"; g<<" >"<::type" NL TAB2; for( int k=0; k!=d; ++k ) { char f=ids[count[k]-1].ch; if( !k && f>='0' && f<='9' ) g<<'_'; g<"; g<< " >"<(a);" NL TAB3 "}" NL; } } int j; for( j=0; j!=d; ++j ) if( --count[j] ) break; else count[j]=initial_count[j]; if( j==d ) break; } } void swizzle( output_file & out, int d ) { assert(d>1); out.require_include(INCLUDE_INLINE); out.require_include(INCLUDE_SWIZZLE_TRAITS); out.require_include(INCLUDE_ENABLE_IF); std::ostream & g=out.stream(); swizzle_pair const swizzle_ids[6] = { {'X',0}, {'Y',1}, {'Z',2}, {'W',3}, {'0',-1}, {'1',-2} }; std::vector initial_count(d,6); swizzle_impl(g,d,swizzle_ids,initial_count); } command_line_options parse_command_line( int argc, char const * argv[] ) { class next { char const * const * const argv; public: int const argc; next( int argc, char const * argv[] ): argc(argc), argv(argv) { } std::string operator()( int & i ) const { assert(i