• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc.
2 
3 //Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include "boost/throw_exception.hpp"
7 #include "boost/exception/info.hpp"
8 #include "boost/exception/diagnostic_information.hpp"
9 #include "boost/bind.hpp"
10 #include <string>
11 #include <map>
12 #include <vector>
13 #include <iostream>
14 #include <fstream>
15 #include <sstream>
16 #include <set>
17 #include <algorithm>
18 #include <limits>
19 #include <assert.h>
20 
21 #define NL "\n"
22 #define TAB "    "
23 #define TAB1 TAB
24 #define TAB2 TAB TAB
25 #define TAB3 TAB TAB TAB
26 #define TAB4 TAB TAB TAB TAB
27 #define TAB5 TAB TAB TAB TAB TAB
28 #define INCLUDE_MAT_ASSIGN "boost/qvm/gen/mat_assign%d.hpp"
29 #define INCLUDE_VEC_ASSIGN "boost/qvm/gen/vec_assign%d.hpp"
30 #define INCLUDE_STATIC_ASSERT "boost/qvm/static_assert.hpp"
31 #define INCLUDE_MATH "boost/qvm/math.hpp"
32 #define INCLUDE_THROW_EXCEPTION "boost/qvm/throw_exception.hpp"
33 #define INCLUDE_ERROR "boost/qvm/error.hpp"
34 #define INCLUDE_INLINE "boost/qvm/inline.hpp"
35 #define INCLUDE_M_TRAITS "boost/qvm/mat_traits.hpp"
36 #define INCLUDE_V_TRAITS "boost/qvm/vec_traits.hpp"
37 #define INCLUDE_Q_TRAITS "boost/qvm/quat_traits.hpp"
38 #define INCLUDE_S_TRAITS "boost/qvm/scalar_traits.hpp"
39 #define INCLUDE_DEDUCE_M "boost/qvm/deduce_mat.hpp"
40 #define INCLUDE_DEDUCE_V "boost/qvm/deduce_vec.hpp"
41 #define INCLUDE_DEDUCE_Q "boost/qvm/deduce_quat.hpp"
42 #define INCLUDE_DEDUCE_S "boost/qvm/deduce_scalar.hpp"
43 #define INCLUDE_SWIZZLE_TRAITS "boost/qvm/detail/swizzle_traits.hpp"
44 #define INCLUDE_ENABLE_IF "boost/qvm/enable_if.hpp"
45 #define INCLUDE_ASSERT "boost/qvm/assert.hpp"
46 
47 namespace
48     {
49     struct exception_base: virtual std::exception, virtual boost::exception { };
50     struct bad_command_line: virtual exception_base { };
51     typedef boost::error_info<struct cmd_arg_,std::string> cmd_arg;
52 
53     struct
54     null_deleter
55         {
56         template <class T>
57         void
operator ()__anona04a1e480111::null_deleter58         operator()( T * ) const
59             {
60             }
61         };
62 
63     std::string
get_include_guard()64     get_include_guard()
65         {
66         std::ostringstream s;
67         s << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;
68         s<<"BOOST_QVM_";
69         for( int i=0; i!=16; ++i )
70             s<<(rand()%256);
71         return s.str();
72         }
73 
74     template <class T>
75     std::string
to_string(T const & x)76     to_string( T const & x )
77         {
78         std::ostringstream s;
79         s<<x;
80         return s.str();
81         }
82 
83     struct
84     command_line_options
85         {
86         bool con;
87         std::string output_directory;
88 
command_line_options__anona04a1e480111::command_line_options89         command_line_options():
90             con(false)
91             {
92             }
93         };
94 
95     class
96     output_file
97         {
98         output_file( output_file const & );
99         output_file & operator=( output_file const & );
100 
101         std::string const output_directory;
102         bool const con;
103         std::ostringstream out_;
104         std::set<std::string> includes_;
105 
106         public:
107 
108         explicit
output_file(command_line_options const & opt)109         output_file( command_line_options const & opt ):
110             output_directory(opt.output_directory),
111             con(opt.con)
112             {
113             }
114 
115         void
require_include(std::string const & fn)116         require_include( std::string const & fn )
117             {
118             assert(!strchr(fn.c_str(),'%'));
119             includes_.insert(fn);
120             };
121 
122         std::ostream &
stream()123         stream()
124             {
125             return out_;
126             }
127 
128         void
dump(std::string const & name) const129         dump( std::string const & name ) const
130             {
131             std::ostream * out = &std::cout;
132             boost::shared_ptr<std::ofstream> f;
133             if( !con )
134                 {
135                 std::string path;
136                 if( !output_directory.empty() )
137                     {
138                     path+=output_directory;
139                     path+='/';
140                     path+=name;
141                     }
142                 boost::shared_ptr<std::ofstream>(new std::ofstream(path.c_str())).swap(f);
143                 out = f.get();
144                 std::cout << "Writing " << path << "..." << std::endl;
145                 }
146             out->exceptions(std::ofstream::eofbit|std::ofstream::failbit|std::ofstream::badbit);
147             std::string include_guard=get_include_guard();
148             *out <<
149                 "//Copyright (c) 2008-2017 Emil Dotchevski and Reverge Studios, Inc." NL
150                 NL
151                 "//Distributed under the Boost Software License, Version 1.0. (See accompanying" NL
152                 "//file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)" NL
153                 NL
154                 "#ifndef " << include_guard << NL
155                 "#define " << include_guard << NL
156                 NL
157                 "//This file was generated by a program. Do not edit manually." NL
158                 NL
159                 ;
160             for( std::set<std::string>::const_iterator i=includes_.begin(),e=includes_.end(); i!=e; ++i )
161                 *out << "#include <" << *i << ">" NL;
162             *out <<
163                 NL
164                 "namespace" NL
165                 "boost" NL
166                 TAB1 "{" NL
167                 TAB1 "namespace" NL
168                 TAB1 "qvm" NL
169                 TAB2 "{" NL <<
170                 out_.str() <<
171                 TAB2 "}" NL
172                 TAB1 "}" NL
173                 NL
174                 "#endif" NL
175                 ;
176             }
177         };
178 
179     void
replace(std::string & s,char const * substr,char const * newstr)180     replace( std::string & s, char const * substr, char const * newstr )
181         {
182         assert(substr && *substr);
183         assert(newstr && *newstr);
184         std::string::size_type f=s.find(substr);
185         if( s.npos!=f )
186             s.replace(f,f+strlen(substr),newstr);
187         }
188 
189     std::string
deduce_name(std::string const & fn,char const * suffix)190     deduce_name( std::string const & fn, char const * suffix )
191         {
192         std::string s=fn;
193         replace(s,"operator==","eq");
194         replace(s,"operator!=","neq");
195         replace(s,"operator+=","plus_eq");
196         replace(s,"operator-=","minus_eq");
197         replace(s,"operator*=","mul_eq");
198         replace(s,"operator/=","div_eq");
199         replace(s,"operator+","plus");
200         replace(s,"operator-","minus");
201         replace(s,"operator*","mul");
202         replace(s,"operator/","div");
203         if( suffix )
204             {
205             s += '_';
206             s += suffix;
207             }
208         return s;
209         }
210 
211     void
header_mr_ma_mb_same_size(output_file & out,int r,int c,std::string const & name)212     header_mr_ma_mb_same_size( output_file & out, int r, int c, std::string const & name )
213         {
214         assert(r>0);
215         assert(c>0);
216         assert(!name.empty());
217         out.require_include(INCLUDE_DEDUCE_M);
218         out.stream() <<
219             TAB2 "template <class A,class B>" NL
220             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
221             TAB2 "typename lazy_enable_if_c<" NL
222             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<B>::rows=="<<r<<" &&" NL
223             TAB3 "mat_traits<A>::cols=="<<c<<" && mat_traits<B>::cols=="<<c<<"," NL
224             TAB3 "deduce_mat2<A,B,"<<r<<','<<c<<"> >::type" NL
225             TAB2<<name<<"( A const & a, B const & b )" NL
226             ;
227         }
228 
229     void
header_mr_ma_mb_mult(output_file & out,int m,int n,int p,std::string const & name)230     header_mr_ma_mb_mult( output_file & out, int m, int n, int p, std::string const & name )
231         {
232         assert(m>0);
233         assert(n>0);
234         assert(p>0);
235         assert(!name.empty());
236         out.require_include(INCLUDE_DEDUCE_M);
237         out.stream()<<
238             TAB2 "template <class A,class B>" NL
239             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
240             TAB2 "typename lazy_enable_if_c<" NL
241             TAB3 "mat_traits<A>::rows=="<<m<<" && mat_traits<B>::rows=="<<n<<" &&" NL
242             TAB3 "mat_traits<A>::cols=="<<n<<" && mat_traits<B>::cols=="<<p<<"," NL
243             TAB3 "deduce_mat2<A,B,"<<m<<','<<p<<"> >::type" NL
244             TAB2<<name<<"( A const & a, B const & b )" NL
245             ;
246         }
247 
248     void
header_vr_ma_vb_mult(output_file & out,int r,int c,std::string const & name)249     header_vr_ma_vb_mult( output_file & out, int r, int c, std::string const & name )
250         {
251         assert(r>0);
252         assert(c>0);
253         assert(!name.empty());
254         out.require_include(INCLUDE_DEDUCE_V);
255         out.stream()<<
256             TAB2 "template <class A,class B>" NL
257             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
258             TAB2 "typename lazy_enable_if_c<" NL
259             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<" &&" NL
260             TAB3 "vec_traits<B>::dim=="<<c<<"," NL
261             TAB3 "deduce_vec2<A,B,"<<c<<"> >::type" NL
262             TAB2<<name<<"( A const & a, B const & b )" NL
263             ;
264         }
265 
266     void
header_vr_va_mb_mult(output_file & out,int r,int c,std::string const & name)267     header_vr_va_mb_mult( output_file & out, int r, int c, std::string const & name )
268         {
269         assert(r>0);
270         assert(c>0);
271         assert(!name.empty());
272         out.require_include(INCLUDE_DEDUCE_V);
273         out.stream()<<
274             TAB2 "template <class A,class B>" NL
275             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
276             TAB2 "typename lazy_enable_if_c<" NL
277             TAB3 "mat_traits<B>::rows=="<<r<<" && mat_traits<B>::cols=="<<c<<" &&" NL
278             TAB3 "vec_traits<A>::dim=="<<c<<"," NL
279             TAB3 "deduce_vec2<A,B,"<<r<<"> >::type" NL
280             TAB2<<name<<"( A const & a, B const & b )" NL
281             ;
282         }
283 
284     void
header_vr_va_vb_same_size(output_file & out,int d,std::string const & name)285     header_vr_va_vb_same_size( output_file & out, int d, std::string const & name )
286         {
287         assert(d>0);
288         assert(!name.empty());
289         out.require_include(INCLUDE_DEDUCE_V);
290         out.stream()<<
291             TAB2 "template <class A,class B>" NL
292             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
293             TAB2 "typename lazy_enable_if_c<" NL
294             TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL
295             TAB3 "deduce_vec2<A,B,"<<d<<"> >::type" NL
296             TAB2<<name<<"( A const & a, B const & b )" NL
297             ;
298         }
299 
300     void
header_bool_ma_mb_same_size(output_file & out,int r,int c,std::string const & name)301     header_bool_ma_mb_same_size( output_file & out, int r, int c, std::string const & name )
302         {
303         assert(r>0);
304         assert(c>0);
305         assert(!name.empty());
306         out.stream()<<
307             TAB2 "template <class A,class B>" NL
308             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
309             TAB2 "typename enable_if_c<" NL
310             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<B>::rows=="<<r<<" &&" NL
311             TAB3 "mat_traits<A>::cols=="<<c<<" && mat_traits<B>::cols=="<<c<<"," NL
312             TAB3 "bool>::type" NL
313             TAB2<<name<<"( A const & a, B const & b )" NL
314             ;
315         }
316 
317     void
header_bool_va_vb_same_size(output_file & out,int d,std::string const & name)318     header_bool_va_vb_same_size( output_file & out, int d, std::string const & name )
319         {
320         assert(d>0);
321         assert(!name.empty());
322         out.stream()<<
323             TAB2 "template <class A,class B>" NL
324             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
325             TAB2 "typename enable_if_c<" NL
326             TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL
327             TAB2 "bool>::type" NL
328             TAB2<<name<<"( A const & a, B const & b )" NL
329             ;
330         }
331 
332     void
header_ma_mb_same_size(output_file & out,int r,int c,std::string const & name)333     header_ma_mb_same_size( output_file & out, int r, int c, std::string const & name )
334         {
335         assert(r>0);
336         assert(c>0);
337         assert(!name.empty());
338         out.stream()<<
339             TAB2 "template <class A,class B>" NL
340             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
341             TAB2 "typename enable_if_c<" NL
342             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<B>::rows=="<<r<<" &&" NL
343             TAB3 "mat_traits<A>::cols=="<<c<<" && mat_traits<B>::cols=="<<c<<"," NL
344             TAB3 "A &>::type" NL
345             TAB2<<name<<"( A & a, B const & b )" NL
346             ;
347         }
348 
349     void
header_va_vb_same_size(output_file & out,int d,std::string const & name)350     header_va_vb_same_size( output_file & out, int d, std::string const & name )
351         {
352         assert(d>0);
353         assert(!name.empty());
354         out.stream()<<
355             TAB2 "template <class A,class B>" NL
356             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
357             TAB2 "typename enable_if_c<" NL
358             TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL
359             TAB3 "A &>::type" NL
360             TAB2<<name<<"( A & a, B const & b )" NL
361             ;
362         }
363 
364     void
header_sr_ma(output_file & out,int r,int c,std::string const & name)365     header_sr_ma( output_file & out, int r, int c, std::string const & name )
366         {
367         assert(r>0);
368         assert(c>0);
369         assert(!name.empty());
370         out.stream()<<
371             TAB2 "template <class A>" NL
372             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
373             TAB2 "typename enable_if_c<" NL
374             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<"," NL
375             TAB3 "typename mat_traits<A>::scalar_type>::type" NL
376             TAB2<<name<<"( A const & a )" NL
377             ;
378         }
379 
380     void
header_sr_va_vb(output_file & out,int d,std::string const & name)381     header_sr_va_vb( output_file & out, int d, std::string const & name )
382         {
383         assert(d>0);
384         assert(!name.empty());
385         out.require_include(INCLUDE_DEDUCE_S);
386         out.stream()<<
387             TAB2 "template <class A,class B>" NL
388             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
389             TAB2 "typename lazy_enable_if_c<" NL
390             TAB3 "vec_traits<A>::dim=="<<d<<" && vec_traits<B>::dim=="<<d<<"," NL
391             TAB3 "deduce_scalar<typename vec_traits<A>::scalar_type,typename vec_traits<B>::scalar_type> >::type" NL
392             TAB2<<name<<"( A const & a, B const & b )" NL
393             ;
394         }
395 
396     void
header_sr_va(output_file & out,int d,std::string const & name)397     header_sr_va( output_file & out, int d, std::string const & name )
398         {
399         assert(d>0);
400         assert(!name.empty());
401         out.stream()<<
402             TAB2 "template <class A>" NL
403             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
404             TAB2 "typename enable_if_c<" NL
405             TAB3 "is_vec<A>::value && vec_traits<A>::dim=="<<d<<"," NL
406             TAB3 "typename vec_traits<A>::scalar_type>::type" NL
407             TAB2<<name<<"( A const & a )" NL
408             ;
409         }
410 
411     void
header_mr_ma(output_file & out,int r,int c,std::string const & name)412     header_mr_ma( output_file & out, int r, int c, std::string const & name )
413         {
414         assert(r>0);
415         assert(c>0);
416         assert(!name.empty());
417         out.require_include(INCLUDE_DEDUCE_M);
418         out.stream()<<
419             TAB2 "template <class A>" NL
420             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
421             TAB2 "typename lazy_enable_if_c<" NL
422             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<"," NL
423             TAB3 "deduce_mat<A> >::type" NL
424             TAB2<<name<<"( A const & a )" NL
425             ;
426         }
427 
428     void
header_vr_va(output_file & out,int d,std::string const & name)429     header_vr_va( output_file & out, int d, std::string const & name )
430         {
431         assert(d>0);
432         assert(!name.empty());
433         out.require_include(INCLUDE_DEDUCE_V);
434         out.stream()<<
435             TAB2 "template <class A>" NL
436             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
437             TAB2 "typename lazy_enable_if_c<" NL
438             TAB3 "vec_traits<A>::dim=="<<d<<"," NL
439             TAB3 "deduce_vec<A> >::type" NL
440             TAB2<<name<<"( A const & a )" NL
441             ;
442         }
443 
444     void
header_vr_va_same_size(output_file & out,int d,std::string const & name)445     header_vr_va_same_size( output_file & out, int d, std::string const & name )
446         {
447         assert(d>0);
448         assert(!name.empty());
449         out.stream()<<
450             TAB2 "template <class R,class A>" NL
451             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
452             TAB2 "typename enable_if_c<" NL
453             TAB3 "is_vec<A>::value &&" NL
454             TAB3 "vec_traits<R>::dim=="<<d<<" && vec_traits<A>::dim=="<<d<<"," NL
455             TAB3 "R>::type" NL
456             TAB2<<name<<"( A const & a )" NL
457             ;
458         }
459 
460     void
header_mr_ma_sb(output_file & out,int r,int c,std::string const & name)461     header_mr_ma_sb( output_file & out, int r, int c, std::string const & name )
462         {
463         assert(r>0);
464         assert(c>0);
465         assert(!name.empty());
466         out.require_include(INCLUDE_DEDUCE_M);
467         out.stream()<<
468             TAB2 "template <class A,class B>" NL
469             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
470             TAB2 "typename lazy_enable_if_c<" NL
471             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<" && is_scalar<B>::value," NL
472             TAB3 "deduce_mat<A> >::type" NL
473             TAB2<<name<<"( A const & a, B b )" NL
474             ;
475         }
476 
477     void
header_mr_sa_mb(output_file & out,int r,int c,std::string const & name)478     header_mr_sa_mb( output_file & out, int r, int c, std::string const & name )
479         {
480         assert(r>0);
481         assert(c>0);
482         assert(!name.empty());
483         out.require_include(INCLUDE_DEDUCE_M);
484         out.stream()<<
485             TAB2 "template <class A,class B>" NL
486             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
487             TAB2 "typename lazy_enable_if_c<" NL
488             TAB3 "is_scalar<A>::value && mat_traits<B>::rows=="<<r<<" && mat_traits<B>::cols=="<<c<<"," NL
489             TAB3 "deduce_mat<B> >::type" NL
490             TAB2<<name<<"( A a, B const & b )" NL
491             ;
492         }
493 
494     void
header_vr_va_sb(output_file & out,int d,std::string const & name)495     header_vr_va_sb( output_file & out, int d, std::string const & name )
496         {
497         assert(d>0);
498         assert(!name.empty());
499         out.require_include(INCLUDE_DEDUCE_V);
500         out.stream()<<
501             TAB2 "template <class A,class B>" NL
502             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
503             TAB2 "typename lazy_enable_if_c<" NL
504             TAB3 "vec_traits<A>::dim=="<<d<<" && is_scalar<B>::value," NL
505             TAB3 "deduce_vec<A> >::type" NL
506             TAB2<<name<<"( A const & a, B b )" NL
507             ;
508         }
509 
510     void
header_vr_sa_vb(output_file & out,int d,std::string const & name)511     header_vr_sa_vb( output_file & out, int d, std::string const & name )
512         {
513         assert(d>0);
514         assert(!name.empty());
515         out.require_include(INCLUDE_DEDUCE_V);
516         out.stream()<<
517             TAB2 "template <class A,class B>" NL
518             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
519             TAB2 "typename lazy_enable_if_c<" NL
520             TAB3 "is_scalar<A>::value && vec_traits<B>::dim=="<<d<<"," NL
521             TAB3 "deduce_vec<B> >::type" NL
522             TAB2<<name<<"( A a, B const & b )" NL
523             ;
524         }
525 
526     void
header_ma_sb(output_file & out,int r,int c,std::string const & name)527     header_ma_sb( output_file & out, int r, int c, std::string const & name )
528         {
529         assert(r>0);
530         assert(c>0);
531         assert(!name.empty());
532         out.stream()<<
533             TAB2 "template <class A,class B>" NL
534             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
535             TAB2 "typename enable_if_c<" NL
536             TAB3 "mat_traits<A>::rows=="<<r<<" && mat_traits<A>::cols=="<<c<<" && is_scalar<B>::value," NL
537             TAB3 "A &>::type" NL
538             TAB2<<name<<"( A & a, B b )" NL
539             ;
540         }
541 
542     void
header_va_sb(output_file & out,int d,std::string const & name)543     header_va_sb( output_file & out, int d, std::string const & name )
544         {
545         assert(d>0);
546         assert(!name.empty());
547         out.stream()<<
548             TAB2 "template <class A,class  B>" NL
549             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
550             TAB2 "typename enable_if_c<" NL
551             TAB3 "vec_traits<A>::dim=="<<d<<" && is_scalar<B>::value," NL
552             TAB3 "A &>::type" NL
553             TAB2<<name<<"( A & a, B b )" NL
554             ;
555         }
556 
557     void
defined(std::ostream & g,int r,int cr,int c,std::string fn,char const * suffix)558     defined( std::ostream & g, int r, int cr, int c, std::string fn, char const * suffix )
559         {
560         assert(r>0);
561         assert(cr>0);
562         assert(c>0);
563         assert(!fn.empty());
564         std::string dn=deduce_name(fn,suffix);
565         std::string name=dn+"_defined";
566         g<<
567             NL
568             TAB2 "namespace" NL
569             TAB2 "sfinae" NL
570             TAB3 "{" NL
571             TAB3 "using ::boost::qvm::"<<fn<<";" NL
572             TAB3 "}" NL
573             NL
574             TAB2 "namespace" NL
575             TAB2 "qvm_detail" NL
576             TAB3 "{" NL
577             TAB3 "template <int R,int /*CR*/,int C>" NL
578             TAB3 "struct "<<name<<";" NL
579             NL
580             TAB3 "template <>" NL
581             TAB3 "struct" NL
582             TAB3<<name<<'<'<<r<<','<<cr<<','<<c<<">" NL
583             TAB4"{" NL
584             TAB4"static bool const value=true;" NL
585             TAB4"};" NL
586             TAB3 "}" NL
587             NL
588             ;
589         }
590 
591     void
defined(std::ostream & g,int r,int c,std::string const & fn,char const * suffix)592     defined( std::ostream & g, int r, int c, std::string const & fn, char const * suffix )
593         {
594         assert(r>0);
595         assert(c>0);
596         assert(!fn.empty());
597         std::string dn=deduce_name(fn,suffix);
598         std::string name=dn+"_defined";
599         g<<
600             NL
601             TAB2 "namespace" NL
602             TAB2 "sfinae" NL
603             TAB3 "{" NL
604             TAB3 "using ::boost::qvm::"<<fn<<";" NL
605             TAB3 "}" NL
606             NL
607             TAB2 "namespace" NL
608             TAB2 "qvm_detail" NL
609             TAB3 "{" NL
610             TAB3 "template <int R,int C>" NL
611             TAB3 "struct "<<name<<";" NL
612             NL
613             TAB3 "template <>" NL
614             TAB3 "struct" NL
615             TAB3<<name<<"<"<<r<<","<<c<<">" NL
616             TAB4"{" NL
617             TAB4"static bool const value=true;" NL
618             TAB4"};" NL
619             TAB3 "}" NL
620             NL
621             ;
622         }
623 
624     void
defined(std::ostream & g,int d,std::string const & fn,char const * suffix)625     defined( std::ostream & g, int d, std::string const & fn, char const * suffix )
626         {
627         assert(d>0);
628         assert(!fn.empty());
629         std::string dn=deduce_name(fn,suffix);
630         std::string name=dn+"_defined";
631         g<<
632             NL
633             TAB2 "namespace" NL
634             TAB2 "sfinae" NL
635             TAB3 "{" NL
636             TAB3 "using ::boost::qvm::"<<fn<<";" NL
637             TAB3 "}" NL
638             NL
639             TAB2 "namespace" NL
640             TAB2 "qvm_detail" NL
641             TAB3 "{" NL
642             TAB3 "template <int D>" NL
643             TAB3 "struct "<<name<<";" NL
644             NL
645             TAB3 "template <>" NL
646             TAB3 "struct" NL
647             TAB3<<name<<"<"<<d<<">" NL
648             TAB4"{" NL
649             TAB4"static bool const value=true;" NL
650             TAB4"};" NL
651             TAB3 "}" NL
652             NL
653             ;
654         }
655 
656     void
mr_mult_ma_mb(output_file & out,int m,int n,int p,char const * suffix)657     mr_mult_ma_mb( output_file & out, int m, int n, int p, char const * suffix )
658         {
659         assert(m>0);
660         assert(n>0);
661         assert(p>0);
662         header_mr_ma_mb_mult(out,m,n,p,"operator*");
663         out.require_include(INCLUDE_DEDUCE_M);
664         std::ostream & g=out.stream();
665         g<<
666             TAB3 "{" NL
667             TAB3 "typedef typename mat_traits<A>::scalar_type Ta;" NL
668             TAB3 "typedef typename mat_traits<B>::scalar_type Tb;" NL
669             ;
670         for( int i=0; i!=m; ++i )
671             for( int j=0; j!=n; ++j )
672                 g<<TAB3 "Ta const a"<<i<<j<<" = mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL;
673         for( int i=0; i!=n; ++i )
674             for( int j=0; j!=p; ++j )
675                 g<<TAB3 "Tb const b"<<i<<j<<" = mat_traits<B>::template read_element<"<<i<<','<<j<<">(b);" NL;
676         g<<
677             TAB3 "typedef typename deduce_mat2<A,B,"<<m<<','<<p<<">::type R;" NL
678             TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows=="<<m<<");" NL
679             TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols=="<<p<<");" NL
680             TAB3 "R r;" NL
681             ;
682         for( int i=0; i!=m; ++i )
683             for( int j=0; j!=p; ++j )
684                 {
685                 g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)=";
686                 for( int k=0; k!=n; ++k )
687                     {
688                     if( k )
689                         g<<'+';
690                     g<<'a'<<i<<k<<"*b"<<k<<j;
691                     }
692                 g<<";" NL;
693                 }
694         g<<
695             TAB3 "return r;" NL
696             TAB3 "}" NL
697             ;
698         defined(g,m,n,p,"operator*",suffix);
699         }
700 
701     void
ma_mult_ma_mb(output_file & out,int d,char const * suffix)702     ma_mult_ma_mb( output_file & out, int d, char const * suffix )
703         {
704         assert(d>0);
705         header_ma_mb_same_size(out,d,d,"operator*=");
706         std::ostream & g=out.stream();
707         g<<
708             TAB3 "{" NL
709             TAB3 "typedef typename mat_traits<A>::scalar_type Ta;" NL
710             TAB3 "typedef typename mat_traits<B>::scalar_type Tb;" NL
711             ;
712         for( int i=0; i!=d; ++i )
713             for( int j=0; j!=d; ++j )
714                 g<<TAB3 "Ta const a"<<i<<j<<" = mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL;
715         for( int i=0; i!=d; ++i )
716             for( int j=0; j!=d; ++j )
717                 g<<TAB3 "Tb const b"<<i<<j<<" = mat_traits<B>::template read_element<"<<i<<','<<j<<">(b);" NL;
718         for( int i=0; i!=d; ++i )
719             for( int j=0; j!=d; ++j )
720                 {
721                 g<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)=";
722                 for( int k=0; k!=d; ++k )
723                     {
724                     if( k )
725                         g<<'+';
726                     g<<'a'<<i<<k<<"*b"<<k<<j;
727                     }
728                 g<<";" NL;
729                 }
730         g<<
731             TAB3 "return a;" NL
732             TAB3 "}" NL
733             ;
734         defined(g,d,"operator*=",suffix);
735         }
736 
737     void
vr_mult_ma_vb(output_file & out,int r,int c,char const * suffix)738     vr_mult_ma_vb( output_file & out, int r, int c, char const * suffix )
739         {
740         assert(r>0);
741         assert(c>0);
742         header_vr_ma_vb_mult(out,r,c,"operator*");
743         out.require_include(INCLUDE_INLINE);
744         out.require_include(INCLUDE_V_TRAITS);
745         out.require_include(INCLUDE_M_TRAITS);
746         out.require_include(INCLUDE_ENABLE_IF);
747         out.require_include(INCLUDE_DEDUCE_V);
748         std::ostream & g=out.stream();
749         g<<
750             TAB3 "{" NL
751             TAB3 "typedef typename mat_traits<A>::scalar_type Ta;" NL
752             TAB3 "typedef typename vec_traits<B>::scalar_type Tb;" NL
753             ;
754         for( int i=0; i!=r; ++i )
755             for( int j=0; j!=c; ++j )
756                 g<<TAB3 "Ta const a"<<i<<j<<" = mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL;
757         for( int i=0; i!=c; ++i )
758             g<<TAB3 "Tb const b"<<i<<" = vec_traits<B>::template read_element<"<<i<<">(b);" NL;
759         g<<
760             TAB3 "typedef typename deduce_vec2<A,B,"<<c<<">::type R;" NL
761             TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim=="<<c<<");" NL
762             TAB3 "R r;" NL
763             ;
764         for( int i=0; i!=r; ++i )
765             {
766             g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=";
767             for( int j=0; j!=c; ++j )
768                 {
769                 if( j )
770                     g<<'+';
771                 g<<'a'<<i<<j<<"*b"<<j;
772                 }
773             g<<";" NL;
774             }
775         g<<
776             TAB3 "return r;" NL
777             TAB3 "}" NL
778             ;
779         defined(g,r,c,"operator*",suffix);
780         }
781 
782     void
vr_mult_va_mb(output_file & out,int r,int c,char const * suffix)783     vr_mult_va_mb( output_file & out, int r, int c, char const * suffix )
784         {
785         assert(r>0);
786         assert(c>0);
787         header_vr_va_mb_mult(out,r,c,"operator*");
788         out.require_include(INCLUDE_INLINE);
789         out.require_include(INCLUDE_V_TRAITS);
790         out.require_include(INCLUDE_M_TRAITS);
791         out.require_include(INCLUDE_ENABLE_IF);
792         out.require_include(INCLUDE_DEDUCE_V);
793         std::ostream & g=out.stream();
794         g<<
795             TAB3 "{" NL
796             TAB3 "typedef typename vec_traits<A>::scalar_type Ta;" NL
797             TAB3 "typedef typename mat_traits<B>::scalar_type Tb;" NL
798             ;
799         for( int i=0; i!=r; ++i )
800             g<<TAB3 "Ta const a"<<i<<" = vec_traits<A>::template read_element<"<<i<<">(a);" NL;
801         for( int i=0; i!=r; ++i )
802             for( int j=0; j!=c; ++j )
803                 g<<TAB3 "Tb const b"<<i<<j<<" = mat_traits<B>::template read_element<"<<i<<','<<j<<">(b);" NL;
804         g<<
805             TAB3 "typedef typename deduce_vec2<A,B,"<<r<<">::type R;" NL
806             TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim=="<<r<<");" NL
807             TAB3 "R r;" NL
808             ;
809         for( int i=0; i!=c; ++i )
810             {
811             g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=";
812             for( int j=0; j!=r; ++j )
813                 {
814                 if( j )
815                     g<<'+';
816                 g<<'a'<<j<<"*b"<<j<<i;
817                 }
818             g<<";" NL;
819             }
820         g<<
821             TAB3 "return r;" NL
822             TAB3 "}" NL
823             ;
824         defined(g,r,c,"operator*",suffix);
825         }
826 
827     void
vr_op_va_vb_same_size(output_file & out,int d,std::string const & fn,std::string const & op,char const * suffix)828     vr_op_va_vb_same_size( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix )
829         {
830         assert(!op.empty());
831         header_vr_va_vb_same_size(out,d,fn);
832         out.require_include(INCLUDE_DEDUCE_V);
833         std::ostream & g=out.stream();
834         g<<
835             TAB3 "{" NL
836             TAB3 "typedef typename deduce_vec2<A,B,"<<d<<">::type R;" NL
837             TAB3 "BOOST_QVM_STATIC_ASSERT(vec_traits<R>::dim=="<<d<<");" NL
838             TAB3 "R r;" NL
839             ;
840         for( int i=0; i!=d; ++i )
841             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;
842         g<<
843             TAB3 "return r;" NL
844             TAB3 "}" NL
845             ;
846         defined(g,d,fn,suffix);
847         }
848 
849     void
bool_eq_ma_mb(output_file & out,int r,int c,char const * suffix)850     bool_eq_ma_mb( output_file & out, int r, int c, char const * suffix )
851         {
852         header_bool_ma_mb_same_size(out,r,c,"operator==");
853         std::ostream & g=out.stream();
854         g<<
855             TAB3 "{" NL
856             TAB3 "return" NL
857             ;
858         for( int i=0; i!=r; ++i )
859             for( int j=0; j!=c; ++j )
860                 g<<
861                     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;
862                     ;
863         g<<
864             TAB3 "}" NL
865             ;
866         defined(g,r,c,"operator==",suffix);
867         }
868 
869     void
bool_eq_va_vb(output_file & out,int d,char const * suffix)870     bool_eq_va_vb( output_file & out, int d, char const * suffix )
871         {
872         header_bool_va_vb_same_size(out,d,"operator==");
873         std::ostream & g=out.stream();
874         g<<
875             TAB3 "{" NL
876             TAB3 "return" NL
877             ;
878         for( int i=0; i!=d; ++i )
879             g<<
880                 TAB4"vec_traits<A>::template read_element<"<<i<<">(a)==vec_traits<B>::template read_element<"<<i<<">(b)"<<(i!=d-1?" &&":";")<<NL;
881                 ;
882         g<<
883             TAB3 "}" NL
884             ;
885         defined(g,d,"operator==",suffix);
886         }
887 
888     void
bool_neq_ma_mb(output_file & out,int r,int c,char const * suffix)889     bool_neq_ma_mb( output_file & out, int r, int c, char const * suffix )
890         {
891         header_bool_ma_mb_same_size(out,r,c,"operator!=");
892         std::ostream & g=out.stream();
893         g<<
894             TAB3 "{" NL
895             TAB3 "return" NL
896             ;
897         for( int i=0; i!=r; ++i )
898             for( int j=0; j!=c; ++j )
899                 g<<
900                     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;
901                     ;
902         g<<
903             TAB3 "}" NL
904             ;
905         defined(g,r,c,"operator!=",suffix);
906         }
907 
908     void
bool_neq_va_vb(output_file & out,int d,char const * suffix)909     bool_neq_va_vb( output_file & out, int d, char const * suffix )
910         {
911         header_bool_va_vb_same_size(out,d,"operator!=");
912         std::ostream & g=out.stream();
913         g<<
914             TAB3 "{" NL
915             TAB3 "return" NL
916             ;
917         for( int i=0; i!=d; ++i )
918             g<<
919                 TAB4"!(vec_traits<A>::template read_element<"<<i<<">(a)==vec_traits<B>::template read_element<"<<i<<">(b))"<<(i!=d-1?" ||":";")<<NL;
920                 ;
921         g<<
922             TAB3 "}" NL
923             ;
924         defined(g,d,"operator!=",suffix);
925         }
926 
927     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)928     mr_op_ma_mb_same_size( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix )
929         {
930         assert(r>0);
931         assert(c>0);
932         assert(!op.empty());
933         header_mr_ma_mb_same_size(out,r,c,fn);
934         out.require_include(INCLUDE_DEDUCE_M);
935         std::ostream & g=out.stream();
936         g<<
937             TAB3 "{" NL
938             TAB3 "typedef typename deduce_mat2<A,B,"<<r<<','<<c<<">::type R;" NL
939             TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::rows=="<<r<<");" NL
940             TAB3 "BOOST_QVM_STATIC_ASSERT(mat_traits<R>::cols=="<<c<<");" NL
941             TAB3 "R r;" NL
942             ;
943         for( int i=0; i!=r; ++i )
944             for( int j=0; j!=c; ++j )
945                 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;
946         g<<
947             TAB3 "return r;" NL
948             TAB3 "}" NL
949             ;
950         defined(g,r,c,fn,suffix);
951         }
952 
953     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)954     ma_op_ma_mb_same_size( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix )
955         {
956         assert(!op.empty());
957         header_ma_mb_same_size(out,r,c,fn);
958         std::ostream & g=out.stream();
959         g<<TAB3 "{" NL;
960         for( int i=0; i!=r; ++i )
961             for( int j=0; j!=c; ++j )
962                 g<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)"<<op<<"mat_traits<B>::template read_element<"<<i<<","<<j<<">(b);" NL;
963         g<<
964             TAB3 "return a;" NL
965             TAB3 "}" NL
966             ;
967         defined(g,r,c,fn,suffix);
968         }
969 
970     void
va_op_va_vb_same_size(output_file & out,int d,std::string const & fn,std::string const & op,char const * suffix)971     va_op_va_vb_same_size( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix )
972         {
973         assert(!op.empty());
974         header_va_vb_same_size(out,d,fn);
975         std::ostream & g=out.stream();
976         g<<TAB3 "{" NL;
977         for( int i=0; i!=d; ++i )
978             g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)"<<op<<"vec_traits<B>::template read_element<"<<i<<">(b);" NL;
979         g<<
980             TAB3 "return a;" NL
981             TAB3 "}" NL
982             ;
983         defined(g,d,fn,suffix);
984         }
985 
986     void
mr_op_ma(output_file & out,int r,int c,std::string const & fn,std::string const & op,char const * suffix)987     mr_op_ma( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix )
988         {
989         assert(!op.empty());
990         header_mr_ma(out,r,c,fn);
991         out.require_include(INCLUDE_DEDUCE_M);
992         std::ostream & g=out.stream();
993         g<<
994             TAB3 "{" NL
995             TAB3 "typedef typename deduce_mat<A>::type R;" NL
996             TAB3 "R r;" NL
997             ;
998         for( int i=0; i!=r; ++i )
999             for( int j=0; j!=c; ++j )
1000                 g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)="<<op<<"mat_traits<A>::template read_element<"<<i<<","<<j<<">(a);" NL;
1001         g<<
1002             TAB3 "return r;" NL
1003             TAB3 "}" NL
1004             ;
1005         defined(g,r,c,fn,suffix);
1006         }
1007 
1008     void
vr_op_va(output_file & out,int d,std::string const & fn,std::string const & op,char const * suffix)1009     vr_op_va( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix )
1010         {
1011         assert(!op.empty());
1012         header_vr_va(out,d,fn);
1013         out.require_include(INCLUDE_DEDUCE_V);
1014         std::ostream & g=out.stream();
1015         g<<
1016             TAB3 "{" NL
1017             TAB3 "typedef typename deduce_vec<A>::type R;" NL
1018             TAB3 "R r;" NL
1019             ;
1020         for( int i=0; i!=d; ++i )
1021             g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)="<<op<<"vec_traits<A>::template read_element<"<<i<<">(a);" NL;
1022         g<<
1023             TAB3 "return r;" NL
1024             TAB3 "}" NL
1025             ;
1026         defined(g,d,fn,suffix);
1027         }
1028 
1029     void
mr_op_ma_sb(output_file & out,int r,int c,std::string const & fn,std::string const & op,char const * suffix)1030     mr_op_ma_sb( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix )
1031         {
1032         assert(!op.empty());
1033         header_mr_ma_sb(out,r,c,fn);
1034         out.require_include(INCLUDE_DEDUCE_M);
1035         out.require_include(INCLUDE_DEDUCE_V);
1036         std::ostream & g=out.stream();
1037         g<<
1038             TAB3 "{" NL
1039             TAB3 "typedef typename deduce_mat<A>::type R;" NL
1040             TAB3 "R r;" NL
1041             ;
1042         for( int i=0; i!=r; ++i )
1043             for( int j=0; j!=c; ++j )
1044                 g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)=mat_traits<A>::template read_element<"<<i<<","<<j<<">(a)"<<op<<"b;" NL;
1045         g<<
1046             TAB3 "return r;" NL
1047             TAB3 "}" NL
1048             ;
1049         defined(g,r,c,fn,suffix);
1050         }
1051 
1052     void
mr_op_sa_mb(output_file & out,int r,int c,std::string const & fn,std::string const & op,char const * suffix)1053     mr_op_sa_mb( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix )
1054         {
1055         assert(!op.empty());
1056         header_mr_sa_mb(out,r,c,fn);
1057         out.require_include(INCLUDE_DEDUCE_M);
1058         out.require_include(INCLUDE_DEDUCE_V);
1059         std::ostream & g=out.stream();
1060         g<<
1061             TAB3 "{" NL
1062             TAB3 "typedef typename deduce_mat<B>::type R;" NL
1063             TAB3 "R r;" NL
1064             ;
1065         for( int i=0; i!=r; ++i )
1066             for( int j=0; j!=c; ++j )
1067                 g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r)=a"<<op<<"mat_traits<B>::template read_element<"<<i<<","<<j<<">(b);" NL;
1068         g<<
1069             TAB3 "return r;" NL
1070             TAB3 "}" NL
1071             ;
1072         defined(g,r,c,fn,suffix);
1073         }
1074 
1075     void
vr_op_va_sb(output_file & out,int d,std::string const & fn,std::string const & op,char const * suffix)1076     vr_op_va_sb( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix )
1077         {
1078         assert(!op.empty());
1079         header_vr_va_sb(out,d,fn);
1080         out.require_include(INCLUDE_DEDUCE_V);
1081         std::ostream & g=out.stream();
1082         g<<
1083             TAB3 "{" NL
1084             TAB3 "typedef typename deduce_vec<A>::type R;" NL
1085             TAB3 "R r;" NL
1086             ;
1087         for( int i=0; i!=d; ++i )
1088             g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=vec_traits<A>::template read_element<"<<i<<">(a)"<<op<<"b;" NL;
1089         g<<
1090             TAB3 "return r;" NL
1091             TAB3 "}" NL
1092             ;
1093         defined(g,d,fn,suffix);
1094         }
1095 
1096     void
vr_op_sa_vb(output_file & out,int d,std::string const & fn,std::string const & op,char const * suffix)1097     vr_op_sa_vb( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix )
1098         {
1099         assert(!op.empty());
1100         header_vr_sa_vb(out,d,fn);
1101         out.require_include(INCLUDE_DEDUCE_V);
1102         std::ostream & g=out.stream();
1103         g<<
1104             TAB3 "{" NL
1105             TAB3 "typedef typename deduce_vec<B>::type R;" NL
1106             TAB3 "R r;" NL
1107             ;
1108         for( int i=0; i!=d; ++i )
1109             g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=a"<<op<<"vec_traits<B>::template read_element<"<<i<<">(b);" NL;
1110         g<<
1111             TAB3 "return r;" NL
1112             TAB3 "}" NL
1113             ;
1114         defined(g,d,fn,suffix);
1115         }
1116 
1117     void
ma_op_ma_sb(output_file & out,int r,int c,std::string const & fn,std::string const & op,char const * suffix)1118     ma_op_ma_sb( output_file & out, int r, int c, std::string const & fn, std::string const & op, char const * suffix )
1119         {
1120         assert(!op.empty());
1121         header_ma_sb(out,r,c,fn);
1122         std::ostream & g=out.stream();
1123         g<<
1124             TAB3 "{" NL
1125             ;
1126         for( int i=0; i!=r; ++i )
1127             for( int j=0; j!=c; ++j )
1128                 g<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)"<<op<<"b;" NL;
1129         g<<
1130             TAB3 "return a;" NL
1131             TAB3 "}" NL
1132             ;
1133         defined(g,r,c,fn,suffix);
1134         }
1135 
1136     void
va_op_va_sb(output_file & out,int d,std::string const & fn,std::string const & op,char const * suffix)1137     va_op_va_sb( output_file & out, int d, std::string const & fn, std::string const & op, char const * suffix )
1138         {
1139         assert(!op.empty());
1140         header_va_sb(out,d,fn);
1141         std::ostream & g=out.stream();
1142         g<<
1143             TAB3 "{" NL
1144             ;
1145         for( int i=0; i!=d; ++i )
1146             g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)"<<op<<"b;" NL;
1147         g<<
1148             TAB3 "return a;" NL
1149             TAB3 "}" NL
1150             ;
1151         defined(g,d,fn,suffix);
1152         }
1153 
1154     void
ma_assign_ma_mb(output_file & out,int r,int c,char const * suffix)1155     ma_assign_ma_mb( output_file & out, int r, int c, char const * suffix )
1156         {
1157         header_ma_mb_same_size(out,r,c,"assign");
1158         out.require_include(INCLUDE_M_TRAITS);
1159         out.require_include(INCLUDE_INLINE);
1160         out.require_include(INCLUDE_ENABLE_IF);
1161         std::ostream & g=out.stream();
1162         g<<TAB3 "{" NL;
1163         for( int i=0; i!=r; ++i )
1164             for( int j=0; j!=c; ++j )
1165                 g<<TAB3 "mat_traits<A>::template write_element<"<<i<<","<<j<<">(a)=mat_traits<B>::template read_element<"<<i<<","<<j<<">(b);" NL;
1166         g<<
1167             TAB3 "return a;" NL
1168             TAB3 "}" NL
1169             ;
1170         defined(g,r,c,"assign",suffix);
1171         }
1172 
1173     void
va_assign_va_vb(output_file & out,int d,char const * suffix)1174     va_assign_va_vb( output_file & out, int d, char const * suffix )
1175         {
1176         header_va_vb_same_size(out,d,"assign");
1177         out.require_include(INCLUDE_V_TRAITS);
1178         out.require_include(INCLUDE_INLINE);
1179         out.require_include(INCLUDE_ENABLE_IF);
1180         std::ostream & g=out.stream();
1181         g<<TAB3 "{" NL;
1182         for( int i=0; i!=d; ++i )
1183             g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)=vec_traits<B>::template read_element<"<<i<<">(b);" NL;
1184         g<<
1185             TAB3 "return a;" NL
1186             TAB3 "}" NL
1187             ;
1188         defined(g,d,"assign",suffix);
1189         }
1190 
1191     void
mr_convert_to_ma(output_file & out,int r,int c,char const * suffix)1192     mr_convert_to_ma( output_file & out, int r, int c, char const * suffix )
1193         {
1194         if( r==c && r>=3 )
1195             {
1196             out.require_include(INCLUDE_Q_TRAITS);
1197             out.require_include(INCLUDE_S_TRAITS);
1198             }
1199         std::ostream & g=out.stream();
1200         g<<
1201             TAB2 "template <class R,class A>" NL
1202             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
1203             TAB2 "typename enable_if_c<" NL
1204             TAB3 "mat_traits<R>::rows=="<<r<<" && mat_traits<A>::rows=="<<r<<" &&" NL
1205             TAB3 "mat_traits<R>::cols=="<<c<<" && mat_traits<A>::cols=="<<c<<"," NL
1206             TAB3 "R>::type" NL
1207             TAB2<<"convert_to( A const & a )" NL
1208             TAB3 "{" NL
1209             TAB3 "R r;" NL
1210             ;
1211         for( int i=0; i!=r; ++i )
1212             for( int j=0; j!=c; ++j )
1213                 g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r) = mat_traits<A>::template read_element<"<<i<<","<<j<<">(a);" NL;
1214         g<<
1215             TAB3 "return r;" NL
1216             TAB3 "}" NL
1217             ;
1218         if( r==c && r>=3 )
1219             {
1220             g<<
1221                 NL
1222                 TAB2 "template <class R,class A>" NL
1223                 TAB2 "BOOST_QVM_INLINE" NL
1224                 TAB2 "typename enable_if_c<" NL
1225                 TAB3 "is_mat<R>::value && is_quat<A>::value &&" NL
1226                 TAB3 "mat_traits<R>::rows=="<<r<<" && mat_traits<R>::cols=="<<c<<"," NL
1227                 TAB3 "R>::type" NL
1228                 TAB2 "convert_to( A const & q )" NL
1229                 TAB3 "{" NL
1230                 TAB3 "typedef typename mat_traits<R>::scalar_type T;" NL
1231                 TAB3 "T const a=quat_traits<A>::template read_element<0>(q);" NL
1232                 TAB3 "T const b=quat_traits<A>::template read_element<1>(q);" NL
1233                 TAB3 "T const c=quat_traits<A>::template read_element<2>(q);" NL
1234                 TAB3 "T const d=quat_traits<A>::template read_element<3>(q);" NL
1235                 TAB3 "T const bb = b*b;" NL
1236                 TAB3 "T const cc = c*c;" NL
1237                 TAB3 "T const dd = d*d;" NL
1238                 TAB3 "T const bc = b*c;" NL
1239                 TAB3 "T const bd = b*d;" NL
1240                 TAB3 "T const cd = c*d;" NL
1241                 TAB3 "T const ab = a*b;" NL
1242                 TAB3 "T const ac = a*c;" NL
1243                 TAB3 "T const ad = a*d;" NL<<
1244                 (r>3?TAB3 "T const zero = scalar_traits<T>::value(0);" NL:"")<<
1245                 TAB3 "T const one = scalar_traits<T>::value(1);" NL
1246                 TAB3 "T const two = one+one;" NL
1247                 TAB3 "R r;" NL
1248                 TAB3 "mat_traits<R>::template write_element<0,0>(r) = one - two*(cc+dd);" NL
1249                 TAB3 "mat_traits<R>::template write_element<0,1>(r) = two*(bc-ad);" NL
1250                 TAB3 "mat_traits<R>::template write_element<0,2>(r) = two*(bd+ac);" NL
1251                 ;
1252             for( int i=3; i!=c; ++i )
1253                 g<<TAB3 "mat_traits<R>::template write_element<0,"<<i<<">(r) = zero;" NL;
1254             g<<
1255                 TAB3 "mat_traits<R>::template write_element<1,0>(r) = two*(bc+ad);" NL
1256                 TAB3 "mat_traits<R>::template write_element<1,1>(r) = one - two*(bb+dd);" NL
1257                 TAB3 "mat_traits<R>::template write_element<1,2>(r) = two*(cd-ab);" NL
1258                 ;
1259             for( int i=3; i!=c; ++i )
1260                 g<<TAB3 "mat_traits<R>::template write_element<1,"<<i<<">(r) = zero;" NL;
1261             g<<
1262                 TAB3 "mat_traits<R>::template write_element<2,0>(r) = two*(bd-ac);" NL
1263                 TAB3 "mat_traits<R>::template write_element<2,1>(r) = two*(cd+ab);" NL
1264                 TAB3 "mat_traits<R>::template write_element<2,2>(r) = one - two*(bb+cc);" NL
1265                 ;
1266             for( int i=3; i!=c; ++i )
1267                 g<<TAB3 "mat_traits<R>::template write_element<2,"<<i<<">(r) = zero;" NL;
1268             for( int i=3; i!=r; ++i )
1269                 for( int j=0; j!=c; ++j )
1270                     g<<TAB3 "mat_traits<R>::template write_element<"<<i<<","<<j<<">(r) = "<<(i==j?"one":"zero")<<";" NL;
1271             g<<
1272                 TAB3 "return r;" NL
1273                 TAB3 "}" NL
1274                 ;
1275             }
1276         defined(g,r,c,"convert_to",suffix);
1277         }
1278 
1279     void
vr_convert_to_va(output_file & out,int d,char const * suffix)1280     vr_convert_to_va( output_file & out, int d, char const * suffix )
1281         {
1282         header_vr_va_same_size(out,d,"convert_to");
1283         std::ostream & g=out.stream();
1284         g<<TAB3 "{" NL<<
1285             TAB3 "R r;" NL
1286             ;
1287         for( int i=0; i!=d; ++i )
1288             g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=vec_traits<A>::template read_element<"<<i<<">(a);" NL;
1289         g<<
1290             TAB3 "return r;" NL
1291             TAB3 "}" NL
1292             ;
1293         defined(g,d,"convert_to",suffix);
1294         }
1295 
1296     struct
1297     del_row_col
1298         {
1299         del_row_col const * next;
1300         int i, j;
1301         char var;
1302         explicit
del_row_col__anona04a1e480111::del_row_col1303         del_row_col( char var ):
1304             next(0),
1305             i(std::numeric_limits<int>::max()),
1306             j(std::numeric_limits<int>::max()),
1307             var(var)
1308             {
1309             }
del_row_col__anona04a1e480111::del_row_col1310         del_row_col( del_row_col const & next, int i, int j ):
1311             next(&next),
1312             i(i),
1313             j(j),
1314             var(next.var)
1315             {
1316             }
1317         std::pair<int,int>
idx__anona04a1e480111::del_row_col1318         idx( std::pair<int,int> const & x ) const
1319             {
1320             std::pair<int,int> r(x.first+(x.first>=i),x.second+(x.second>=j));
1321             if( next )
1322                 return next->idx(r);
1323             else
1324                 return r;
1325 
1326             }
1327         void
operator ()__anona04a1e480111::del_row_col1328         operator()( std::ostream & g, int r, int c ) const
1329             {
1330             std::pair<int,int> p=idx(std::make_pair(r,c));
1331             g << var << p.first << p.second;
1332             }
1333         };
1334 
1335     void
determinant_impl(std::ostream & g,int n,del_row_col const & a)1336     determinant_impl( std::ostream & g, int n, del_row_col const & a )
1337         {
1338         if( n==1 )
1339             return a(g,0,0);
1340         g << "(";
1341         char const * plus="";
1342         for( int i=0; i!=n; ++i,plus="+" )
1343             {
1344             g<<((i&1)?"-":plus);
1345             a(g,0,i);
1346             g<<'*';
1347             determinant_impl(g,n-1,del_row_col(a,0,i));
1348             }
1349         g << ")";
1350         }
1351 
1352     void
determinant(output_file & out,int d,char const * suffix)1353     determinant( output_file & out, int d, char const * suffix )
1354         {
1355         header_sr_ma(out,d,d,"determinant");
1356         std::ostream & g=out.stream();
1357         g<<
1358             TAB3 "{" NL
1359             TAB3 "typedef typename mat_traits<A>::scalar_type T;" NL
1360             ;
1361         for( int i=0; i!=d; ++i )
1362             for( int j=0; j!=d; ++j )
1363                 g<<TAB3<<"T const a"<<i<<j<<"=mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL;
1364         g<<TAB3 "T det=";
1365         determinant_impl(g,d,del_row_col('a'));
1366         g<<";" NL;
1367         g<<
1368             TAB3 "return det;" NL
1369             TAB3 "}" NL
1370             ;
1371         defined(g,d,"determinant",suffix);
1372         }
1373 
1374     void
inverse_ma(output_file & out,int d,char const * suffix)1375     inverse_ma( output_file & out, int d, char const * suffix )
1376         {
1377         assert(d>1);
1378         out.require_include(INCLUDE_DEDUCE_M);
1379         out.require_include(INCLUDE_ASSERT);
1380         out.require_include(INCLUDE_THROW_EXCEPTION);
1381         out.require_include(INCLUDE_ERROR);
1382         std::ostream & g=out.stream();
1383         g<<
1384             TAB2 "template <class A,class B>" NL
1385             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
1386             TAB2 "typename lazy_enable_if_c<" NL
1387             TAB3 "mat_traits<A>::rows=="<<d<<" && mat_traits<A>::cols=="<<d<<" && is_scalar<B>::value," NL
1388             TAB3 "deduce_mat<A> >::type" NL
1389             TAB2 "inverse( A const & a, B det )" NL
1390             TAB3 "{" NL
1391             TAB3 "typedef typename mat_traits<A>::scalar_type T;" NL
1392             TAB3 "BOOST_QVM_ASSERT(det!=scalar_traits<B>::value(0));" NL
1393             ;
1394         for( int i=0; i!=d; ++i )
1395             for( int j=0; j!=d; ++j )
1396                 g<<TAB3 "T const a"<<i<<j<<"=mat_traits<A>::template read_element<"<<i<<','<<j<<">(a);" NL;
1397         g<<
1398             TAB3 "T const f=scalar_traits<T>::value(1)/det;" NL
1399             TAB3 "typedef typename deduce_mat<A>::type R;" NL
1400             TAB3 "R r;" NL
1401             ;
1402         for( int i=0; i!=d; ++i )
1403             for( int j=0; j!=d; ++j )
1404                 {
1405                 g<<TAB3 "mat_traits<R>::template write_element<"<<i<<','<<j<<">(r)="<<(((i+j)&1)?'-':' ')<<"f*";
1406                 determinant_impl(g,d-1,del_row_col(del_row_col('a'),j,i));
1407                 g<<";" NL;
1408                 }
1409         g<<
1410             TAB3 "return r;" NL
1411             TAB3 "}" NL
1412             NL
1413             TAB2 "template <class A>" NL
1414             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
1415             TAB2 "typename lazy_enable_if_c<" NL
1416             TAB3 "mat_traits<A>::rows=="<<d<<" && mat_traits<A>::cols=="<<d<<"," NL
1417             TAB3 "deduce_mat<A> >::type" NL
1418             TAB2 "inverse( A const & a )" NL
1419             TAB3 "{" NL
1420             TAB3 "typedef typename mat_traits<A>::scalar_type T;" NL
1421             TAB3 "T det=determinant(a);" NL
1422             TAB3 "if( det==scalar_traits<T>::value(0) )" NL
1423             TAB4"BOOST_QVM_THROW_EXCEPTION(zero_determinant_error());" NL
1424             TAB3 "return inverse(a,det);" NL
1425             TAB3 "}" NL
1426             ;
1427         defined(g,d,"inverse",suffix);
1428         }
1429 
1430     void
mag_sqr(output_file & out,int d,char const * suffix)1431     mag_sqr( output_file & out, int d, char const * suffix )
1432         {
1433         header_sr_va(out,d,"mag_sqr");
1434         out.require_include(INCLUDE_MATH);
1435         std::ostream & g=out.stream();
1436         g<<
1437             TAB3 "{" NL
1438             TAB3 "typedef typename vec_traits<A>::scalar_type T;" NL
1439             ;
1440         for( int i=0; i!=d; ++i )
1441             g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL;
1442         g<<TAB3 "T const m2=";
1443         for( int i=0; i!=d; ++i )
1444             {
1445             if( i )
1446                 g<<'+';
1447             g<<'a'<<i<<"*a"<<i;
1448             }
1449         g<<
1450             ";" NL
1451             TAB3 "return m2;" NL
1452             TAB3 "}" NL
1453             ;
1454         defined(g,d,"mag_sqr",suffix);
1455         }
1456 
1457     void
mag(output_file & out,int d,char const * suffix)1458     mag( output_file & out, int d, char const * suffix )
1459         {
1460         header_sr_va(out,d,"mag");
1461         out.require_include(INCLUDE_MATH);
1462         std::ostream & g=out.stream();
1463         g<<
1464             TAB3 "{" NL
1465             TAB3 "typedef typename vec_traits<A>::scalar_type T;" NL
1466             ;
1467         for( int i=0; i!=d; ++i )
1468             g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL;
1469         g<<TAB3 "T const m2=";
1470         for( int i=0; i!=d; ++i )
1471             {
1472             if( i )
1473                 g<<'+';
1474             g<<'a'<<i<<"*a"<<i;
1475             }
1476         g<<
1477             ";" NL
1478             TAB3 "T const mag=sqrt<T>(m2);" NL
1479             TAB3 "return mag;" NL
1480             TAB3 "}" NL
1481             ;
1482         defined(g,d,"mag",suffix);
1483         }
1484 
1485     void
normalize(output_file & out,int d,char const * suffix)1486     normalize( output_file & out, int d, char const * suffix )
1487         {
1488         header_vr_va(out,d,"normalized");
1489         out.require_include(INCLUDE_MATH);
1490         out.require_include(INCLUDE_THROW_EXCEPTION);
1491         out.require_include(INCLUDE_ERROR);
1492         out.require_include(INCLUDE_DEDUCE_V);
1493         std::ostream & g=out.stream();
1494         g<<
1495             TAB3 "{" NL
1496             TAB3 "typedef typename vec_traits<A>::scalar_type T;" NL
1497             ;
1498         for( int i=0; i!=d; ++i )
1499             g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL;
1500         g<<TAB3 "T const m2=";
1501         for( int i=0; i!=d; ++i )
1502             {
1503             if( i )
1504                 g<<'+';
1505             g<<'a'<<i<<"*a"<<i;
1506             }
1507         g<<
1508             ";" NL
1509             TAB3 "if( m2==scalar_traits<typename vec_traits<A>::scalar_type>::value(0) )" NL
1510             TAB4"BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());" NL
1511             TAB3 "T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);" NL
1512             TAB3 "typedef typename deduce_vec<A>::type R;" NL
1513             TAB3 "R r;" NL
1514             ;
1515         for( int i=0; i!=d; ++i )
1516             g<<TAB3 "vec_traits<R>::template write_element<"<<i<<">(r)=a"<<i<<"*rm;" NL;
1517         g<<
1518             TAB3 "return r;" NL
1519             TAB3 "}" NL
1520             NL
1521             TAB2 "namespace" NL
1522             TAB2 "sfinae" NL
1523             TAB3 "{" NL
1524             TAB3 "using ::boost::qvm::normalized;" NL
1525             TAB3 "}" NL
1526             NL
1527             TAB2 "template <class A>" NL
1528             TAB2 "BOOST_QVM_INLINE_OPERATIONS" NL
1529             TAB2 "typename enable_if_c<" NL
1530             TAB3 "vec_traits<A>::dim=="<<d<<"," NL
1531             TAB3 "void>::type" NL
1532             TAB2<<"normalize( A & a )" NL
1533             TAB3 "{" NL
1534             TAB3 "typedef typename vec_traits<A>::scalar_type T;" NL
1535             ;
1536         for( int i=0; i!=d; ++i )
1537             g<<TAB3 "T const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL;
1538         g<<TAB3 "T const m2=";
1539         for( int i=0; i!=d; ++i )
1540             {
1541             if( i )
1542                 g<<'+';
1543             g<<'a'<<i<<"*a"<<i;
1544             }
1545         g<<
1546             ";" NL
1547             TAB3 "if( m2==scalar_traits<typename vec_traits<A>::scalar_type>::value(0) )" NL
1548             TAB4"BOOST_QVM_THROW_EXCEPTION(zero_magnitude_error());" NL
1549             TAB3 "T const rm=scalar_traits<T>::value(1)/sqrt<T>(m2);" NL
1550             ;
1551         for( int i=0; i!=d; ++i )
1552             g<<TAB3 "vec_traits<A>::template write_element<"<<i<<">(a)*=rm;" NL;
1553         g<<TAB3 "}" NL;
1554         defined(g,d,"normalize",suffix);
1555         }
1556 
1557     void
dot(output_file & out,int d,char const * suffix)1558     dot( output_file & out, int d, char const * suffix )
1559         {
1560         header_sr_va_vb(out,d,"dot");
1561         out.require_include(INCLUDE_DEDUCE_S);
1562         out.require_include(INCLUDE_STATIC_ASSERT);
1563         std::ostream & g=out.stream();
1564         g<<
1565             TAB3 "{" NL
1566             TAB3 "typedef typename vec_traits<A>::scalar_type Ta;" NL
1567             TAB3 "typedef typename vec_traits<B>::scalar_type Tb;" NL
1568             TAB3 "typedef typename deduce_scalar<Ta,Tb>::type Tr;" NL
1569             ;
1570         for( int i=0; i!=d; ++i )
1571             g<<TAB3 "Ta const a"<<i<<"=vec_traits<A>::template read_element<"<<i<<">(a);" NL;
1572         for( int i=0; i!=d; ++i )
1573             g<<TAB3 "Tb const b"<<i<<"=vec_traits<B>::template read_element<"<<i<<">(b);" NL;
1574         g<<TAB3 "Tr const dot=";
1575         for( int i=0; i!=d; ++i )
1576             {
1577             if( i )
1578                 g<<'+';
1579             g<<'a'<<i<<"*b"<<i;
1580             }
1581         g<<
1582             ";" NL
1583             TAB3 "return dot;" NL
1584             TAB3 "}" NL
1585             ;
1586         defined(g,d,"dot",suffix);
1587         }
1588 
1589     struct
1590     swizzle_pair
1591         {
1592         char ch;
1593         int idx;
1594         };
1595 
1596     template <int N>
1597     void
swizzle_impl(std::ostream & g,int d,swizzle_pair const (& ids)[N],std::vector<int> const & initial_count)1598     swizzle_impl( std::ostream & g, int d, swizzle_pair const (&ids)[N], std::vector<int> const & initial_count )
1599         {
1600         assert(d>=2);
1601         std::vector<int> count(initial_count);
1602         for( char const * const ref_id[2] = { " const &", " &" };; )
1603             {
1604             int max_dim=-100;
1605             for( int i=0; i!=d; ++i )
1606                 max_dim=std::max(max_dim,ids[count[i]-1].idx);
1607             if( max_dim<0 )
1608                 {
1609                 g<<
1610                     TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL
1611                     TAB2 "qvm_detail::sw01_<";
1612                 for( int k=0; k!=d; ++k )
1613                     g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<<ids[count[k]-1].idx;
1614                 for( int k=0; k!=d; ++k )
1615                     g<<" >";
1616                 g<<
1617                     " > const &" NL
1618                     TAB2 "_";
1619                 for( int k=0; k!=d; ++k )
1620                     {
1621                     char f=ids[count[k]-1].ch;
1622                     assert(f>='0' && f<='9');
1623                     g<<f;
1624                     }
1625                 g<<
1626                     "()" NL
1627                     TAB3 "{" NL
1628                     TAB3 "return *reinterpret_cast<qvm_detail::sw01_<";
1629                 for( int k=0; k!=d; ++k )
1630                     g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<<ids[count[k]-1].idx;
1631                 for( int k=0; k!=d; ++k )
1632                     g<<" >";
1633                 g<<
1634                     " > const *>(qvm_detail::get_null());" NL
1635                     TAB3 "}" NL;
1636                 }
1637             else
1638                 for( int rfid=0; rfid<2; ++rfid )
1639                     {
1640                     for( int scalar=0; scalar!=2; ++scalar )
1641                         {
1642                         if( scalar && max_dim>0 )
1643                             break;
1644                         if( scalar )
1645                             g<<
1646                                 TAB2 "template <class S>" NL
1647                                 TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL
1648                                 TAB2 "typename enable_if_c<" NL
1649                                 TAB3 "is_scalar<S>::value," NL
1650                                 TAB3 "qvm_detail::sws_<S,";
1651                         else
1652                             g<<
1653                                 TAB2 "template <class V>" NL
1654                                 TAB2 "BOOST_QVM_INLINE_TRIVIAL" NL
1655                                 TAB2 "typename enable_if_c<" NL
1656                                 TAB3 "is_vec<V>::value && vec_traits<V>::dim>="<<max_dim+1<<"," NL
1657                                 TAB3 "qvm_detail::sw_<V,";
1658                         for( int k=0; k!=d; ++k )
1659                             g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<<ids[count[k]-1].idx;
1660                         for( int k=0; k!=d; ++k )
1661                             g<<" >";
1662                         g<<" >"<<ref_id[rfid]<<">::type" NL TAB2;
1663                         for( int k=0; k!=d; ++k )
1664                             {
1665                             char f=ids[count[k]-1].ch;
1666                             if( !k && f>='0' && f<='9' )
1667                                 g<<'_';
1668                             g<<f;
1669                             }
1670                         if( scalar )
1671                             g<<
1672                                 "( S"<<ref_id[rfid]<<" a )" NL
1673                                 TAB3 "{" NL
1674                                 TAB3 "return reinterpret_cast<qvm_detail::sws_<S,";
1675                         else
1676                             g<<
1677                                 "( V"<<ref_id[rfid]<<" a )" NL
1678                                 TAB3 "{" NL
1679                                 TAB3 "return reinterpret_cast<qvm_detail::sw_<V,";
1680                         for( int k=0; k!=d; ++k )
1681                             g<<(k?",":"")<<"qvm_detail::swizzle_idx<"<<ids[count[k]-1].idx;
1682                         for( int k=0; k!=d; ++k )
1683                             g<<" >";
1684                         g<<
1685                             " >"<<ref_id[rfid]<<">(a);" NL
1686                             TAB3 "}" NL;
1687                         }
1688                     }
1689             int j;
1690             for( j=0; j!=d; ++j )
1691                 if( --count[j] )
1692                     break;
1693                 else
1694                     count[j]=initial_count[j];
1695             if( j==d )
1696                 break;
1697             }
1698         }
1699 
1700     void
swizzle(output_file & out,int d)1701     swizzle( output_file & out, int d )
1702         {
1703         assert(d>1);
1704         out.require_include(INCLUDE_INLINE);
1705         out.require_include(INCLUDE_SWIZZLE_TRAITS);
1706         out.require_include(INCLUDE_ENABLE_IF);
1707         std::ostream & g=out.stream();
1708         swizzle_pair const swizzle_ids[6] =
1709             {
1710                 {'X',0},
1711                 {'Y',1},
1712                 {'Z',2},
1713                 {'W',3},
1714                 {'0',-1},
1715                 {'1',-2}
1716             };
1717         std::vector<int> initial_count(d,6);
1718         swizzle_impl(g,d,swizzle_ids,initial_count);
1719         }
1720 
1721     command_line_options
parse_command_line(int argc,char const * argv[])1722     parse_command_line( int argc, char const * argv[] )
1723         {
1724         class
1725         next
1726             {
1727             char const * const * const argv;
1728             public:
1729             int const argc;
1730             next( int argc, char const * argv[] ):
1731                 argv(argv),
1732                 argc(argc)
1733                 {
1734                 }
1735             std::string
1736             operator()( int & i ) const
1737                 {
1738                 assert(i<argc);
1739                 if( ++i==argc )
1740                     BOOST_THROW_EXCEPTION(bad_command_line() << cmd_arg(argv[i-1]));
1741                 return argv[i];
1742                 }
1743             } next_token(argc,argv);
1744         command_line_options r;
1745         for( int i=1; i!=argc; ++i )
1746             if( argv[i][0]=='-' )
1747                 {
1748                 char const * arg=argv[i];
1749                 if( arg==std::string("-od") )
1750                     r.output_directory=next_token(i);
1751                 else if( arg==std::string("-con") )
1752                     r.con=true;
1753                 else
1754                     BOOST_THROW_EXCEPTION(bad_command_line() << cmd_arg(arg));
1755                 }
1756         return r;
1757         }
1758 
1759     void
gen(int argc,char const * argv[])1760     gen( int argc, char const * argv[] )
1761         {
1762         command_line_options opt=parse_command_line(argc,argv);
1763         for( int d=2; d!=5; ++d )
1764             {
1765             output_file f(opt);
1766                 {
1767                 char buf[1024];
1768                 sprintf(buf,INCLUDE_MAT_ASSIGN,d);
1769                 f.require_include(buf);
1770                 }
1771             mr_op_ma_mb_same_size(f,d,d,"operator+","+","mm");
1772             mr_op_ma_mb_same_size(f,d,1,"operator+","+","mm");
1773             mr_op_ma_mb_same_size(f,1,d,"operator+","+","mm");
1774             mr_op_ma_mb_same_size(f,d,d,"operator-","-","mm");
1775             mr_op_ma_mb_same_size(f,d,1,"operator-","-","mm");
1776             mr_op_ma_mb_same_size(f,1,d,"operator-","-","mm");
1777             ma_op_ma_mb_same_size(f,d,d,"operator+=","+=","mm");
1778             ma_op_ma_mb_same_size(f,d,1,"operator+=","+=","mm");
1779             ma_op_ma_mb_same_size(f,1,d,"operator+=","+=","mm");
1780             ma_op_ma_mb_same_size(f,d,d,"operator-=","-=","mm");
1781             ma_op_ma_mb_same_size(f,d,1,"operator-=","-=","mm");
1782             ma_op_ma_mb_same_size(f,1,d,"operator-=","-=","mm");
1783             mr_op_ma_sb(f,d,d,"operator*","*","ms");
1784             mr_op_sa_mb(f,d,d,"operator*","*","sm");
1785             mr_op_ma_sb(f,d,1,"operator*","*","ms");
1786             mr_op_sa_mb(f,d,1,"operator*","*","sm");
1787             mr_op_ma_sb(f,1,d,"operator*","*","ms");
1788             mr_op_sa_mb(f,1,d,"operator*","*","sm");
1789             ma_op_ma_sb(f,d,d,"operator*=","*=","ms");
1790             ma_op_ma_sb(f,d,1,"operator*=","*=","ms");
1791             ma_op_ma_sb(f,1,d,"operator*=","*=","ms");
1792             mr_op_ma_sb(f,d,d,"operator/","/","ms");
1793             mr_op_sa_mb(f,d,d,"operator/","/","sm");
1794             mr_op_ma_sb(f,d,1,"operator/","/","ms");
1795             mr_op_sa_mb(f,d,1,"operator/","/","sm");
1796             mr_op_ma_sb(f,1,d,"operator/","/","ms");
1797             ma_op_ma_sb(f,d,d,"operator/=","/=","ms");
1798             ma_op_ma_sb(f,d,1,"operator/=","/=","ms");
1799             ma_op_ma_sb(f,1,d,"operator/=","/=","ms");
1800             mr_convert_to_ma(f,d,d,"m");
1801             mr_convert_to_ma(f,d,1,"m");
1802             mr_convert_to_ma(f,1,d,"m");
1803             bool_eq_ma_mb(f,d,d,"mm");
1804             bool_eq_ma_mb(f,d,1,"mm");
1805             bool_eq_ma_mb(f,1,d,"mm");
1806             bool_neq_ma_mb(f,d,d,"mm");
1807             bool_neq_ma_mb(f,d,1,"mm");
1808             bool_neq_ma_mb(f,1,d,"mm");
1809             mr_op_ma(f,d,d,"operator-","-","m");
1810             mr_op_ma(f,d,1,"operator-","-","m");
1811             mr_op_ma(f,1,d,"operator-","-","m");
1812             determinant(f,d,0);
1813             inverse_ma(f,d,"m");
1814             mr_mult_ma_mb(f,d,d,d,"mm");
1815             ma_mult_ma_mb(f,d,"mm");
1816             mr_mult_ma_mb(f,d,d,1,"mm");
1817             mr_mult_ma_mb(f,1,d,d,"mm");
1818             f.dump("mat_operations"+to_string(d)+".hpp");
1819             }
1820 
1821         for( int d=2; d!=5; ++d )
1822             {
1823             output_file f(opt);
1824             ma_assign_ma_mb(f,d,d,"mm");
1825             ma_assign_ma_mb(f,d,1,"mm");
1826             ma_assign_ma_mb(f,1,d,"mm");
1827             f.dump("mat_assign"+to_string(d)+".hpp");
1828             }
1829 
1830         for( int d=2; d!=5; ++d )
1831             {
1832             output_file f(opt);
1833                 {
1834                 char buf[1024];
1835                 sprintf(buf,INCLUDE_VEC_ASSIGN,d);
1836                 f.require_include(buf);
1837                 }
1838             vr_op_va_vb_same_size(f,d,"operator+","+","vv");
1839             vr_op_va_vb_same_size(f,d,"operator-","-","vv");
1840             va_op_va_vb_same_size(f,d,"operator+=","+=","vv");
1841             va_op_va_vb_same_size(f,d,"operator-=","-=","vv");
1842             vr_op_va_sb(f,d,"operator*","*","vs");
1843             vr_op_sa_vb(f,d,"operator*","*","sv");
1844             va_op_va_sb(f,d,"operator*=","*=","vs");
1845             vr_op_va_sb(f,d,"operator/","/","vs");
1846             va_op_va_sb(f,d,"operator/=","/=","vs");
1847             vr_convert_to_va(f,d,"v");
1848             bool_eq_va_vb(f,d,"vv");
1849             bool_neq_va_vb(f,d,"vv");
1850             vr_op_va(f,d,"operator-","-","v");
1851             mag(f,d,"v");
1852             mag_sqr(f,d,"v");
1853             normalize(f,d,"v");
1854             dot(f,d,"vv");
1855             f.dump("vec_operations"+to_string(d)+".hpp");
1856             }
1857 
1858         for( int d=2; d!=5; ++d )
1859             {
1860             output_file f(opt);
1861             va_assign_va_vb(f,d,"vv");
1862             f.dump("vec_assign"+to_string(d)+".hpp");
1863             }
1864 
1865         for( int d=2; d!=5; ++d )
1866             {
1867             output_file f(opt);
1868             vr_mult_ma_vb(f,d,d,"mv");
1869             vr_mult_va_mb(f,d,d,"vm");
1870             f.dump("vec_mat_operations"+to_string(d)+".hpp");
1871             }
1872 
1873             {
1874             output_file f(opt);
1875             swizzle(f,2);
1876             f.dump("swizzle2.hpp");
1877             }
1878             {
1879             output_file f(opt);
1880             swizzle(f,3);
1881             f.dump("swizzle3.hpp");
1882             }
1883             {
1884             output_file f(opt);
1885             swizzle(f,4);
1886             f.dump("swizzle4.hpp");
1887             }
1888         }
1889     }
1890 
1891 int
main(int argc,char const * argv[])1892 main( int argc, char const * argv[] )
1893     {
1894     try
1895         {
1896         gen(argc,argv);
1897         }
1898     catch(
1899     std::ifstream::failure & )
1900         {
1901         std::cerr << "Failed to write generated output file" << std::endl;
1902         }
1903     catch(
1904     ... )
1905         {
1906         std::cerr << "Unexpected exception" << std::endl << boost::current_exception_diagnostic_information();
1907         }
1908     return 1;
1909     }
1910