//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 <string> #include <map> #include <vector> #include <iostream> #include <fstream> #include <sstream> #include <set> #include <algorithm> #include <limits> #include <assert.h> #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<struct cmd_arg_,std::string> cmd_arg; struct null_deleter { template <class T> 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 <class T> std::string to_string( T const & x ) { std::ostringstream s; s<<x; return s.str(); } struct command_line_options { bool con; std::string output_directory; command_line_options(): con(false) { } }; class output_file { output_file( output_file const & ); output_file & operator=( output_file const & ); std::string const output_directory; bool const con; std::ostringstream out_; std::set<std::string> 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<std::ofstream> f; if( !con ) { std::string path; if( !output_directory.empty() ) { path+=output_directory; path+='/'; path+=name; } boost::shared_ptr<std::ofstream>(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<std::string>::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 <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<B>::rows=="<<r<<" &&" NL TAB3 "mat_traits<A>::cols=="<<c<<" && mat_traits<B>::cols=="<<c<<"," NL TAB3 "deduce_mat2<A,B,"<<r<<','<<c<<"> >::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_mr_ma_mb_mult( output_file & out, int m, int n, int p, std::string const & name ) { assert(m>0); assert(n>0); assert(p>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_M); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<m<<" && mat_traits<B>::rows=="<<n<<" &&" NL TAB3 "mat_traits<A>::cols=="<<n<<" && mat_traits<B>::cols=="<<p<<"," NL TAB3 "deduce_mat2<A,B,"<<m<<','<<p<<"> >::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_vr_ma_vb_mult( 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_V); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<" &&" NL TAB3 "vec_traits<B>::dim=="<<c<<"," NL TAB3 "deduce_vec2<A,B,"<<c<<"> >::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_vr_va_mb_mult( 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_V); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<B>::rows=="<<r<<" && mat_traits<B>::cols=="<<c<<" &&" NL TAB3 "vec_traits<A>::dim=="<<c<<"," NL TAB3 "deduce_vec2<A,B,"<<r<<"> >::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_vr_va_vb_same_size( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL TAB3 "deduce_vec2<A,B,"<<d<<"> >::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_bool_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.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<B>::rows=="<<r<<" &&" NL TAB3 "mat_traits<A>::cols=="<<c<<" && mat_traits<B>::cols=="<<c<<"," NL TAB3 "bool>::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_bool_va_vb_same_size( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL TAB2 "bool>::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_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.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<B>::rows=="<<r<<" &&" NL TAB3 "mat_traits<A>::cols=="<<c<<" && mat_traits<B>::cols=="<<c<<"," NL TAB3 "A &>::type" NL TAB2<<name<<"( A & a, B const & b )" NL ; } void header_va_vb_same_size( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL TAB3 "A &>::type" NL TAB2<<name<<"( A & a, B const & b )" NL ; } void header_sr_ma( output_file & out, int r, int c, std::string const & name ) { assert(r>0); assert(c>0); assert(!name.empty()); out.stream()<< TAB2 "template <class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<"," NL TAB3 "typename mat_traits<A>::scalar_type>::type" NL TAB2<<name<<"( A const & a )" NL ; } void header_sr_va_vb( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_S); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL TAB3 "deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type" NL TAB2<<name<<"( A const & a, B const & b )" NL ; } void header_sr_va( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.stream()<< TAB2 "template <class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "is_vec<A>::value && vec_traits<A>::dim=="<<d<<"," NL TAB3 "typename vec_traits<A>::scalar_type>::type" NL TAB2<<name<<"( A const & a )" NL ; } void header_mr_ma( 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 <class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<"," NL TAB3 "deduce_mat<A> >::type" NL TAB2<<name<<"( A const & a )" NL ; } void header_vr_va( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template <class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<"," NL TAB3 "deduce_vec<A> >::type" NL TAB2<<name<<"( A const & a )" NL ; } void header_vr_va_same_size( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.stream()<< TAB2 "template <class R,class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "is_vec<A>::value &&" NL TAB3 "vec_traits<R>::dim=="<<d<<" && vec_traits<A>::dim=="<<d<<"," NL TAB3 "R>::type" NL TAB2<<name<<"( A const & a )" NL ; } void header_mr_ma_sb( 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 <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<" && is_scalar<B>::value," NL TAB3 "deduce_mat<A> >::type" NL TAB2<<name<<"( A const & a, B b )" NL ; } void header_mr_sa_mb( 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 <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "is_scalar<A>::value && mat_traits<B>::rows=="<<r<<" && mat_traits<B>::cols=="<<c<<"," NL TAB3 "deduce_mat<B> >::type" NL TAB2<<name<<"( A a, B const & b )" NL ; } void header_vr_va_sb( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<" && is_scalar<B>::value," NL TAB3 "deduce_vec<A> >::type" NL TAB2<<name<<"( A const & a, B b )" NL ; } void header_vr_sa_vb( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.require_include(INCLUDE_DEDUCE_V); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "is_scalar<A>::value && vec_traits<B>::dim=="<<d<<"," NL TAB3 "deduce_vec<B> >::type" NL TAB2<<name<<"( A a, B const & b )" NL ; } void header_ma_sb( output_file & out, int r, int c, std::string const & name ) { assert(r>0); assert(c>0); assert(!name.empty()); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<" && is_scalar<B>::value," NL TAB3 "A &>::type" NL TAB2<<name<<"( A & a, B b )" NL ; } void header_va_sb( output_file & out, int d, std::string const & name ) { assert(d>0); assert(!name.empty()); out.stream()<< TAB2 "template <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<" && is_scalar<B>::value," NL TAB3 "A &>::type" NL TAB2<<name<<"( A & a, B b )" NL ; } void defined( std::ostream & g, int r, int cr, int c, std::string fn, char const * suffix ) { assert(r>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::"<<fn<<";" NL TAB3 "}" NL NL TAB2 "namespace" NL TAB2 "qvm_detail" NL TAB3 "{" NL TAB3 "template <int R,int /*CR*/,int C>" NL TAB3 "struct "<<name<<";" NL NL TAB3 "template <>" NL TAB3 "struct" NL TAB3<<name<<'<'<<r<<','<<cr<<','<<c<<">" 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::"<<fn<<";" NL TAB3 "}" NL NL TAB2 "namespace" NL TAB2 "qvm_detail" NL TAB3 "{" NL TAB3 "template <int R,int C>" NL TAB3 "struct "<<name<<";" NL NL TAB3 "template <>" NL TAB3 "struct" NL TAB3<<name<<"<"<<r<<","<<c<<">" 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::"<<fn<<";" NL TAB3 "}" NL NL TAB2 "namespace" NL TAB2 "qvm_detail" NL TAB3 "{" NL TAB3 "template <int D>" NL TAB3 "struct "<<name<<";" NL NL TAB3 "template <>" NL TAB3 "struct" NL TAB3<<name<<"<"<<d<<">" 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<A>::scalar_type Ta;" NL TAB3 "typedef typename mat_traits<B>::scalar_type Tb;" NL ; for( int i=0; i!=m; ++i ) for( int j=0; j!=n; ++j ) g<<TAB3 "Ta const a"<<i<<j<<" = mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL; for( int i=0; i!=n; ++i ) for( int j=0; j!=p; ++j ) g<<TAB3 "Tb const b"<<i<<j<<" = mat_traits<B>::template read_element<"<<i<<','<<j<<">(b);" NL; g<< TAB3 "typedef typename deduce_mat2<A,B,"<<m<<','<<p<<">::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows=="<<m<<");" NL TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols=="<<p<<");" NL TAB3 "R r;" NL ; for( int i=0; i!=m; ++i ) for( int j=0; j!=p; ++j ) { g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)="; for( int k=0; k!=n; ++k ) { if( k ) g<<'+'; g<<'a'<<i<<k<<"*b"<<k<<j; } g<<";" NL; } g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,m,n,p,"operator*",suffix); } void ma_mult_ma_mb( output_file & out, int d, char const * suffix ) { assert(d>0); header_ma_mb_same_size(out,d,d,"operator*="); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename mat_traits<A>::scalar_type Ta;" NL TAB3 "typedef typename mat_traits<B>::scalar_type Tb;" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<<TAB3 "Ta const a"<<i<<j<<" = mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<<TAB3 "Tb const b"<<i<<j<<" = mat_traits<B>::template read_element<"<<i<<','<<j<<">(b);" NL; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) { g<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)="; for( int k=0; k!=d; ++k ) { if( k ) g<<'+'; g<<'a'<<i<<k<<"*b"<<k<<j; } g<<";" NL; } g<< TAB3 "return a;" NL TAB3 "}" NL ; defined(g,d,"operator*=",suffix); } void vr_mult_ma_vb( output_file & out, int r, int c, char const * suffix ) { assert(r>0); assert(c>0); header_vr_ma_vb_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 mat_traits<A>::scalar_type Ta;" NL TAB3 "typedef typename vec_traits<B>::scalar_type Tb;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "Ta const a"<<i<<j<<" = mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL; for( int i=0; i!=c; ++i ) g<<TAB3 "Tb const b"<<i<<" = vec_traits<B>::template read_element<"<<i<<">(b);" NL; g<< TAB3 "typedef typename deduce_vec2<A,B,"<<c<<">::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim=="<<c<<");" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) { g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)="; for( int j=0; j!=c; ++j ) { if( j ) g<<'+'; g<<'a'<<i<<j<<"*b"<<j; } g<<";" NL; } g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,r,c,"operator*",suffix); } void vr_mult_va_mb( output_file & out, int r, int c, char const * suffix ) { assert(r>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<A>::scalar_type Ta;" NL TAB3 "typedef typename mat_traits<B>::scalar_type Tb;" NL ; for( int i=0; i!=r; ++i ) g<<TAB3 "Ta const a"<<i<<" = vec_traits<A>::template read_element<"<<i<<">(a);" NL; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "Tb const b"<<i<<j<<" = mat_traits<B>::template read_element<"<<i<<','<<j<<">(b);" NL; g<< TAB3 "typedef typename deduce_vec2<A,B,"<<r<<">::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim=="<<r<<");" NL TAB3 "R r;" NL ; for( int i=0; i!=c; ++i ) { g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)="; for( int j=0; j!=r; ++j ) { if( j ) g<<'+'; g<<'a'<<j<<"*b"<<j<<i; } g<<";" NL; } g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,r,c,"operator*",suffix); } void vr_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_vr_va_vb_same_size(out,d,fn); out.require_include(INCLUDE_DEDUCE_V); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename deduce_vec2<A,B,"<<d<<">::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim=="<<d<<");" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=vec_traits<A>::template read_element<"<<i<<">(a)"<<op<<"vec_traits<B>::template read_element<"<<i<<">(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<A>::template read_element<"<<i<<','<<j<<">(a)==mat_traits<B>::template read_element<"<<i<<','<<j<<">(b)"<<(i!=r-1||j!=c-1?" &&":";")<<NL; ; g<< TAB3 "}" NL ; defined(g,r,c,"operator==",suffix); } void bool_eq_va_vb( output_file & out, int d, char const * suffix ) { header_bool_va_vb_same_size(out,d,"operator=="); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "return" NL ; for( int i=0; i!=d; ++i ) g<< TAB4"vec_traits<A>::template read_element<"<<i<<">(a)==vec_traits<B>::template read_element<"<<i<<">(b)"<<(i!=d-1?" &&":";")<<NL; ; g<< TAB3 "}" NL ; defined(g,d,"operator==",suffix); } void bool_neq_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<A>::template read_element<"<<i<<','<<j<<">(a)==mat_traits<B>::template read_element<"<<i<<','<<j<<">(b))"<<(i!=r-1||j!=c-1?" ||":";")<<NL; ; g<< TAB3 "}" NL ; defined(g,r,c,"operator!=",suffix); } void bool_neq_va_vb( output_file & out, int d, char const * suffix ) { header_bool_va_vb_same_size(out,d,"operator!="); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "return" NL ; for( int i=0; i!=d; ++i ) g<< TAB4"!(vec_traits<A>::template read_element<"<<i<<">(a)==vec_traits<B>::template read_element<"<<i<<">(b))"<<(i!=d-1?" ||":";")<<NL; ; g<< TAB3 "}" NL ; defined(g,d,"operator!=",suffix); } void mr_op_ma_mb_same_size( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix ) { assert(r>0); assert(c>0); assert(!op.empty()); header_mr_ma_mb_same_size(out,r,c,fn); out.require_include(INCLUDE_DEDUCE_M); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename deduce_mat2<A,B,"<<r<<','<<c<<">::type R;" NL TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows=="<<r<<");" NL TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols=="<<c<<");" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)=mat_traits<A>::template read_element<"<<i<<","<<j<<">(a)"<<op<<"mat_traits<B>::template read_element<"<<i<<","<<j<<">(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<<TAB3 "{" NL; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)"<<op<<"mat_traits<B>::template read_element<"<<i<<","<<j<<">(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<<TAB3 "{" NL; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)"<<op<<"vec_traits<B>::template read_element<"<<i<<">(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<A>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)="<<op<<"mat_traits<A>::template read_element<"<<i<<","<<j<<">(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<A>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)="<<op<<"vec_traits<A>::template read_element<"<<i<<">(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<A>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)=mat_traits<A>::template read_element<"<<i<<","<<j<<">(a)"<<op<<"b;" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,r,c,fn,suffix); } void mr_op_sa_mb( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_mr_sa_mb(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<B>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)=a"<<op<<"mat_traits<B>::template read_element<"<<i<<","<<j<<">(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<A>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=vec_traits<A>::template read_element<"<<i<<">(a)"<<op<<"b;" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; defined(g,d,fn,suffix); } void vr_op_sa_vb( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_vr_sa_vb(out,d,fn); out.require_include(INCLUDE_DEDUCE_V); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename deduce_vec<B>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=a"<<op<<"vec_traits<B>::template read_element<"<<i<<">(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<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)"<<op<<"b;" NL; g<< TAB3 "return a;" NL TAB3 "}" NL ; defined(g,r,c,fn,suffix); } void va_op_va_sb( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix ) { assert(!op.empty()); header_va_sb(out,d,fn); std::ostream & g=out.stream(); g<< TAB3 "{" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)"<<op<<"b;" NL; g<< TAB3 "return a;" NL TAB3 "}" NL ; defined(g,d,fn,suffix); } void ma_assign_ma_mb( output_file & out, int r, int c, char const * suffix ) { header_ma_mb_same_size(out,r,c,"assign"); out.require_include(INCLUDE_M_TRAITS); out.require_include(INCLUDE_INLINE); out.require_include(INCLUDE_ENABLE_IF); std::ostream & g=out.stream(); g<<TAB3 "{" NL; for( int i=0; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)=mat_traits<B>::template read_element<"<<i<<","<<j<<">(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<<TAB3 "{" NL; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)=vec_traits<B>::template read_element<"<<i<<">(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 <class R,class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "mat_traits<R>::rows=="<<r<<" && mat_traits<A>::rows=="<<r<<" &&" NL TAB3 "mat_traits<R>::cols=="<<c<<" && mat_traits<A>::cols=="<<c<<"," NL TAB3 "R>::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<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r) = mat_traits<A>::template read_element<"<<i<<","<<j<<">(a);" NL; g<< TAB3 "return r;" NL TAB3 "}" NL ; if( r==c && r>=3 ) { g<< NL TAB2 "template <class R,class A>" NL TAB2 "BOOST_QVM_INLINE" NL TAB2 "typename enable_if_c<" NL TAB3 "is_mat<R>::value && is_quat<A>::value &&" NL TAB3 "mat_traits<R>::rows=="<<r<<" && mat_traits<R>::cols=="<<c<<"," NL TAB3 "R>::type" NL TAB2 "convert_to( A const & q )" NL TAB3 "{" NL TAB3 "typedef typename mat_traits<R>::scalar_type T;" NL TAB3 "T const a=quat_traits<A>::template read_element<0>(q);" NL TAB3 "T const b=quat_traits<A>::template read_element<1>(q);" NL TAB3 "T const c=quat_traits<A>::template read_element<2>(q);" NL TAB3 "T const d=quat_traits<A>::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<T>::value(0);" NL:"")<< TAB3 "T const one = scalar_traits<T>::value(1);" NL TAB3 "T const two = one+one;" NL TAB3 "R r;" NL TAB3 "mat_traits<R>::template write_element<0,0>(r) = one - two*(cc+dd);" NL TAB3 "mat_traits<R>::template write_element<0,1>(r) = two*(bc-ad);" NL TAB3 "mat_traits<R>::template write_element<0,2>(r) = two*(bd+ac);" NL ; for( int i=3; i!=c; ++i ) g<<TAB3 "mat_traits<R>::template write_element<0,"<<i<<">(r) = zero;" NL; g<< TAB3 "mat_traits<R>::template write_element<1,0>(r) = two*(bc+ad);" NL TAB3 "mat_traits<R>::template write_element<1,1>(r) = one - two*(bb+dd);" NL TAB3 "mat_traits<R>::template write_element<1,2>(r) = two*(cd-ab);" NL ; for( int i=3; i!=c; ++i ) g<<TAB3 "mat_traits<R>::template write_element<1,"<<i<<">(r) = zero;" NL; g<< TAB3 "mat_traits<R>::template write_element<2,0>(r) = two*(bd-ac);" NL TAB3 "mat_traits<R>::template write_element<2,1>(r) = two*(cd+ab);" NL TAB3 "mat_traits<R>::template write_element<2,2>(r) = one - two*(bb+cc);" NL ; for( int i=3; i!=c; ++i ) g<<TAB3 "mat_traits<R>::template write_element<2,"<<i<<">(r) = zero;" NL; for( int i=3; i!=r; ++i ) for( int j=0; j!=c; ++j ) g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(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<<TAB3 "{" NL<< TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=vec_traits<A>::template read_element<"<<i<<">(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<int>::max()), j(std::numeric_limits<int>::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<int,int> idx( std::pair<int,int> const & x ) const { std::pair<int,int> 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<int,int> 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<A>::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<<TAB3<<"T const a"<<i<<j<<"=mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL; g<<TAB3 "T det="; determinant_impl(g,d,del_row_col('a')); g<<";" NL; g<< TAB3 "return det;" NL TAB3 "}" NL ; defined(g,d,"determinant",suffix); } void inverse_ma( output_file & out, int d, char const * suffix ) { assert(d>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 <class A,class B>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<d<<" && mat_traits<A>::cols=="<<d<<" && is_scalar<B>::value," NL TAB3 "deduce_mat<A> >::type" NL TAB2 "inverse( A const & a, B det )" NL TAB3 "{" NL TAB3 "typedef typename mat_traits<A>::scalar_type T;" NL TAB3 "BOOST_QVM_ASSERT(det!=scalar_traits<B>::value(0));" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) g<<TAB3 "T const a"<<i<<j<<"=mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL; g<< TAB3 "T const f=scalar_traits<T>::value(1)/det;" NL TAB3 "typedef typename deduce_mat<A>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) for( int j=0; j!=d; ++j ) { g<<TAB3 "mat_traits<R>::template write_element<"<<i<<','<<j<<">(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 <class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename lazy_enable_if_c<" NL TAB3 "mat_traits<A>::rows=="<<d<<" && mat_traits<A>::cols=="<<d<<"," NL TAB3 "deduce_mat<A> >::type" NL TAB2 "inverse( A const & a )" NL TAB3 "{" NL TAB3 "typedef typename mat_traits<A>::scalar_type T;" NL TAB3 "T det=determinant(a);" NL TAB3 "if( det==scalar_traits<T>::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<A>::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL; g<<TAB3 "T const m2="; for( int i=0; i!=d; ++i ) { if( i ) g<<'+'; g<<'a'<<i<<"*a"<<i; } g<< ";" NL TAB3 "return m2;" NL TAB3 "}" NL ; defined(g,d,"mag_sqr",suffix); } void mag( output_file & out, int d, char const * suffix ) { header_sr_va(out,d,"mag"); out.require_include(INCLUDE_MATH); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename vec_traits<A>::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL; g<<TAB3 "T const m2="; for( int i=0; i!=d; ++i ) { if( i ) g<<'+'; g<<'a'<<i<<"*a"<<i; } g<< ";" NL TAB3 "T const mag=sqrt<T>(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<A>::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL; g<<TAB3 "T const m2="; for( int i=0; i!=d; ++i ) { if( i ) g<<'+'; g<<'a'<<i<<"*a"<<i; } g<< ";" NL TAB3 "if( m2==scalar_traits<typename vec_traits<A>::scalar_type>::value(0) )" NL TAB4"BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());" NL TAB3 "T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);" NL TAB3 "typedef typename deduce_vec<A>::type R;" NL TAB3 "R r;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=a"<<i<<"*rm;" NL; g<< TAB3 "return r;" NL TAB3 "}" NL NL TAB2 "namespace" NL TAB2 "sfinae" NL TAB3 "{" NL TAB3 "using ::boost::qvm::normalized;" NL TAB3 "}" NL NL TAB2 "template <class A>" NL TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL TAB2 "typename enable_if_c<" NL TAB3 "vec_traits<A>::dim=="<<d<<"," NL TAB3 "void>::type" NL TAB2<<"normalize( A & a )" NL TAB3 "{" NL TAB3 "typedef typename vec_traits<A>::scalar_type T;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL; g<<TAB3 "T const m2="; for( int i=0; i!=d; ++i ) { if( i ) g<<'+'; g<<'a'<<i<<"*a"<<i; } g<< ";" NL TAB3 "if( m2==scalar_traits<typename vec_traits<A>::scalar_type>::value(0) )" NL TAB4"BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());" NL TAB3 "T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)*=rm;" NL; g<<TAB3 "}" NL; defined(g,d,"normalize",suffix); } void dot( output_file & out, int d, char const * suffix ) { header_sr_va_vb(out,d,"dot"); out.require_include(INCLUDE_DEDUCE_S); out.require_include(INCLUDE_STATIC_ASSERT); std::ostream & g=out.stream(); g<< TAB3 "{" NL TAB3 "typedef typename vec_traits<A>::scalar_type Ta;" NL TAB3 "typedef typename vec_traits<B>::scalar_type Tb;" NL TAB3 "typedef typename deduce_scalar<Ta,Tb>::type Tr;" NL ; for( int i=0; i!=d; ++i ) g<<TAB3 "Ta const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL; for( int i=0; i!=d; ++i ) g<<TAB3 "Tb const b"<<i<<"=vec_traits<B>::template read_element<"<<i<<">(b);" NL; g<<TAB3 "Tr const dot="; for( int i=0; i!=d; ++i ) { if( i ) g<<'+'; g<<'a'<<i<<"*b"<<i; } g<< ";" NL TAB3 "return dot;" NL TAB3 "}" NL ; defined(g,d,"dot",suffix); } struct swizzle_pair { char ch; int idx; }; template <int N> void swizzle_impl( std::ostream & g, int d, swizzle_pair const (&ids)[N], std::vector<int> const & initial_count ) { assert(d>=2); std::vector<int> 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<"<<ids[count[k]-1].idx; for( int k=0; k!=d; ++k ) g<<" >"; g<< " > const &" NL TAB2 "_"; for( int k=0; k!=d; ++k ) { char f=ids[count[k]-1].ch; assert(f>='0' && f<='9'); g<<f; } g<< "()" NL TAB3 "{" NL TAB3 "return *reinterpret_cast<qvm_detail::sw01_<"; for( int k=0; k!=d; ++k ) g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<<ids[count[k]-1].idx; for( int k=0; k!=d; ++k ) 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 <class S>" NL TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL TAB2 "typename enable_if_c<" NL TAB3 "is_scalar<S>::value," NL TAB3 "qvm_detail::sws_<S,"; else g<< TAB2 "template <class V>" NL TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL TAB2 "typename enable_if_c<" NL TAB3 "is_vec<V>::value && vec_traits<V>::dim>="<<max_dim+1<<"," NL TAB3 "qvm_detail::sw_<V,"; for( int k=0; k!=d; ++k ) g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<<ids[count[k]-1].idx; for( int k=0; k!=d; ++k ) g<<" >"; g<<" >"<<ref_id[rfid]<<">::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<<f; } if( scalar ) g<< "( S"<<ref_id[rfid]<<" a )" NL TAB3 "{" NL TAB3 "return reinterpret_cast<qvm_detail::sws_<S,"; else g<< "( V"<<ref_id[rfid]<<" a )" NL TAB3 "{" NL TAB3 "return reinterpret_cast<qvm_detail::sw_<V,"; for( int k=0; k!=d; ++k ) g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<<ids[count[k]-1].idx; for( int k=0; k!=d; ++k ) g<<" >"; g<< " >"<<ref_id[rfid]<<">(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<int> 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[] ): argv(argv), argc(argc) { } std::string operator()( int & i ) const { assert(i<argc); if( ++i==argc ) BOOST_THROW_EXCEPTION(bad_command_line() << cmd_arg(argv[i-1])); return argv[i]; } } next_token(argc,argv); command_line_options r; for( int i=1; i!=argc; ++i ) if( argv[i][0]=='-' ) { char const * arg=argv[i]; if( arg==std::string("-od") ) r.output_directory=next_token(i); else if( arg==std::string("-con") ) r.con=true; else BOOST_THROW_EXCEPTION(bad_command_line() << cmd_arg(arg)); } return r; } void gen( int argc, char const * argv[] ) { command_line_options opt=parse_command_line(argc,argv); for( int d=2; d!=5; ++d ) { output_file f(opt); { char buf[1024]; sprintf(buf,INCLUDE_MAT_ASSIGN,d); f.require_include(buf); } mr_op_ma_mb_same_size(f,d,d,"operator+","+","mm"); mr_op_ma_mb_same_size(f,d,1,"operator+","+","mm"); mr_op_ma_mb_same_size(f,1,d,"operator+","+","mm"); mr_op_ma_mb_same_size(f,d,d,"operator-","-","mm"); mr_op_ma_mb_same_size(f,d,1,"operator-","-","mm"); mr_op_ma_mb_same_size(f,1,d,"operator-","-","mm"); ma_op_ma_mb_same_size(f,d,d,"operator+=","+=","mm"); ma_op_ma_mb_same_size(f,d,1,"operator+=","+=","mm"); ma_op_ma_mb_same_size(f,1,d,"operator+=","+=","mm"); ma_op_ma_mb_same_size(f,d,d,"operator-=","-=","mm"); ma_op_ma_mb_same_size(f,d,1,"operator-=","-=","mm"); ma_op_ma_mb_same_size(f,1,d,"operator-=","-=","mm"); mr_op_ma_sb(f,d,d,"operator*","*","ms"); mr_op_sa_mb(f,d,d,"operator*","*","sm"); mr_op_ma_sb(f,d,1,"operator*","*","ms"); mr_op_sa_mb(f,d,1,"operator*","*","sm"); mr_op_ma_sb(f,1,d,"operator*","*","ms"); mr_op_sa_mb(f,1,d,"operator*","*","sm"); ma_op_ma_sb(f,d,d,"operator*=","*=","ms"); ma_op_ma_sb(f,d,1,"operator*=","*=","ms"); ma_op_ma_sb(f,1,d,"operator*=","*=","ms"); mr_op_ma_sb(f,d,d,"operator/","/","ms"); mr_op_sa_mb(f,d,d,"operator/","/","sm"); mr_op_ma_sb(f,d,1,"operator/","/","ms"); mr_op_sa_mb(f,d,1,"operator/","/","sm"); mr_op_ma_sb(f,1,d,"operator/","/","ms"); ma_op_ma_sb(f,d,d,"operator/=","/=","ms"); ma_op_ma_sb(f,d,1,"operator/=","/=","ms"); ma_op_ma_sb(f,1,d,"operator/=","/=","ms"); mr_convert_to_ma(f,d,d,"m"); mr_convert_to_ma(f,d,1,"m"); mr_convert_to_ma(f,1,d,"m"); bool_eq_ma_mb(f,d,d,"mm"); bool_eq_ma_mb(f,d,1,"mm"); bool_eq_ma_mb(f,1,d,"mm"); bool_neq_ma_mb(f,d,d,"mm"); bool_neq_ma_mb(f,d,1,"mm"); bool_neq_ma_mb(f,1,d,"mm"); mr_op_ma(f,d,d,"operator-","-","m"); mr_op_ma(f,d,1,"operator-","-","m"); mr_op_ma(f,1,d,"operator-","-","m"); determinant(f,d,0); inverse_ma(f,d,"m"); mr_mult_ma_mb(f,d,d,d,"mm"); ma_mult_ma_mb(f,d,"mm"); mr_mult_ma_mb(f,d,d,1,"mm"); mr_mult_ma_mb(f,1,d,d,"mm"); f.dump("mat_operations"+to_string(d)+".hpp"); } for( int d=2; d!=5; ++d ) { output_file f(opt); ma_assign_ma_mb(f,d,d,"mm"); ma_assign_ma_mb(f,d,1,"mm"); ma_assign_ma_mb(f,1,d,"mm"); f.dump("mat_assign"+to_string(d)+".hpp"); } for( int d=2; d!=5; ++d ) { output_file f(opt); { char buf[1024]; sprintf(buf,INCLUDE_VEC_ASSIGN,d); f.require_include(buf); } vr_op_va_vb_same_size(f,d,"operator+","+","vv"); vr_op_va_vb_same_size(f,d,"operator-","-","vv"); va_op_va_vb_same_size(f,d,"operator+=","+=","vv"); va_op_va_vb_same_size(f,d,"operator-=","-=","vv"); vr_op_va_sb(f,d,"operator*","*","vs"); vr_op_sa_vb(f,d,"operator*","*","sv"); va_op_va_sb(f,d,"operator*=","*=","vs"); vr_op_va_sb(f,d,"operator/","/","vs"); va_op_va_sb(f,d,"operator/=","/=","vs"); vr_convert_to_va(f,d,"v"); bool_eq_va_vb(f,d,"vv"); bool_neq_va_vb(f,d,"vv"); vr_op_va(f,d,"operator-","-","v"); mag(f,d,"v"); mag_sqr(f,d,"v"); normalize(f,d,"v"); dot(f,d,"vv"); f.dump("vec_operations"+to_string(d)+".hpp"); } for( int d=2; d!=5; ++d ) { output_file f(opt); va_assign_va_vb(f,d,"vv"); f.dump("vec_assign"+to_string(d)+".hpp"); } for( int d=2; d!=5; ++d ) { output_file f(opt); vr_mult_ma_vb(f,d,d,"mv"); vr_mult_va_mb(f,d,d,"vm"); f.dump("vec_mat_operations"+to_string(d)+".hpp"); } { output_file f(opt); swizzle(f,2); f.dump("swizzle2.hpp"); } { output_file f(opt); swizzle(f,3); f.dump("swizzle3.hpp"); } { output_file f(opt); swizzle(f,4); f.dump("swizzle4.hpp"); } } } int main( int argc, char const * argv[] ) { try { gen(argc,argv); } catch( std::ifstream::failure & ) { std::cerr << "Failed to write generated output file" << std::endl; } catch( ... ) { std::cerr << "Unexpected exception" << std::endl << boost::current_exception_diagnostic_information(); } return 1; }