This is the Tiny Vector Matrix Expression Templates library found at http://tvmet.sourceforge.net. It is the fastest and most compact matrix lib out there (for < 10x10 matricies). I have done some minor tweaks to make it compile for mbed. For examples and hints on how to use, see: http://tvmet.sourceforge.net/usage.html
Dependents: Eurobot_2012_Secondary
VectorOperators.h
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 00499 /** 00500 * \fn operator<<(std::ostream& os, const Vector<T, Sz>& rhs) 00501 * \brief Overload operator for i/o 00502 * \ingroup _binary_operator 00503 */ 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:
Generated on Tue Jul 12 2022 19:00:12 by 1.7.2