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