SourceForge Logo Tiny Vector Matrix library using Expression Templates Sourceforge Project Page

include/tvmet/VectorOperators.h

Go to the documentation of this file.
00001 /*
00002  * Tiny Vector Matrix Library
00003  * Dense Vector Matrix Libary of Tiny size using Expression Templates
00004  *
00005  * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.net>
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * $Id: VectorOperators.h,v 1.18 2007-06-23 15:58:58 opetzold Exp $
00022  */
00023 
00024 #ifndef TVMET_VECTOR_OPERATORS_H
00025 #define TVMET_VECTOR_OPERATORS_H
00026 
00027 namespace tvmet {
00028 
00029 
00030 /*********************************************************
00031  * PART I: DECLARATION
00032  *********************************************************/
00033 
00034 
00035 template<class T, std::size_t Sz>
00036 inline
00037 std::ostream& operator<<(std::ostream& os,
00038        const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00039 
00040 
00041 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00042  * Member operators (arithmetic and bit ops)
00043  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
00044 
00045 
00046 /*
00047  * update_operator(Vector<T1, Sz>,  Vector<T2, Sz>)
00048  * update_operator(Vector<T1, Sz>,  XprVector<E, Sz>)
00049  * Note: per se element wise
00050  */
00051 #define TVMET_DECLARE_MACRO(NAME, OP)         \
00052 template<class T1, class T2, std::size_t Sz>        \
00053 Vector<T1, Sz>&               \
00054 operator OP (Vector<T1, Sz>& lhs,         \
00055        const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;  \
00056                   \
00057 template<class T, class E, std::size_t Sz>        \
00058 Vector<T, Sz>&                \
00059 operator OP (Vector<T, Sz>& lhs,          \
00060        const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00061 
00062 TVMET_DECLARE_MACRO(add_eq, +=)   // per se element wise
00063 TVMET_DECLARE_MACRO(sub_eq, -=)   // per se element wise
00064 TVMET_DECLARE_MACRO(mul_eq, *=)   // per se element wise
00065 namespace element_wise {
00066   TVMET_DECLARE_MACRO(div_eq, /=)   // not defined for vectors
00067 }
00068 
00069 // integer operators only, e.g used on double you wil get an error
00070 namespace element_wise {
00071   TVMET_DECLARE_MACRO(mod_eq, %=)
00072   TVMET_DECLARE_MACRO(xor_eq, ^=)
00073   TVMET_DECLARE_MACRO(and_eq, &=)
00074   TVMET_DECLARE_MACRO(or_eq, |=)
00075   TVMET_DECLARE_MACRO(shl_eq, <<=)
00076   TVMET_DECLARE_MACRO(shr_eq, >>=)
00077 }
00078 
00079 #undef TVMET_DECLARE_MACRO
00080 
00081 
00082 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00083  * Vector arithmetic operators implemented by functions
00084  * add, sub, mul and div
00085  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
00086 
00087 
00088 /*
00089  * operator(Vector<T1, Sz>, Vector<T2, Sz>)
00090  * operator(Vector<T1, Sz>, XprVector<E, Sz>)
00091  * operator(XprVector<E, Sz>, Vector<T1, Sz>)
00092  */
00093 #define TVMET_DECLARE_MACRO(NAME, OP)         \
00094 template<class T1, class T2, std::size_t Sz>        \
00095 XprVector<                \
00096   XprBinOp<               \
00097     Fcnl_##NAME<T1, T2>,            \
00098     VectorConstReference<T1, Sz>,         \
00099     VectorConstReference<T2, Sz>          \
00100   >,                  \
00101   Sz                  \
00102 >                 \
00103 operator OP (const Vector<T1, Sz>& lhs,         \
00104        const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;  \
00105                   \
00106 template<class E, class T, std::size_t Sz>        \
00107 XprVector<                \
00108   XprBinOp<               \
00109     Fcnl_##NAME<typename E::value_type, T>,       \
00110     XprVector<E, Sz>,             \
00111     VectorConstReference<T, Sz>           \
00112   >,                  \
00113   Sz                  \
00114 >                 \
00115 operator OP (const XprVector<E, Sz>& lhs,       \
00116        const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;   \
00117                   \
00118 template<class E, class T, std::size_t Sz>        \
00119 XprVector<                \
00120   XprBinOp<               \
00121     Fcnl_##NAME<T, typename E::value_type>,       \
00122     VectorConstReference<T, Sz>,          \
00123     XprVector<E, Sz>              \
00124   >,                  \
00125   Sz                  \
00126 >                 \
00127 operator OP (const Vector<T, Sz>& lhs,          \
00128        const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00129 
00130 TVMET_DECLARE_MACRO(add, +)   // per se element wise
00131 TVMET_DECLARE_MACRO(sub, -)   // per se element wise
00132 TVMET_DECLARE_MACRO(mul, *)   // per se element wise
00133 namespace element_wise {
00134   TVMET_DECLARE_MACRO(div, /)   // not defined for vectors
00135 }
00136 
00137 #undef TVMET_DECLARE_MACRO
00138 
00139 
00140 /*
00141  * operator(Vector<T, Sz>, POD)
00142  * operator(POD, Vector<T, Sz>)
00143  * Note: operations +,-,*,/ are per se element wise
00144  */
00145 #define TVMET_DECLARE_MACRO(NAME, OP, POD)      \
00146 template<class T, std::size_t Sz>       \
00147 XprVector<              \
00148   XprBinOp<             \
00149     Fcnl_##NAME< T, POD >,          \
00150     VectorConstReference<T, Sz>,        \
00151     XprLiteral< POD >           \
00152   >,                \
00153   Sz                \
00154 >               \
00155 operator OP (const Vector<T, Sz>& lhs,        \
00156        POD rhs) TVMET_CXX_ALWAYS_INLINE;      \
00157                 \
00158 template<class T, std::size_t Sz>       \
00159 XprVector<              \
00160   XprBinOp<             \
00161     Fcnl_##NAME< POD, T>,         \
00162     XprLiteral< POD >,            \
00163     VectorConstReference<T, Sz>         \
00164   >,                \
00165   Sz                \
00166 >               \
00167 operator OP (POD lhs,             \
00168        const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00169 
00170 TVMET_DECLARE_MACRO(add, +, int)
00171 TVMET_DECLARE_MACRO(sub, -, int)
00172 TVMET_DECLARE_MACRO(mul, *, int)
00173 TVMET_DECLARE_MACRO(div, /, int)
00174 
00175 #if defined(TVMET_HAVE_LONG_LONG)
00176 TVMET_DECLARE_MACRO(add, +, long long int)
00177 TVMET_DECLARE_MACRO(sub, -, long long int)
00178 TVMET_DECLARE_MACRO(mul, *, long long int)
00179 TVMET_DECLARE_MACRO(div, /, long long int)
00180 #endif
00181 
00182 TVMET_DECLARE_MACRO(add, +, float)
00183 TVMET_DECLARE_MACRO(sub, -, float)
00184 TVMET_DECLARE_MACRO(mul, *, float)
00185 TVMET_DECLARE_MACRO(div, /, float)
00186 
00187 TVMET_DECLARE_MACRO(add, +, double)
00188 TVMET_DECLARE_MACRO(sub, -, double)
00189 TVMET_DECLARE_MACRO(mul, *, double)
00190 TVMET_DECLARE_MACRO(div, /, double)
00191 
00192 #if defined(TVMET_HAVE_LONG_DOUBLE)
00193 TVMET_DECLARE_MACRO(add, +, long double)
00194 TVMET_DECLARE_MACRO(sub, -, long double)
00195 TVMET_DECLARE_MACRO(mul, *, long double)
00196 TVMET_DECLARE_MACRO(div, /, long double)
00197 #endif
00198 
00199 #undef TVMET_DECLARE_MACRO
00200 
00201 
00202 #if defined(TVMET_HAVE_COMPLEX)
00203 /*
00204  * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
00205  * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
00206  * Note: operations +,-,*,/ are per se element wise
00207  * \todo type promotion
00208  */
00209 #define TVMET_DECLARE_MACRO(NAME, OP)           \
00210 template<class T, std::size_t Sz>           \
00211 XprVector<                  \
00212   XprBinOp<                 \
00213     Fcnl_##NAME< std::complex<T>, std::complex<T> >,        \
00214     VectorConstReference< std::complex<T>, Sz>,         \
00215     XprLiteral< std::complex<T> >           \
00216   >,                    \
00217   Sz                    \
00218 >                   \
00219 operator OP (const Vector<std::complex<T>, Sz>& lhs,        \
00220        const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;   \
00221                     \
00222 template<class T, std::size_t Sz>           \
00223 XprVector<                  \
00224   XprBinOp<                 \
00225     Fcnl_##NAME< std::complex<T>, std::complex<T> >,        \
00226     XprLiteral< std::complex<T> >,            \
00227     VectorConstReference< std::complex<T>, Sz>          \
00228   >,                    \
00229   Sz                    \
00230 >                   \
00231 operator OP (const std::complex<T>& lhs,          \
00232        const Vector< std::complex<T>, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00233 
00234 TVMET_DECLARE_MACRO(add, +)   // per se element wise
00235 TVMET_DECLARE_MACRO(sub, -)   // per se element wise
00236 TVMET_DECLARE_MACRO(mul, *)   // per se element wise
00237 TVMET_DECLARE_MACRO(div, /)   // per se element wise
00238 #undef TVMET_DECLARE_MACRO
00239 
00240 #endif // defined(TVMET_HAVE_COMPLEX)
00241 
00242 
00243 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00244  * Vector integer and compare operators
00245  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
00246 
00247 
00248 /*
00249  * operator(Vector<T1, Sz>, Vector<T2, Sz>)
00250  * operator(XprVector<E, Sz>, Vector<T, Sz>)
00251  * operator(Vector<T, Sz>, XprVector<E, Sz>)
00252  * Note: operations are per se element wise
00253  */
00254 #define TVMET_DECLARE_MACRO(NAME, OP)         \
00255 template<class T1, class T2, std::size_t Sz>        \
00256 XprVector<                \
00257   XprBinOp<               \
00258     Fcnl_##NAME<T1, T2>,            \
00259     VectorConstReference<T1, Sz>,         \
00260     VectorConstReference<T2, Sz>          \
00261   >,                  \
00262   Sz                  \
00263 >                 \
00264 operator OP (const Vector<T1, Sz>& lhs,         \
00265        const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;  \
00266                   \
00267 template<class E, class T, std::size_t Sz>        \
00268 XprVector<                \
00269   XprBinOp<               \
00270     Fcnl_##NAME<typename E::value_type, T>,       \
00271     XprVector<E, Sz>,             \
00272     VectorConstReference<T, Sz>           \
00273   >,                  \
00274   Sz                  \
00275 >                 \
00276 operator OP (const XprVector<E, Sz>& lhs,         \
00277        const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;   \
00278                   \
00279 template<class E, class T, std::size_t Sz>        \
00280 XprVector<                \
00281   XprBinOp<               \
00282     Fcnl_##NAME<T, typename E::value_type>,       \
00283     VectorConstReference<T, Sz>,          \
00284     XprVector<E, Sz>              \
00285   >,                  \
00286   Sz                  \
00287 >                 \
00288 operator OP (const Vector<T, Sz>& lhs,          \
00289        const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00290 
00291 // integer operators only, e.g used on double you wil get an error
00292 namespace element_wise {
00293   TVMET_DECLARE_MACRO(mod, %)
00294   TVMET_DECLARE_MACRO(bitxor, ^)
00295   TVMET_DECLARE_MACRO(bitand, &)
00296   TVMET_DECLARE_MACRO(bitor, |)
00297   TVMET_DECLARE_MACRO(shl, <<)
00298   TVMET_DECLARE_MACRO(shr, >>)
00299 }
00300 
00301 // necessary operators for eval functions
00302 TVMET_DECLARE_MACRO(greater, >)
00303 TVMET_DECLARE_MACRO(less, <)
00304 TVMET_DECLARE_MACRO(greater_eq, >=)
00305 TVMET_DECLARE_MACRO(less_eq, <=)
00306 TVMET_DECLARE_MACRO(eq, ==)
00307 TVMET_DECLARE_MACRO(not_eq, !=)
00308 TVMET_DECLARE_MACRO(and, &&)
00309 TVMET_DECLARE_MACRO(or, ||)
00310 
00311 #undef TVMET_DECLARE_MACRO
00312 
00313 
00314 
00315 #if defined(TVMET_HAVE_COMPLEX)
00316 /*
00317  * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
00318  * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
00319  * Note: - per se element wise
00320  *       - bit ops on complex<int> doesn't make sense, stay away
00321  * \todo type promotion
00322  */
00323 #define TVMET_DECLARE_MACRO(NAME, OP)           \
00324 template<class T, std::size_t Sz>           \
00325 XprVector<                  \
00326   XprBinOp<                 \
00327     Fcnl_##NAME< std::complex<T>, std::complex<T> >,        \
00328     VectorConstReference< std::complex<T>, Sz>,         \
00329     XprLiteral< std::complex<T> >           \
00330   >,                    \
00331   Sz                    \
00332 >                   \
00333 operator OP (const Vector<std::complex<T>, Sz>& lhs,        \
00334        const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;   \
00335                     \
00336 template<class T, std::size_t Sz>           \
00337 XprVector<                  \
00338   XprBinOp<                 \
00339     Fcnl_##NAME< std::complex<T>, std::complex<T> >,        \
00340     XprLiteral< std::complex<T> >,            \
00341     VectorConstReference< std::complex<T>, Sz>          \
00342   >,                    \
00343   Sz                    \
00344 >                   \
00345 operator OP (const std::complex<T>& lhs,          \
00346        const Vector< std::complex<T>, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00347 
00348 // necessary operators for eval functions
00349 TVMET_DECLARE_MACRO(greater, >)
00350 TVMET_DECLARE_MACRO(less, <)
00351 TVMET_DECLARE_MACRO(greater_eq, >=)
00352 TVMET_DECLARE_MACRO(less_eq, <=)
00353 TVMET_DECLARE_MACRO(eq, ==)
00354 TVMET_DECLARE_MACRO(not_eq, !=)
00355 TVMET_DECLARE_MACRO(and, &&)
00356 TVMET_DECLARE_MACRO(or, ||)
00357 
00358 #undef TVMET_DECLARE_MACRO
00359 
00360 #endif // defined(TVMET_HAVE_COMPLEX)
00361 
00362 
00363 /*
00364  * operator(Vector<T, Sz>, POD)
00365  * operator(POD, Vector<T, Sz>)
00366  * Note: operations are per se element_wise
00367  */
00368 #define TVMET_DECLARE_MACRO(NAME, OP, TP)       \
00369 template<class T, std::size_t Sz>         \
00370 XprVector<                \
00371   XprBinOp<               \
00372     Fcnl_##NAME< T, TP >,           \
00373     VectorConstReference<T, Sz>,          \
00374     XprLiteral< TP >              \
00375   >,                  \
00376   Sz                  \
00377 >                 \
00378 operator OP (const Vector<T, Sz>& lhs, TP rhs) TVMET_CXX_ALWAYS_INLINE; \
00379                   \
00380 template<class T, std::size_t Sz>         \
00381 XprVector<                \
00382   XprBinOp<               \
00383     Fcnl_##NAME< TP, T>,            \
00384     XprLiteral< TP >,             \
00385     VectorConstReference<T, Sz>           \
00386   >,                  \
00387   Sz                  \
00388 >                 \
00389 operator OP (TP lhs, const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00390 
00391 // integer operators only, e.g used on double you wil get an error
00392 namespace element_wise {
00393   TVMET_DECLARE_MACRO(mod, %, int)
00394   TVMET_DECLARE_MACRO(bitxor, ^, int)
00395   TVMET_DECLARE_MACRO(bitand, &, int)
00396   TVMET_DECLARE_MACRO(bitor, |, int)
00397   TVMET_DECLARE_MACRO(shl, <<, int)
00398   TVMET_DECLARE_MACRO(shr, >>, int)
00399 }
00400 
00401 // necessary operators for eval functions
00402 TVMET_DECLARE_MACRO(greater, >, int)
00403 TVMET_DECLARE_MACRO(less, <, int)
00404 TVMET_DECLARE_MACRO(greater_eq, >=, int)
00405 TVMET_DECLARE_MACRO(less_eq, <=, int)
00406 TVMET_DECLARE_MACRO(eq, ==, int)
00407 TVMET_DECLARE_MACRO(not_eq, !=, int)
00408 TVMET_DECLARE_MACRO(and, &&, int)
00409 TVMET_DECLARE_MACRO(or, ||, int)
00410 
00411 #if defined(TVMET_HAVE_LONG_LONG)
00412 // integer operators only
00413 namespace element_wise {
00414   TVMET_DECLARE_MACRO(mod, %, long long int)
00415   TVMET_DECLARE_MACRO(bitxor, ^, long long int)
00416   TVMET_DECLARE_MACRO(bitand, &, long long int)
00417   TVMET_DECLARE_MACRO(bitor, |, long long int)
00418   TVMET_DECLARE_MACRO(shl, <<, long long int)
00419   TVMET_DECLARE_MACRO(shr, >>, long long int)
00420 }
00421 
00422 // necessary operators for eval functions
00423 TVMET_DECLARE_MACRO(greater, >, long long int)
00424 TVMET_DECLARE_MACRO(less, <, long long int)
00425 TVMET_DECLARE_MACRO(greater_eq, >=, long long int)
00426 TVMET_DECLARE_MACRO(less_eq, <=, long long int)
00427 TVMET_DECLARE_MACRO(eq, ==, long long int)
00428 TVMET_DECLARE_MACRO(not_eq, !=, long long int)
00429 TVMET_DECLARE_MACRO(and, &&, long long int)
00430 TVMET_DECLARE_MACRO(or, ||, long long int)
00431 #endif // defined(TVMET_HAVE_LONG_LONG)
00432 
00433 // necessary operators for eval functions
00434 TVMET_DECLARE_MACRO(greater, >, float)
00435 TVMET_DECLARE_MACRO(less, <, float)
00436 TVMET_DECLARE_MACRO(greater_eq, >=, float)
00437 TVMET_DECLARE_MACRO(less_eq, <=, float)
00438 TVMET_DECLARE_MACRO(eq, ==, float)
00439 TVMET_DECLARE_MACRO(not_eq, !=, float)
00440 TVMET_DECLARE_MACRO(and, &&, float)
00441 TVMET_DECLARE_MACRO(or, ||, float)
00442 
00443 // necessary operators for eval functions
00444 TVMET_DECLARE_MACRO(greater, >, double)
00445 TVMET_DECLARE_MACRO(less, <, double)
00446 TVMET_DECLARE_MACRO(greater_eq, >=, double)
00447 TVMET_DECLARE_MACRO(less_eq, <=, double)
00448 TVMET_DECLARE_MACRO(eq, ==, double)
00449 TVMET_DECLARE_MACRO(not_eq, !=, double)
00450 TVMET_DECLARE_MACRO(and, &&, double)
00451 TVMET_DECLARE_MACRO(or, ||, double)
00452 
00453 #if defined(TVMET_HAVE_LONG_DOUBLE)
00454 // necessary operators for eval functions
00455 TVMET_DECLARE_MACRO(greater, >, long double)
00456 TVMET_DECLARE_MACRO(less, <, long double)
00457 TVMET_DECLARE_MACRO(greater_eq, >=, long double)
00458 TVMET_DECLARE_MACRO(less_eq, <=, long double)
00459 TVMET_DECLARE_MACRO(eq, ==, long double)
00460 TVMET_DECLARE_MACRO(not_eq, !=, long double)
00461 TVMET_DECLARE_MACRO(and, &&, long double)
00462 TVMET_DECLARE_MACRO(or, ||, long double)
00463 #endif // defined(TVMET_HAVE_LONG_DOUBLE)
00464 
00465 #undef TVMET_DECLARE_MACRO
00466 
00467 
00468 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00469  * global unary operators
00470  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
00471 
00472 
00473 /*
00474  * unary_operator(Vector<T, Sz>)
00475  * Note: per se element wise
00476  */
00477 #define TVMET_DECLARE_MACRO(NAME, OP)       \
00478 template <class T, std::size_t Sz>        \
00479 XprVector<              \
00480   XprUnOp<              \
00481     Fcnl_##NAME<T>,           \
00482     VectorConstReference<T, Sz>         \
00483   >,                \
00484   Sz                \
00485 >               \
00486 operator OP (const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
00487 
00488 TVMET_DECLARE_MACRO(not, !)
00489 TVMET_DECLARE_MACRO(compl, ~)
00490 TVMET_DECLARE_MACRO(neg, -)
00491 #undef TVMET_DECLARE_MACRO
00492 
00493 
00494 /*********************************************************
00495  * PART II: IMPLEMENTATION
00496  *********************************************************/
00497 
00498 
00504 template<class T, std::size_t Sz>
00505 inline
00506 std::ostream& operator<<(std::ostream& os, const Vector<T, Sz>& rhs) {
00507   return rhs.print_on(os);
00508 }
00509 
00510 
00511 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00512  * Member operators (arithmetic and bit ops)
00513  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
00514 
00515 
00516 /*
00517  * update_operator(Vector<T1, Sz>,  Vector<T2, Sz>)
00518  * update_operator(Vector<T1, Sz>,  XprVector<E, Sz>)
00519  * Note: per se element wise
00520  */
00521 #define TVMET_IMPLEMENT_MACRO(NAME, OP)       \
00522 template<class T1, class T2, std::size_t Sz>      \
00523 inline Vector<T1, Sz>&            \
00524 operator OP (Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {  \
00525   return lhs.M_##NAME(rhs);         \
00526 }               \
00527                 \
00528 template<class T, class E, std::size_t Sz>      \
00529 inline Vector<T, Sz>&           \
00530 operator OP (Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) { \
00531   return lhs.M_##NAME(rhs);         \
00532 }
00533 
00534 TVMET_IMPLEMENT_MACRO(add_eq, +=)   // per se element wise
00535 TVMET_IMPLEMENT_MACRO(sub_eq, -=)   // per se element wise
00536 TVMET_IMPLEMENT_MACRO(mul_eq, *=)   // per se element wise
00537 namespace element_wise {
00538   TVMET_IMPLEMENT_MACRO(div_eq, /=)   // not defined for vectors
00539 }
00540 
00541 // integer operators only, e.g used on double you wil get an error
00542 namespace element_wise {
00543   TVMET_IMPLEMENT_MACRO(mod_eq, %=)
00544   TVMET_IMPLEMENT_MACRO(xor_eq, ^=)
00545   TVMET_IMPLEMENT_MACRO(and_eq, &=)
00546   TVMET_IMPLEMENT_MACRO(or_eq, |=)
00547   TVMET_IMPLEMENT_MACRO(shl_eq, <<=)
00548   TVMET_IMPLEMENT_MACRO(shr_eq, >>=)
00549 }
00550 
00551 #undef TVMET_IMPLEMENT_MACRO
00552 
00553 
00554 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00555  * Vector arithmetic operators implemented by functions
00556  * add, sub, mul and div
00557  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
00558 
00559 
00560 /*
00561  * operator(Vector<T1, Sz>, Vector<T2, Sz>)
00562  * operator(Vector<T1, Sz>, XprVector<E, Sz>)
00563  * operator(XprVector<E, Sz>, Vector<T1, Sz>)
00564  */
00565 #define TVMET_IMPLEMENT_MACRO(NAME, OP)         \
00566 template<class T1, class T2, std::size_t Sz>        \
00567 inline                  \
00568 XprVector<                \
00569   XprBinOp<               \
00570     Fcnl_##NAME<T1, T2>,            \
00571     VectorConstReference<T1, Sz>,         \
00572     VectorConstReference<T2, Sz>          \
00573   >,                  \
00574   Sz                  \
00575 >                 \
00576 operator OP (const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {  \
00577   return NAME (lhs, rhs);           \
00578 }                 \
00579                   \
00580 template<class E, class T, std::size_t Sz>        \
00581 inline                  \
00582 XprVector<                \
00583   XprBinOp<               \
00584     Fcnl_##NAME<typename E::value_type, T>,       \
00585     XprVector<E, Sz>,             \
00586     VectorConstReference<T, Sz>           \
00587   >,                  \
00588   Sz                  \
00589 >                 \
00590 operator OP (const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs) { \
00591   return NAME (lhs, rhs);           \
00592 }                 \
00593                   \
00594 template<class E, class T, std::size_t Sz>        \
00595 inline                  \
00596 XprVector<                \
00597   XprBinOp<               \
00598     Fcnl_##NAME<T, typename E::value_type>,       \
00599     VectorConstReference<T, Sz>,          \
00600     XprVector<E, Sz>              \
00601   >,                  \
00602   Sz                  \
00603 >                 \
00604 operator OP (const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) { \
00605   return NAME (lhs, rhs);           \
00606 }
00607 
00608 TVMET_IMPLEMENT_MACRO(add, +)   // per se element wise
00609 TVMET_IMPLEMENT_MACRO(sub, -)   // per se element wise
00610 TVMET_IMPLEMENT_MACRO(mul, *)   // per se element wise
00611 namespace element_wise {
00612   TVMET_IMPLEMENT_MACRO(div, /)   // not defined for vectors
00613 }
00614 
00615 #undef TVMET_IMPLEMENT_MACRO
00616 
00617 
00618 /*
00619  * operator(Vector<T, Sz>, POD)
00620  * operator(POD, Vector<T, Sz>)
00621  * Note: operations +,-,*,/ are per se element wise
00622  */
00623 #define TVMET_IMPLEMENT_MACRO(NAME, OP, POD)    \
00624 template<class T, std::size_t Sz>     \
00625 inline              \
00626 XprVector<            \
00627   XprBinOp<           \
00628     Fcnl_##NAME< T, POD >,        \
00629     VectorConstReference<T, Sz>,      \
00630     XprLiteral< POD >         \
00631   >,              \
00632   Sz              \
00633 >             \
00634 operator OP (const Vector<T, Sz>& lhs, POD rhs) { \
00635   return NAME (lhs, rhs);       \
00636 }             \
00637               \
00638 template<class T, std::size_t Sz>     \
00639 inline              \
00640 XprVector<            \
00641   XprBinOp<           \
00642     Fcnl_##NAME< POD, T>,       \
00643     XprLiteral< POD >,          \
00644     VectorConstReference<T, Sz>       \
00645   >,              \
00646   Sz              \
00647 >             \
00648 operator OP (POD lhs, const Vector<T, Sz>& rhs) { \
00649   return NAME (lhs, rhs);       \
00650 }
00651 
00652 TVMET_IMPLEMENT_MACRO(add, +, int)
00653 TVMET_IMPLEMENT_MACRO(sub, -, int)
00654 TVMET_IMPLEMENT_MACRO(mul, *, int)
00655 TVMET_IMPLEMENT_MACRO(div, /, int)
00656 
00657 #if defined(TVMET_HAVE_LONG_LONG)
00658 TVMET_IMPLEMENT_MACRO(add, +, long long int)
00659 TVMET_IMPLEMENT_MACRO(sub, -, long long int)
00660 TVMET_IMPLEMENT_MACRO(mul, *, long long int)
00661 TVMET_IMPLEMENT_MACRO(div, /, long long int)
00662 #endif
00663 
00664 TVMET_IMPLEMENT_MACRO(add, +, float)
00665 TVMET_IMPLEMENT_MACRO(sub, -, float)
00666 TVMET_IMPLEMENT_MACRO(mul, *, float)
00667 TVMET_IMPLEMENT_MACRO(div, /, float)
00668 
00669 TVMET_IMPLEMENT_MACRO(add, +, double)
00670 TVMET_IMPLEMENT_MACRO(sub, -, double)
00671 TVMET_IMPLEMENT_MACRO(mul, *, double)
00672 TVMET_IMPLEMENT_MACRO(div, /, double)
00673 
00674 #if defined(TVMET_HAVE_LONG_DOUBLE)
00675 TVMET_IMPLEMENT_MACRO(add, +, long double)
00676 TVMET_IMPLEMENT_MACRO(sub, -, long double)
00677 TVMET_IMPLEMENT_MACRO(mul, *, long double)
00678 TVMET_IMPLEMENT_MACRO(div, /, long double)
00679 #endif
00680 
00681 #undef TVMET_IMPLEMENT_MACRO
00682 
00683 
00684 #if defined(TVMET_HAVE_COMPLEX)
00685 /*
00686  * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
00687  * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
00688  * Note: operations +,-,*,/ are per se element wise
00689  * \todo type promotion
00690  */
00691 #define TVMET_IMPLEMENT_MACRO(NAME, OP)     \
00692 template<class T, std::size_t Sz>     \
00693 inline              \
00694 XprVector<            \
00695   XprBinOp<           \
00696     Fcnl_##NAME< std::complex<T>, std::complex<T> >,  \
00697     VectorConstReference< std::complex<T>, Sz>,   \
00698     XprLiteral< std::complex<T> >     \
00699   >,              \
00700   Sz              \
00701 >             \
00702 operator OP (const Vector<std::complex<T>, Sz>& lhs,  \
00703        const std::complex<T>& rhs) {    \
00704   return NAME (lhs, rhs);       \
00705 }             \
00706               \
00707 template<class T, std::size_t Sz>     \
00708 inline              \
00709 XprVector<            \
00710   XprBinOp<           \
00711     Fcnl_##NAME< std::complex<T>, std::complex<T> >,  \
00712     XprLiteral< std::complex<T> >,      \
00713     VectorConstReference< std::complex<T>, Sz>    \
00714   >,              \
00715   Sz              \
00716 >             \
00717 operator OP (const std::complex<T>& lhs,    \
00718        const Vector< std::complex<T>, Sz>& rhs) { \
00719   return NAME (lhs, rhs);       \
00720 }
00721 
00722 TVMET_IMPLEMENT_MACRO(add, +)   // per se element wise
00723 TVMET_IMPLEMENT_MACRO(sub, -)   // per se element wise
00724 TVMET_IMPLEMENT_MACRO(mul, *)   // per se element wise
00725 TVMET_IMPLEMENT_MACRO(div, /)   // per se element wise
00726 
00727 #undef TVMET_IMPLEMENT_MACRO
00728 
00729 #endif // defined(TVMET_HAVE_COMPLEX)
00730 
00731 
00732 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00733  * Vector integer and compare operators
00734  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
00735 
00736 
00737 /*
00738  * operator(Vector<T1, Sz>, Vector<T2, Sz>)
00739  * operator(XprVector<E, Sz>, Vector<T, Sz>)
00740  * operator(Vector<T, Sz>, XprVector<E, Sz>)
00741  * Note: operations are per se element wise
00742  */
00743 #define TVMET_IMPLEMENT_MACRO(NAME, OP)         \
00744 template<class T1, class T2, std::size_t Sz>        \
00745 inline                  \
00746 XprVector<                \
00747   XprBinOp<               \
00748     Fcnl_##NAME<T1, T2>,            \
00749     VectorConstReference<T1, Sz>,         \
00750     VectorConstReference<T2, Sz>          \
00751   >,                  \
00752   Sz                  \
00753 >                 \
00754 operator OP (const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {  \
00755   typedef XprBinOp <              \
00756     Fcnl_##NAME<T1, T2>,            \
00757     VectorConstReference<T1, Sz>,         \
00758     VectorConstReference<T2, Sz>          \
00759   >             expr_type;  \
00760   return XprVector<expr_type, Sz>(          \
00761     expr_type(lhs.const_ref(), rhs.const_ref()));     \
00762 }                 \
00763                   \
00764 template<class E, class T, std::size_t Sz>        \
00765 inline                  \
00766 XprVector<                \
00767   XprBinOp<               \
00768     Fcnl_##NAME<typename E::value_type, T>,       \
00769     XprVector<E, Sz>,             \
00770     VectorConstReference<T, Sz>           \
00771   >,                  \
00772   Sz                  \
00773 >                 \
00774 operator OP (const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs) { \
00775   typedef XprBinOp<             \
00776     Fcnl_##NAME<typename E::value_type, T>,       \
00777     XprVector<E, Sz>,             \
00778     VectorConstReference<T, Sz>           \
00779   >                expr_type; \
00780   return XprVector<expr_type, Sz>(          \
00781     expr_type(lhs, rhs.const_ref()));         \
00782 }                 \
00783                   \
00784 template<class E, class T, std::size_t Sz>        \
00785 inline                  \
00786 XprVector<                \
00787   XprBinOp<               \
00788     Fcnl_##NAME<T, typename E::value_type>,       \
00789     VectorConstReference<T, Sz>,          \
00790     XprVector<E, Sz>              \
00791   >,                  \
00792   Sz                  \
00793 >                 \
00794 operator OP (const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) { \
00795   typedef XprBinOp<             \
00796     Fcnl_##NAME<T, typename E::value_type>,       \
00797     VectorConstReference<T, Sz>,          \
00798     XprVector<E, Sz>              \
00799   >               expr_type;  \
00800   return XprVector<expr_type, Sz>(          \
00801     expr_type(lhs.const_ref(), rhs));         \
00802 }
00803 
00804 // integer operators only, e.g used on double you wil get an error
00805 namespace element_wise {
00806   TVMET_IMPLEMENT_MACRO(mod, %)
00807   TVMET_IMPLEMENT_MACRO(bitxor, ^)
00808   TVMET_IMPLEMENT_MACRO(bitand, &)
00809   TVMET_IMPLEMENT_MACRO(bitor, |)
00810   TVMET_IMPLEMENT_MACRO(shl, <<)
00811   TVMET_IMPLEMENT_MACRO(shr, >>)
00812 }
00813 
00814 // necessary operators for eval functions
00815 TVMET_IMPLEMENT_MACRO(greater, >)
00816 TVMET_IMPLEMENT_MACRO(less, <)
00817 TVMET_IMPLEMENT_MACRO(greater_eq, >=)
00818 TVMET_IMPLEMENT_MACRO(less_eq, <=)
00819 TVMET_IMPLEMENT_MACRO(eq, ==)
00820 TVMET_IMPLEMENT_MACRO(not_eq, !=)
00821 TVMET_IMPLEMENT_MACRO(and, &&)
00822 TVMET_IMPLEMENT_MACRO(or, ||)
00823 
00824 #undef TVMET_IMPLEMENT_MACRO
00825 
00826 
00827 #if defined(TVMET_HAVE_COMPLEX)
00828 /*
00829  * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
00830  * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
00831  * Note: - per se element wise
00832  *       - bit ops on complex<int> doesn't make sense, stay away
00833  * \todo type promotion
00834  */
00835 #define TVMET_IMPLEMENT_MACRO(NAME, OP)             \
00836 template<class T, std::size_t Sz>             \
00837 inline                      \
00838 XprVector<                    \
00839   XprBinOp<                   \
00840     Fcnl_##NAME< std::complex<T>, std::complex<T> >,          \
00841     VectorConstReference< std::complex<T>, Sz>,           \
00842     XprLiteral< std::complex<T> >             \
00843   >,                      \
00844   Sz                      \
00845 >                     \
00846 operator OP (const Vector<std::complex<T>, Sz>& lhs, const std::complex<T>& rhs) {  \
00847   typedef XprBinOp<                 \
00848     Fcnl_##NAME< std::complex<T>, std::complex<T> >,          \
00849     VectorConstReference< std::complex<T>, Sz>,           \
00850     XprLiteral< std::complex<T> >             \
00851   >             expr_type;      \
00852   return XprVector<expr_type, Sz>(              \
00853     expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));      \
00854 }                     \
00855                       \
00856 template<class T, std::size_t Sz>             \
00857 inline                      \
00858 XprVector<                    \
00859   XprBinOp<                   \
00860     Fcnl_##NAME< std::complex<T>, std::complex<T> >,          \
00861     XprLiteral< std::complex<T> >,              \
00862     VectorConstReference< std::complex<T>, Sz>            \
00863   >,                      \
00864   Sz                      \
00865 >                     \
00866 operator OP (const std::complex<T>& lhs, const Vector< std::complex<T>, Sz>& rhs) { \
00867   typedef XprBinOp<                 \
00868     Fcnl_##NAME< std::complex<T>, std::complex<T> >,          \
00869     XprLiteral< std::complex<T> >,              \
00870     VectorConstReference< std::complex<T>, Sz>            \
00871   >             expr_type;      \
00872   return XprVector<expr_type, Sz>(              \
00873     expr_type(XprLiteral< std::complex<T> >(lhs), rhs.const_ref()));      \
00874 }
00875 
00876 // necessary operators for eval functions
00877 TVMET_IMPLEMENT_MACRO(greater, >)
00878 TVMET_IMPLEMENT_MACRO(less, <)
00879 TVMET_IMPLEMENT_MACRO(greater_eq, >=)
00880 TVMET_IMPLEMENT_MACRO(less_eq, <=)
00881 TVMET_IMPLEMENT_MACRO(eq, ==)
00882 TVMET_IMPLEMENT_MACRO(not_eq, !=)
00883 TVMET_IMPLEMENT_MACRO(and, &&)
00884 TVMET_IMPLEMENT_MACRO(or, ||)
00885 
00886 #undef TVMET_IMPLEMENT_MACRO
00887 
00888 #endif // defined(TVMET_HAVE_COMPLEX)
00889 
00890 
00891 /*
00892  * operator(Vector<T, Sz>, POD)
00893  * operator(POD, Vector<T, Sz>)
00894  * Note: operations are per se element_wise
00895  */
00896 #define TVMET_IMPLEMENT_MACRO(NAME, OP, TP)       \
00897 template<class T, std::size_t Sz>         \
00898 inline                  \
00899 XprVector<                \
00900   XprBinOp<               \
00901     Fcnl_##NAME< T, TP >,           \
00902     VectorConstReference<T, Sz>,          \
00903     XprLiteral< TP >              \
00904   >,                  \
00905   Sz                  \
00906 >                 \
00907 operator OP (const Vector<T, Sz>& lhs, TP rhs) {      \
00908   typedef XprBinOp<             \
00909     Fcnl_##NAME<T, TP >,            \
00910     VectorConstReference<T, Sz>,          \
00911     XprLiteral< TP >              \
00912   >             expr_type;  \
00913   return XprVector<expr_type, Sz>(          \
00914     expr_type(lhs.const_ref(), XprLiteral< TP >(rhs)));     \
00915 }                 \
00916                   \
00917 template<class T, std::size_t Sz>         \
00918 inline                  \
00919 XprVector<                \
00920   XprBinOp<               \
00921     Fcnl_##NAME< TP, T>,            \
00922     XprLiteral< TP >,             \
00923     VectorConstReference<T, Sz>           \
00924   >,                  \
00925   Sz                  \
00926 >                 \
00927 operator OP (TP lhs, const Vector<T, Sz>& rhs) {      \
00928   typedef XprBinOp<             \
00929     Fcnl_##NAME< TP, T>,            \
00930     XprLiteral< TP >,             \
00931     VectorConstReference<T, Sz>           \
00932   >             expr_type;  \
00933   return XprVector<expr_type, Sz>(          \
00934     expr_type(XprLiteral< TP >(lhs), rhs.const_ref()));     \
00935 }
00936 
00937 // integer operators only, e.g used on double you wil get an error
00938 namespace element_wise {
00939   TVMET_IMPLEMENT_MACRO(mod, %, int)
00940   TVMET_IMPLEMENT_MACRO(bitxor, ^, int)
00941   TVMET_IMPLEMENT_MACRO(bitand, &, int)
00942   TVMET_IMPLEMENT_MACRO(bitor, |, int)
00943   TVMET_IMPLEMENT_MACRO(shl, <<, int)
00944   TVMET_IMPLEMENT_MACRO(shr, >>, int)
00945 }
00946 
00947 // necessary operators for eval functions
00948 TVMET_IMPLEMENT_MACRO(greater, >, int)
00949 TVMET_IMPLEMENT_MACRO(less, <, int)
00950 TVMET_IMPLEMENT_MACRO(greater_eq, >=, int)
00951 TVMET_IMPLEMENT_MACRO(less_eq, <=, int)
00952 TVMET_IMPLEMENT_MACRO(eq, ==, int)
00953 TVMET_IMPLEMENT_MACRO(not_eq, !=, int)
00954 TVMET_IMPLEMENT_MACRO(and, &&, int)
00955 TVMET_IMPLEMENT_MACRO(or, ||, int)
00956 
00957 #if defined(TVMET_HAVE_LONG_LONG)
00958 // integer operators only
00959 namespace element_wise {
00960   TVMET_IMPLEMENT_MACRO(mod, %, long long int)
00961   TVMET_IMPLEMENT_MACRO(bitxor, ^, long long int)
00962   TVMET_IMPLEMENT_MACRO(bitand, &, long long int)
00963   TVMET_IMPLEMENT_MACRO(bitor, |, long long int)
00964   TVMET_IMPLEMENT_MACRO(shl, <<, long long int)
00965   TVMET_IMPLEMENT_MACRO(shr, >>, long long int)
00966 }
00967 
00968 // necessary operators for eval functions
00969 TVMET_IMPLEMENT_MACRO(greater, >, long long int)
00970 TVMET_IMPLEMENT_MACRO(less, <, long long int)
00971 TVMET_IMPLEMENT_MACRO(greater_eq, >=, long long int)
00972 TVMET_IMPLEMENT_MACRO(less_eq, <=, long long int)
00973 TVMET_IMPLEMENT_MACRO(eq, ==, long long int)
00974 TVMET_IMPLEMENT_MACRO(not_eq, !=, long long int)
00975 TVMET_IMPLEMENT_MACRO(and, &&, long long int)
00976 TVMET_IMPLEMENT_MACRO(or, ||, long long int)
00977 #endif // defined(TVMET_HAVE_LONG_LONG)
00978 
00979 // necessary operators for eval functions
00980 TVMET_IMPLEMENT_MACRO(greater, >, float)
00981 TVMET_IMPLEMENT_MACRO(less, <, float)
00982 TVMET_IMPLEMENT_MACRO(greater_eq, >=, float)
00983 TVMET_IMPLEMENT_MACRO(less_eq, <=, float)
00984 TVMET_IMPLEMENT_MACRO(eq, ==, float)
00985 TVMET_IMPLEMENT_MACRO(not_eq, !=, float)
00986 TVMET_IMPLEMENT_MACRO(and, &&, float)
00987 TVMET_IMPLEMENT_MACRO(or, ||, float)
00988 
00989 // necessary operators for eval functions
00990 TVMET_IMPLEMENT_MACRO(greater, >, double)
00991 TVMET_IMPLEMENT_MACRO(less, <, double)
00992 TVMET_IMPLEMENT_MACRO(greater_eq, >=, double)
00993 TVMET_IMPLEMENT_MACRO(less_eq, <=, double)
00994 TVMET_IMPLEMENT_MACRO(eq, ==, double)
00995 TVMET_IMPLEMENT_MACRO(not_eq, !=, double)
00996 TVMET_IMPLEMENT_MACRO(and, &&, double)
00997 TVMET_IMPLEMENT_MACRO(or, ||, double)
00998 
00999 #if defined(TVMET_HAVE_LONG_DOUBLE)
01000 // necessary operators for eval functions
01001 TVMET_IMPLEMENT_MACRO(greater, >, long double)
01002 TVMET_IMPLEMENT_MACRO(less, <, long double)
01003 TVMET_IMPLEMENT_MACRO(greater_eq, >=, long double)
01004 TVMET_IMPLEMENT_MACRO(less_eq, <=, long double)
01005 TVMET_IMPLEMENT_MACRO(eq, ==, long double)
01006 TVMET_IMPLEMENT_MACRO(not_eq, !=, long double)
01007 TVMET_IMPLEMENT_MACRO(and, &&, long double)
01008 TVMET_IMPLEMENT_MACRO(or, ||, long double)
01009 #endif // defined(TVMET_HAVE_LONG_DOUBLE)
01010 
01011 #undef TVMET_IMPLEMENT_MACRO
01012 
01013 
01014 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
01015  * global unary operators
01016  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
01017 
01018 
01019 /*
01020  * unary_operator(Vector<T, Sz>)
01021  * Note: per se element wise
01022  */
01023 #define TVMET_IMPLEMENT_MACRO(NAME, OP)         \
01024 template <class T, std::size_t Sz>          \
01025 inline                  \
01026 XprVector<                \
01027   XprUnOp<                \
01028     Fcnl_##NAME<T>,             \
01029     VectorConstReference<T, Sz>           \
01030   >,                  \
01031   Sz                  \
01032 >                 \
01033 operator OP (const Vector<T, Sz>& rhs) {        \
01034   typedef XprUnOp<              \
01035     Fcnl_##NAME<T>,             \
01036     VectorConstReference<T, Sz>           \
01037   >                expr_type; \
01038   return XprVector<expr_type, Sz>(expr_type(rhs.const_ref()));    \
01039 }
01040 
01041 TVMET_IMPLEMENT_MACRO(not, !)
01042 TVMET_IMPLEMENT_MACRO(compl, ~)
01043 TVMET_IMPLEMENT_MACRO(neg, -)
01044 
01045 #undef TVMET_IMPLEMENT_MACRO
01046 
01047 
01048 } // namespace tvmet
01049 
01050 #endif // TVMET_VECTOR_OPERATORS_H
01051 
01052 // Local Variables:
01053 // mode:C++
01054 // tab-width:8
01055 // End:

Author: