1 ////////////////////////////////////////////////////////////////////////////////////// 2 // This file is distributed under the University of Illinois/NCSA Open Source License. 3 // See LICENSE file in top directory for details. 4 // 5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers. 6 // 7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign 8 // 9 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign 10 ////////////////////////////////////////////////////////////////////////////////////// 11 12 13 #ifndef OHMMS_TINYVECTOR_OPERATORS_H 14 #define OHMMS_TINYVECTOR_OPERATORS_H 15 #include <complex> 16 17 namespace qmcplusplus 18 { 19 template<class T1> 20 struct BinaryReturn<T1, std::complex<T1>, OpMultiply> 21 { 22 typedef std::complex<T1> Type_t; 23 }; 24 25 template<class T1> 26 struct BinaryReturn<std::complex<T1>, T1, OpMultiply> 27 { 28 typedef std::complex<T1> Type_t; 29 }; 30 31 /////////////////////////////////////////////////////////////////////// 32 // 33 // Assignment operators 34 // template<class T1, class T2, class OP> struct OTAssign {}; 35 // 36 /////////////////////////////////////////////////////////////////////// 37 38 ////////////////////////////////////////////////////////////////////// 39 // Specializations for TinyVectors of arbitrary size. 40 ////////////////////////////////////////////////////////////////////// 41 template<class T1, class T2, class OP, unsigned D> 42 struct OTAssign<TinyVector<T1, D>, TinyVector<T2, D>, OP> 43 { 44 inline static void apply(TinyVector<T1, D>& lhs, const TinyVector<T2, D>& rhs, OP op) 45 { 46 for (unsigned d = 0; d < D; ++d) 47 op(lhs[d], rhs[d]); 48 } 49 }; 50 51 template<class T1, class T2, class OP, unsigned D> 52 struct OTAssign<TinyVector<T1, D>, T2, OP> 53 { 54 inline static void apply(TinyVector<T1, D>& lhs, const T2& rhs, OP op) 55 { 56 for (unsigned d = 0; d < D; ++d) 57 op(lhs[d], rhs); 58 } 59 }; 60 61 ////////////////////////////////////////////////////////////////////// 62 // Specializations for TinyVectors with D=1. 63 ////////////////////////////////////////////////////////////////////// 64 65 template<class T1, class T2, class OP> 66 struct OTAssign<TinyVector<T1, 1>, TinyVector<T2, 1>, OP> 67 { 68 inline static void apply(TinyVector<T1, 1>& lhs, const TinyVector<T2, 1>& rhs, OP op) { op(lhs[0], rhs[0]); } 69 }; 70 71 template<class T1, class T2, class OP> 72 struct OTAssign<TinyVector<T1, 1>, T2, OP> 73 { 74 inline static void apply(TinyVector<T1, 1>& lhs, const T2& rhs, OP op) { op(lhs[0], rhs); } 75 }; 76 77 ////////////////////////////////////////////////////////////////////// 78 // Specializations for TinyVectors with D=2. 79 ////////////////////////////////////////////////////////////////////// 80 81 template<class T1, class T2, class OP> 82 struct OTAssign<TinyVector<T1, 2>, TinyVector<T2, 2>, OP> 83 { 84 inline static void apply(TinyVector<T1, 2>& lhs, const TinyVector<T2, 2>& rhs, OP op) 85 { 86 op(lhs[0], rhs[0]); 87 op(lhs[1], rhs[1]); 88 } 89 }; 90 91 template<class T1, class T2, class OP> 92 struct OTAssign<TinyVector<T1, 2>, T2, OP> 93 { 94 inline static void apply(TinyVector<T1, 2>& lhs, const T2& rhs, OP op) 95 { 96 op(lhs[0], rhs); 97 op(lhs[1], rhs); 98 } 99 }; 100 101 ////////////////////////////////////////////////////////////////////// 102 // Specializations for TinyVectors with D=3. 103 ////////////////////////////////////////////////////////////////////// 104 105 template<class T1, class T2, class OP> 106 struct OTAssign<TinyVector<T1, 3>, TinyVector<T2, 3>, OP> 107 { 108 inline static void apply(TinyVector<T1, 3>& lhs, const TinyVector<T2, 3>& rhs, OP op) 109 { 110 op(lhs[0], rhs[0]); 111 op(lhs[1], rhs[1]); 112 op(lhs[2], rhs[2]); 113 } 114 }; 115 116 template<class T1, class T2, class OP> 117 struct OTAssign<TinyVector<T1, 3>, TinyVector<std::complex<T2>, 3>, OP> 118 { 119 inline static void apply(TinyVector<T1, 3>& lhs, const TinyVector<std::complex<T2>, 3>& rhs, OP op) 120 { 121 op(lhs[0], rhs[0].real()); 122 op(lhs[1], rhs[1].real()); 123 op(lhs[2], rhs[2].real()); 124 } 125 }; 126 127 template<class T1, class T2, class OP> 128 struct OTAssign<TinyVector<std::complex<T1>, 3>, TinyVector<std::complex<T2>, 3>, OP> 129 { 130 inline static void apply(TinyVector<std::complex<T1>, 3>& lhs, const TinyVector<std::complex<T2>, 3>& rhs, OP op) 131 { 132 op(lhs[0], rhs[0]); 133 op(lhs[1], rhs[1]); 134 op(lhs[2], rhs[2]); 135 } 136 }; 137 138 template<class T1, class T2, class OP> 139 struct OTAssign<TinyVector<T1, 3>, T2, OP> 140 { 141 inline static void apply(TinyVector<T1, 3>& lhs, const T2& rhs, OP op) 142 { 143 op(lhs[0], rhs); 144 op(lhs[1], rhs); 145 op(lhs[2], rhs); 146 } 147 }; 148 149 /////////////////////////////////////////////////////////////////////// 150 // 151 // Binary operators 152 //template<class T1, class T2, class OP> struct OTBinary {}; 153 // 154 /////////////////////////////////////////////////////////////////////// 155 156 ////////////////////////////////////////////////////////////////////// 157 // Specializations for TinyVectors of arbitrary size. 158 ////////////////////////////////////////////////////////////////////// 159 160 template<class T1, class T2, class OP, unsigned D> 161 struct OTBinary<TinyVector<T1, D>, TinyVector<T2, D>, OP> 162 { 163 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 164 inline static TinyVector<Type_t, D> apply(const TinyVector<T1, D>& lhs, const TinyVector<T2, D>& rhs, OP op) 165 { 166 TinyVector<Type_t, D> ret; 167 for (unsigned d = 0; d < D; ++d) 168 ret[d] = op(lhs[d], rhs[d]); 169 return ret; 170 } 171 }; 172 173 template<class T1, class T2, class OP, unsigned D> 174 struct OTBinary<TinyVector<T1, D>, T2, OP> 175 { 176 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 177 inline static TinyVector<Type_t, D> apply(const TinyVector<T1, D>& lhs, const T2& rhs, OP op) 178 { 179 TinyVector<Type_t, D> ret; 180 for (unsigned d = 0; d < D; ++d) 181 ret[d] = op(lhs[d], rhs); 182 return ret; 183 } 184 }; 185 186 template<class T1, class T2, class OP, unsigned D> 187 struct OTBinary<T1, TinyVector<T2, D>, OP> 188 { 189 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 190 inline static TinyVector<Type_t, D> apply(const T1& lhs, const TinyVector<T2, D>& rhs, OP op) 191 { 192 TinyVector<Type_t, D> ret; 193 for (unsigned d = 0; d < D; ++d) 194 ret[d] = op(lhs, rhs[d]); 195 return ret; 196 } 197 }; 198 199 ////////////////////////////////////////////////////////////////////// 200 // Specializations of OTBinary for TinyVectors with D=1. 201 ////////////////////////////////////////////////////////////////////// 202 203 template<class T1, class T2, class OP> 204 struct OTBinary<TinyVector<T1, 1>, TinyVector<T2, 1>, OP> 205 { 206 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 207 inline static TinyVector<Type_t, 1> apply(const TinyVector<T1, 1>& lhs, const TinyVector<T2, 1>& rhs, OP op) 208 { 209 return TinyVector<Type_t, 1>(op(lhs[0], rhs[0])); 210 } 211 }; 212 213 template<class T1, class T2, class OP> 214 struct OTBinary<TinyVector<T1, 1>, T2, OP> 215 { 216 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 217 inline static TinyVector<Type_t, 1> apply(const TinyVector<T1, 1>& lhs, const T2& rhs, OP op) 218 { 219 return TinyVector<Type_t, 1>(op(lhs[0], rhs)); 220 } 221 }; 222 223 template<class T1, class T2, class OP> 224 struct OTBinary<T1, TinyVector<T2, 1>, OP> 225 { 226 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 227 inline static TinyVector<Type_t, 1> apply(const T1& lhs, const TinyVector<T2, 1>& rhs, OP op) 228 { 229 return TinyVector<Type_t, 1>(op(lhs, rhs[0])); 230 } 231 }; 232 233 ////////////////////////////////////////////////////////////////////// 234 // Specializations of OTBinary for TinyVectors with D=2. 235 ////////////////////////////////////////////////////////////////////// 236 237 template<class T1, class T2, class OP> 238 struct OTBinary<TinyVector<T1, 2>, TinyVector<T2, 2>, OP> 239 { 240 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 241 inline static TinyVector<Type_t, 2> apply(const TinyVector<T1, 2>& lhs, const TinyVector<T2, 2>& rhs, OP op) 242 { 243 return TinyVector<Type_t, 2>(op(lhs[0], rhs[0]), op(lhs[1], rhs[1])); 244 } 245 }; 246 247 template<class T1, class T2, class OP> 248 struct OTBinary<TinyVector<T1, 2>, T2, OP> 249 { 250 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 251 inline static TinyVector<Type_t, 2> apply(const TinyVector<T1, 2>& lhs, const T2& rhs, OP op) 252 { 253 return TinyVector<Type_t, 2>(op(lhs[0], rhs), op(lhs[1], rhs)); 254 } 255 }; 256 257 template<class T1, class T2, class OP> 258 struct OTBinary<T1, TinyVector<T2, 2>, OP> 259 { 260 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 261 inline static TinyVector<Type_t, 2> apply(const T1& lhs, const TinyVector<T2, 2>& rhs, OP op) 262 { 263 return TinyVector<Type_t, 2>(op(lhs, rhs[0]), op(lhs, rhs[1])); 264 } 265 }; 266 267 ////////////////////////////////////////////////////////////////////// 268 // Specializations of OTBinary for TinyVectors with D=3. 269 ////////////////////////////////////////////////////////////////////// 270 271 template<class T1, class T2, class OP> 272 struct OTBinary<TinyVector<T1, 3>, TinyVector<T2, 3>, OP> 273 { 274 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 275 inline static TinyVector<Type_t, 3> apply(const TinyVector<T1, 3>& lhs, const TinyVector<T2, 3>& rhs, OP op) 276 { 277 return TinyVector<Type_t, 3>(op(lhs[0], rhs[0]), op(lhs[1], rhs[1]), op(lhs[2], rhs[2])); 278 } 279 }; 280 281 template<class T1, class T2, class OP> 282 struct OTBinary<TinyVector<T1, 3>, T2, OP> 283 { 284 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 285 inline static TinyVector<Type_t, 3> apply(const TinyVector<T1, 3>& lhs, const T2& rhs, OP op) 286 { 287 return TinyVector<Type_t, 3>(op(lhs[0], rhs), op(lhs[1], rhs), op(lhs[2], rhs)); 288 } 289 }; 290 291 template<class T1, class T2, class OP> 292 struct OTBinary<T1, TinyVector<T2, 3>, OP> 293 { 294 typedef typename BinaryReturn<T1, T2, OP>::Type_t Type_t; 295 inline static TinyVector<Type_t, 3> apply(const T1& lhs, const TinyVector<T2, 3>& rhs, OP op) 296 { 297 return TinyVector<Type_t, 3>(op(lhs, rhs[0]), op(lhs, rhs[1]), op(lhs, rhs[2])); 298 } 299 }; 300 301 ////////////////////////////////////////////////////////////////////// 302 // 303 // Specializations for TinyVector dot TinyVector 304 // 305 ////////////////////////////////////////////////////////////////////// 306 307 template<class T1, class T2, unsigned D> 308 struct OTDot<TinyVector<T1, D>, TinyVector<T2, D>> 309 { 310 typedef typename BinaryReturn<T1, T2, OpMultiply>::Type_t Type_t; 311 inline static Type_t apply(const TinyVector<T1, D>& lhs, const TinyVector<T2, D>& rhs) 312 { 313 Type_t res = lhs[0] * rhs[0]; 314 for (unsigned d = 1; d < D; ++d) 315 res += lhs[d] * rhs[d]; 316 return res; 317 } 318 }; 319 320 template<class T1, class T2> 321 struct OTDot<TinyVector<T1, 1>, TinyVector<T2, 1>> 322 { 323 typedef typename BinaryReturn<T1, T2, OpMultiply>::Type_t Type_t; 324 inline static Type_t apply(const TinyVector<T1, 1>& lhs, const TinyVector<T2, 1>& rhs) { return lhs[0] * rhs[0]; } 325 }; 326 327 template<class T1, class T2> 328 struct OTDot<TinyVector<T1, 2>, TinyVector<T2, 2>> 329 { 330 typedef typename BinaryReturn<T1, T2, OpMultiply>::Type_t Type_t; 331 inline static Type_t apply(const TinyVector<T1, 2>& lhs, const TinyVector<T2, 2>& rhs) 332 { 333 return lhs[0] * rhs[0] + lhs[1] * rhs[1]; 334 } 335 }; 336 337 template<class T1, class T2> 338 struct OTDot<TinyVector<T1, 3>, TinyVector<T2, 3>> 339 { 340 typedef typename BinaryReturn<T1, T2, OpMultiply>::Type_t Type_t; 341 inline static Type_t apply(const TinyVector<T1, 3>& lhs, const TinyVector<T2, 3>& rhs) 342 { 343 return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2]; 344 } 345 }; 346 347 template<class T1, class T2> 348 struct OTDot<TinyVector<T1, 4>, TinyVector<T2, 4>> 349 { 350 typedef typename BinaryReturn<T1, T2, OpMultiply>::Type_t Type_t; 351 inline static Type_t apply(const TinyVector<T1, 4>& lhs, const TinyVector<T2, 4>& rhs) 352 { 353 return lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2] + lhs[3] * rhs[3]; 354 } 355 }; 356 357 /** specialization for real-complex TinyVector */ 358 template<class T1> 359 struct OTDot<TinyVector<T1, 3>, TinyVector<std::complex<T1>, 3>> 360 { 361 typedef T1 Type_t; 362 inline static Type_t apply(const TinyVector<T1, 3>& lhs, const TinyVector<std::complex<T1>, 3>& rhs) 363 { 364 return lhs[0] * rhs[0].real() + lhs[1] * rhs[1].real() + lhs[2] * rhs[2].real(); 365 } 366 }; 367 368 /** specialization for complex-real TinyVector */ 369 template<class T1, class T2> 370 struct OTDot<TinyVector<std::complex<T1>, 3>, TinyVector<T2, 3>> 371 { 372 typedef T1 Type_t; 373 inline static Type_t apply(const TinyVector<std::complex<T1>, 3>& lhs, const TinyVector<T2, 3>& rhs) 374 { 375 return lhs[0].real() * rhs[0] + lhs[1].real() * rhs[1] + lhs[2].real() * rhs[2]; 376 } 377 }; 378 379 /** specialization for complex-complex TinyVector */ 380 template<class T1, class T2> 381 struct OTDot<TinyVector<std::complex<T1>, 3>, TinyVector<std::complex<T2>, 3>> 382 { 383 typedef typename BinaryReturn<std::complex<T1>, std::complex<T2>, OpMultiply>::Type_t Type_t; 384 inline static Type_t apply(const TinyVector<std::complex<T1>, 3>& lhs, const TinyVector<std::complex<T2>, 3>& rhs) 385 { 386 return std::complex<T1>(lhs[0].real() * rhs[0].real() - lhs[0].imag() * rhs[0].imag() + 387 lhs[1].real() * rhs[1].real() - lhs[1].imag() * rhs[1].imag() + 388 lhs[2].real() * rhs[2].real() - lhs[2].imag() * rhs[2].imag(), 389 lhs[0].real() * rhs[0].imag() + lhs[0].imag() * rhs[0].real() + 390 lhs[1].real() * rhs[1].imag() + lhs[1].imag() * rhs[1].real() + 391 lhs[2].real() * rhs[2].imag() + lhs[2].imag() * rhs[2].real()); 392 } 393 }; 394 395 ////////////////////////////////////////////////////////////////////// 396 // 397 // Definition of the struct OTCross. 398 // 399 ////////////////////////////////////////////////////////////////////// 400 401 template<class T1, class T2> 402 struct OTCross 403 {}; 404 405 ////////////////////////////////////////////////////////////////////// 406 // 407 // Specializations for TinyVector cross TinyVector 408 // 409 ////////////////////////////////////////////////////////////////////// 410 411 template<class T1, class T2, unsigned D> 412 struct OTCross<TinyVector<T1, D>, TinyVector<T2, D>> 413 { 414 typedef typename BinaryReturn<T1, T2, OpMultiply>::Type_t Type_t; 415 inline static TinyVector<Type_t, D> apply(const TinyVector<T1, D>& a, const TinyVector<T2, D>& b) 416 { 417 TinyVector<Type_t, D> bogusCross(-99999); 418 return bogusCross; 419 } 420 }; 421 422 template<class T1, class T2> 423 struct OTCross<TinyVector<T1, 3>, TinyVector<T2, 3>> 424 { 425 typedef typename BinaryReturn<T1, T2, OpMultiply>::Type_t Type_t; 426 inline static TinyVector<Type_t, 3> apply(const TinyVector<T1, 3>& a, const TinyVector<T2, 3>& b) 427 { 428 TinyVector<Type_t, 3> cross; 429 cross[0] = a[1] * b[2] - a[2] * b[1]; 430 cross[1] = a[2] * b[0] - a[0] * b[2]; 431 cross[2] = a[0] * b[1] - a[1] * b[0]; 432 return cross; 433 } 434 }; 435 436 } // namespace qmcplusplus 437 438 /* This has been substituted by OHMMS_META_BINARY_OPERATORS 439 #define OHMMS_TINYVECTOR_BINARY_OPERATORS(FUNC,TAG) \ 440 \ 441 template <class T1, class T2, unsigned D> \ 442 struct BinaryReturn< TinyVector<T1,D>, TinyVector<T2,D>, TAG > \ 443 { \ 444 typedef TinyVector<typename BinaryReturn<T1,T2,TAG>::Type_t, D> Type_t; \ 445 }; \ 446 \ 447 template <class T1, class T2, unsigned D> \ 448 inline \ 449 typename BinaryReturn< TinyVector<T1,D>, TinyVector<T2,D>, TAG >::Type_t \ 450 FUNC( const TinyVector<T1,D>& v1, const TinyVector<T2,D>& v2 ) \ 451 { \ 452 return OTBinary<TinyVector<T1,D>,TinyVector<T2,D>,TAG>::apply(v1,v2,TAG()); \ 453 } \ 454 \ 455 template <class T1, class T2, unsigned D> \ 456 struct BinaryReturn< TinyVector<T1,D>, T2, TAG > \ 457 { \ 458 typedef TinyVector< typename BinaryReturn<T1,T2,TAG>::Type_t, D > Type_t; \ 459 }; \ 460 \ 461 template <class T1, class T2, unsigned D> \ 462 struct BinaryReturn< T1, TinyVector<T2,D>, TAG > \ 463 { \ 464 typedef TinyVector< typename BinaryReturn<T1,T2,TAG>::Type_t, D > Type_t; \ 465 }; \ 466 \ 467 template <class T1, class T2, unsigned D> \ 468 inline \ 469 typename BinaryReturn< TinyVector<T1,D>, T2, TAG >::Type_t \ 470 FUNC( const TinyVector<T1,D>& v1, const T2& x ) \ 471 { \ 472 return OTBinary<TinyVector<T1,D>,T2,TAG>::apply(v1,x,TAG()); \ 473 } \ 474 \ 475 template <class T1, class T2, unsigned D> \ 476 inline \ 477 typename BinaryReturn< T1, TinyVector<T2,D>, TAG >::Type_t \ 478 FUNC( const T1& x, const TinyVector<T2,D>& v2) \ 479 { \ 480 return OTBinary<T1,TinyVector<T2,D>,TAG>::apply(x,v2,TAG()); \ 481 } \ 482 483 #define OHMMS_TINYVECTOR_ACCUM_OPERATORS(FUNC,TAG) \ 484 \ 485 template <class T1, class T2, unsigned D> \ 486 inline TinyVector<T1,D>& \ 487 FUNC( TinyVector<T1,D>& v1, const TinyVector<T2,D>& v2 ) \ 488 { \ 489 OTAssign<TinyVector<T1,D>,TinyVector<T2,D>,TAG>::apply(v1,v2,TAG()); \ 490 return v1; \ 491 } \ 492 \ 493 template <class T1, class T2, unsigned D> \ 494 inline TinyVector<T1,D>& \ 495 FUNC( TinyVector<T1,D>& v1, const T2& v2 ) \ 496 { \ 497 OTAssign<TinyVector<T1,D>,T2,TAG>::apply(v1,v2,TAG()); \ 498 return v1; \ 499 } \ 500 501 */ 502 #endif // OHMMS_TINYVECTOR_OPERATORS_H 503