OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
IpplTypeComputations.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  *
7  * Visit http://people.web.psi.ch/adelmann/ for more details
8  *
9  ***************************************************************************/
10 
11 
13 //
14 // FILE NAME
15 // IpplTypeComputations.h
16 //
17 // CREATED
18 // July 11, 1997
19 //
20 // DESCRIPTION
21 // PETE: Portable Expression Template Engine.
22 //
23 // This header file contains IPPL-specific type computations.
24 //
26 
27 #ifndef IPPL_TYPE_COMPUTATIONS_H
28 #define IPPL_TYPE_COMPUTATIONS_H
29 
30 
31 // include files
32 #include "PETE/TypeComputations.h"
33 #include "AppTypes/dcomplex.h"
34 
35 
36 // forward declarations
37 template<class T, unsigned D> class Vektor;
38 template<class T, unsigned D> class Tenzor;
39 template<class T, unsigned D> class AntiSymTenzor;
40 template<class T, unsigned D> class SymTenzor;
41 class RNGBitReverse;
42 template <class T> class RNGLattice;
43 class RNGSimple;
44 class RNGRand;
45 class RNGXDiv;
46 class RNGXCI;
47 
48 
49 // definition of global sign function
50 template<class T>
51 inline int sign(T a) { return ((a > 0) ? 1 : (a == 0 ? 0 : -1)); }
52 
53 
55 //
56 // PETE_Type2Index FOR USER TYPES
57 //
59 
60 // Complex numbers.
61 
62 template<> struct PETE_Type2Index<dcomplex> {
63  enum { val = 8 };
64 };
65 
66 #ifdef IPPL_USE_SINGLE_PRECISION
67  #define CTYPE float
68 #else
69  #define CTYPE double
70 #endif
71 
72 // Return types for scalar ops with RNGs.
73 
74 #define _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OP) \
75 template <> \
76 struct PETEBinaryReturn<GEN,SCA,OP> { \
77  typedef PETEBinaryReturn<CTYPE,SCA,OP>::type type; \
78 }; \
79 template <> \
80 struct PETEBinaryReturn<SCA,GEN,OP> { \
81  typedef PETEBinaryReturn<SCA,CTYPE,OP>::type type; \
82 };
83 
84 #define _SCALAR_RNG_RETURNS_(GEN,SCA) \
85 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpAdd) \
86 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpSubtract) \
87 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpMultipply) \
88 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpDivide)
89 
90 #define _PETE_RNG_RETURNS_(GEN) \
91  \
92 template <> struct PETE_Type2Index< GEN > { \
93  enum { val = PETE_Type2Index<CTYPE>::val }; \
94 }; \
95  \
96 _SCALAR_RNG_RETURNS_(GEN,short) \
97 _SCALAR_RNG_RETURNS_(GEN,int) \
98 _SCALAR_RNG_RETURNS_(GEN,long) \
99 _SCALAR_RNG_RETURNS_(GEN,float) \
100 _SCALAR_RNG_RETURNS_(GEN,double) \
101 _SCALAR_RNG_RETURNS_(GEN,dcomplex)
102 
110 
111 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
112 
113 // Life is way easier with this feature.
114 
115 template<class T, unsigned Dim>
116 struct PETE_Type2Index< Vektor<T, Dim> > {
117  enum { val = 20 + 10 * Dim + PETE_Type2Index<T>::val };
118 };
119 
120 template<class T, unsigned Dim>
121 struct PETE_Type2Index< SymTenzor<T, Dim> > {
122  enum { val = 120 + 10 * Dim + PETE_Type2Index<T>::val };
123 };
124 
125 template<class T, unsigned Dim>
126 struct PETE_Type2Index< Tenzor<T, Dim> > {
127  enum { val = 220 + 10 * Dim + PETE_Type2Index<T>::val };
128 };
129 
130 template<class T, unsigned Dim>
131 struct PETE_Type2Index< AntiSymTenzor<T, Dim> > {
132  enum { val = 320 + 10 * Dim + PETE_Type2Index<T>::val };
133 };
134 
135 #else
136 
137 // Without partial specialization, we must give all the cases. Yuuuck!
138 
139 // Vectors of size 1.
140 
141 template<> struct PETE_Type2Index< Vektor<short, 1U> > {
142  enum { val = 30 };
143 };
144 
145 template<> struct PETE_Type2Index< Vektor<int, 1U> > {
146  enum { val = 31 };
147 };
148 
149 template<> struct PETE_Type2Index< Vektor<long, 1U> > {
150  enum { val = 32 };
151 };
152 
153 template<> struct PETE_Type2Index< Vektor<float, 1U> > {
154  enum { val = 33 };
155 };
156 
157 template<> struct PETE_Type2Index< Vektor<double, 1U> > {
158  enum { val = 34 };
159 };
160 
161 template<> struct PETE_Type2Index< Vektor<dcomplex, 1U> > {
162  enum { val = 35 };
163 };
164 
165 // Vectors of size 2.
166 
167 template<> struct PETE_Type2Index< Vektor<short, 2U> > {
168  enum { val = 40 };
169 };
170 
171 template<> struct PETE_Type2Index< Vektor<int, 2U> > {
172  enum { val = 41 };
173 };
174 
175 template<> struct PETE_Type2Index< Vektor<long, 2U> > {
176  enum { val = 42 };
177 };
178 
179 template<> struct PETE_Type2Index< Vektor<float, 2U> > {
180  enum { val = 43 };
181 };
182 
183 template<> struct PETE_Type2Index< Vektor<double, 2U> > {
184  enum { val = 44 };
185 };
186 
187 template<> struct PETE_Type2Index< Vektor<dcomplex, 2U> > {
188  enum { val = 45 };
189 };
190 
191 // Vectors of size 3.
192 
193 template<> struct PETE_Type2Index< Vektor<short, 3U> > {
194  enum { val = 50 };
195 };
196 
197 template<> struct PETE_Type2Index< Vektor<int, 3U> > {
198  enum { val = 51 };
199 };
200 
201 template<> struct PETE_Type2Index< Vektor<long, 3U> > {
202  enum { val = 52 };
203 };
204 
205 template<> struct PETE_Type2Index< Vektor<float, 3U> > {
206  enum { val = 53 };
207 };
208 
209 template<> struct PETE_Type2Index< Vektor<double, 3U> > {
210  enum { val = 54 };
211 };
212 
213 template<> struct PETE_Type2Index< Vektor<dcomplex, 3U> > {
214  enum { val = 55 };
215 };
216 
217 // SymTensors of size 1.
218 
219 template<> struct PETE_Type2Index< SymTenzor<short, 1U> > {
220  enum { val = 130 };
221 };
222 
223 template<> struct PETE_Type2Index< SymTenzor<int, 1U> > {
224  enum { val = 131 };
225 };
226 
227 template<> struct PETE_Type2Index< SymTenzor<long, 1U> > {
228  enum { val = 132 };
229 };
230 
231 template<> struct PETE_Type2Index< SymTenzor<float, 1U> > {
232  enum { val = 133 };
233 };
234 
235 template<> struct PETE_Type2Index< SymTenzor<double, 1U> > {
236  enum { val = 134 };
237 };
238 
239 template<> struct PETE_Type2Index< SymTenzor<dcomplex, 1U> > {
240  enum { val = 135 };
241 };
242 
243 // SymTensors of size 2.
244 
245 template<> struct PETE_Type2Index< SymTenzor<short, 2U> > {
246  enum { val = 140 };
247 };
248 
249 template<> struct PETE_Type2Index< SymTenzor<int, 2U> > {
250  enum { val = 141 };
251 };
252 
253 template<> struct PETE_Type2Index< SymTenzor<long, 2U> > {
254  enum { val = 142 };
255 };
256 
257 template<> struct PETE_Type2Index< SymTenzor<float, 2U> > {
258  enum { val = 143 };
259 };
260 
261 template<> struct PETE_Type2Index< SymTenzor<double, 2U> > {
262  enum { val = 144 };
263 };
264 
265 template<> struct PETE_Type2Index< SymTenzor<dcomplex, 2U> > {
266  enum { val = 145 };
267 };
268 
269 // SymTensors of size 3.
270 
271 template<> struct PETE_Type2Index< SymTenzor<short, 3U> > {
272  enum { val = 150 };
273 };
274 
275 template<> struct PETE_Type2Index< SymTenzor<int, 3U> > {
276  enum { val = 151 };
277 };
278 
279 template<> struct PETE_Type2Index< SymTenzor<long, 3U> > {
280  enum { val = 152 };
281 };
282 
283 template<> struct PETE_Type2Index< SymTenzor<float, 3U> > {
284  enum { val = 153 };
285 };
286 
287 template<> struct PETE_Type2Index< SymTenzor<double, 3U> > {
288  enum { val = 154 };
289 };
290 
291 template<> struct PETE_Type2Index< SymTenzor<dcomplex, 3U> > {
292  enum { val = 155 };
293 };
294 
295 // Tensors of size 1.
296 
297 template<> struct PETE_Type2Index< Tenzor<short, 1U> > {
298  enum { val = 230 };
299 };
300 
301 template<> struct PETE_Type2Index< Tenzor<int, 1U> > {
302  enum { val = 231 };
303 };
304 
305 template<> struct PETE_Type2Index< Tenzor<long, 1U> > {
306  enum { val = 232 };
307 };
308 
309 template<> struct PETE_Type2Index< Tenzor<float, 1U> > {
310  enum { val = 233 };
311 };
312 
313 template<> struct PETE_Type2Index< Tenzor<double, 1U> > {
314  enum { val = 234 };
315 };
316 
317 template<> struct PETE_Type2Index< Tenzor<dcomplex, 1U> > {
318  enum { val = 235 };
319 };
320 
321 // Tensors of size 2.
322 
323 template<> struct PETE_Type2Index< Tenzor<short, 2U> > {
324  enum { val = 240 };
325 };
326 
327 template<> struct PETE_Type2Index< Tenzor<int, 2U> > {
328  enum { val = 241 };
329 };
330 
331 template<> struct PETE_Type2Index< Tenzor<long, 2U> > {
332  enum { val = 242 };
333 };
334 
335 template<> struct PETE_Type2Index< Tenzor<float, 2U> > {
336  enum { val = 243 };
337 };
338 
339 template<> struct PETE_Type2Index< Tenzor<double, 2U> > {
340  enum { val = 244 };
341 };
342 
343 template<> struct PETE_Type2Index< Tenzor<dcomplex, 2U> > {
344  enum { val = 245 };
345 };
346 
347 // Tensors of size 3.
348 
349 template<> struct PETE_Type2Index< Tenzor<short, 3U> > {
350  enum { val = 250 };
351 };
352 
353 template<> struct PETE_Type2Index< Tenzor<int, 3U> > {
354  enum { val = 251 };
355 };
356 
357 template<> struct PETE_Type2Index< Tenzor<long, 3U> > {
358  enum { val = 252 };
359 };
360 
361 template<> struct PETE_Type2Index< Tenzor<float, 3U> > {
362  enum { val = 253 };
363 };
364 
365 template<> struct PETE_Type2Index< Tenzor<double, 3U> > {
366  enum { val = 254 };
367 };
368 
369 template<> struct PETE_Type2Index< Tenzor<dcomplex, 3U> > {
370  enum { val = 255 };
371 };
372 
373 #endif
374 
375 
377 //
378 // PETE_Index2Type FOR USER TYPES
379 //
381 
382 #if !defined(IPPL_USE_PARTIAL_SPECIALIZATION)
383 
384 // Complex numbers.
385 
386 template<> struct PETE_Index2Type<8> {
387  typedef dcomplex type;
388 };
389 
390 // Vectors of length 1.
391 
392 template<> struct PETE_Index2Type<30> {
394 };
395 
396 template<> struct PETE_Index2Type<31> {
398 };
399 
400 template<> struct PETE_Index2Type<32> {
402 };
403 
404 template<> struct PETE_Index2Type<33> {
406 };
407 
408 template<> struct PETE_Index2Type<34> {
410 };
411 
412 template<> struct PETE_Index2Type<35> {
414 };
415 
416 // Vectors of length 2.
417 
418 template<> struct PETE_Index2Type<40> {
420 };
421 
422 template<> struct PETE_Index2Type<41> {
424 };
425 
426 template<> struct PETE_Index2Type<42> {
428 };
429 
430 template<> struct PETE_Index2Type<43> {
432 };
433 
434 template<> struct PETE_Index2Type<44> {
436 };
437 
438 template<> struct PETE_Index2Type<45> {
440 };
441 
442 // Vectors of length 3.
443 
444 template<> struct PETE_Index2Type<50> {
446 };
447 
448 template<> struct PETE_Index2Type<51> {
450 };
451 
452 template<> struct PETE_Index2Type<52> {
454 };
455 
456 template<> struct PETE_Index2Type<53> {
458 };
459 
460 template<> struct PETE_Index2Type<54> {
462 };
463 
464 template<> struct PETE_Index2Type<55> {
466 };
467 
468 // SymTensors of length 1.
469 
470 template<> struct PETE_Index2Type<130> {
472 };
473 
474 template<> struct PETE_Index2Type<131> {
476 };
477 
478 template<> struct PETE_Index2Type<132> {
480 };
481 
482 template<> struct PETE_Index2Type<133> {
484 };
485 
486 template<> struct PETE_Index2Type<134> {
488 };
489 
490 template<> struct PETE_Index2Type<135> {
492 };
493 
494 // SymTensors of length 2.
495 
496 template<> struct PETE_Index2Type<140> {
498 };
499 
500 template<> struct PETE_Index2Type<141> {
502 };
503 
504 template<> struct PETE_Index2Type<142> {
506 };
507 
508 template<> struct PETE_Index2Type<143> {
510 };
511 
512 template<> struct PETE_Index2Type<144> {
514 };
515 
516 template<> struct PETE_Index2Type<145> {
518 };
519 
520 // SymTensors of length 3.
521 
522 template<> struct PETE_Index2Type<150> {
524 };
525 
526 template<> struct PETE_Index2Type<151> {
528 };
529 
530 template<> struct PETE_Index2Type<152> {
532 };
533 
534 template<> struct PETE_Index2Type<153> {
536 };
537 
538 template<> struct PETE_Index2Type<154> {
540 };
541 
542 template<> struct PETE_Index2Type<155> {
544 };
545 
546 // Tensors of length 1.
547 
548 template<> struct PETE_Index2Type<230> {
550 };
551 
552 template<> struct PETE_Index2Type<231> {
554 };
555 
556 template<> struct PETE_Index2Type<232> {
558 };
559 
560 template<> struct PETE_Index2Type<233> {
562 };
563 
564 template<> struct PETE_Index2Type<234> {
566 };
567 
568 template<> struct PETE_Index2Type<235> {
570 };
571 
572 // Tensors of length 2.
573 
574 template<> struct PETE_Index2Type<240> {
576 };
577 
578 template<> struct PETE_Index2Type<241> {
580 };
581 
582 template<> struct PETE_Index2Type<242> {
584 };
585 
586 template<> struct PETE_Index2Type<243> {
588 };
589 
590 template<> struct PETE_Index2Type<244> {
592 };
593 
594 template<> struct PETE_Index2Type<245> {
596 };
597 
598 // Tensors of length 3.
599 
600 template<> struct PETE_Index2Type<250> {
602 };
603 
604 template<> struct PETE_Index2Type<251> {
606 };
607 
608 template<> struct PETE_Index2Type<252> {
610 };
611 
612 template<> struct PETE_Index2Type<253> {
614 };
615 
616 template<> struct PETE_Index2Type<254> {
618 };
619 
620 template<> struct PETE_Index2Type<255> {
622 };
623 
624 #endif
625 
626 
628 //
629 // SPECIAL CASES FOR UNARY FUNCTIONS
630 //
632 
633 // Abs function: special return for complex numbers.
634 
635 struct FnAbs {
636 #ifdef IPPL_PURIFY
637  FnAbs() {}
638  FnAbs(const FnAbs &) {}
639  FnAbs& operator=(const FnAbs &) { return *this; }
640 #endif
642 };
643 
644 template<> struct PETEUnaryReturn<dcomplex, FnAbs> {
645  typedef double type;
646 };
647 
648 // The conj, norm, arg, real, and imag functions for complex numbers.
649 
650 struct FnConj {
651 #ifdef IPPL_PURIFY
652  FnConj() {}
653  FnConj(const FnConj &) {}
654  FnConj& operator=(const FnConj &) { return *this; }
655 #endif
657 };
658 
659 struct FnNorm {
660 #ifdef IPPL_PURIFY
661  FnNorm() {}
662  FnNorm(const FnNorm &) {}
663  FnNorm& operator=(const FnNorm &) { return *this; }
664 #endif
665  typedef double type;
667 };
668 
669 template<> struct PETEUnaryReturn<dcomplex, FnNorm> {
670  typedef double type;
671 };
672 
673 struct FnArg {
674 #ifdef IPPL_PURIFY
675  FnArg() {}
676  FnArg(const FnArg &) {}
677  FnArg& operator=(const FnArg &) { return *this; }
678 #endif
679  typedef double type;
681 };
682 
683 template<> struct PETEUnaryReturn<dcomplex, FnArg> {
684  typedef double type;
685 };
686 
687 struct FnReal {
688 #ifdef IPPL_PURIFY
689  FnReal() {}
690  FnReal(const FnReal &) {}
691  FnReal& operator=(const FnReal &) { return *this; }
692 #endif
693  typedef double type;
695 };
696 
697 template<> struct PETEUnaryReturn<dcomplex, FnReal> {
698  typedef double type;
699 };
700 
701 struct FnImag {
702 #ifdef IPPL_PURIFY
703  FnImag() {}
704  FnImag(const FnImag &) {}
705  FnImag& operator=(const FnImag &) { return *this; }
706 #endif
707  typedef double type;
709 };
710 
711 template<> struct PETEUnaryReturn<dcomplex, FnImag> {
712  typedef double type;
713 };
714 
715 // The sign function.
716 
717 struct FnSign {
718 #ifdef IPPL_PURIFY
719  FnSign() {}
720  FnSign(const FnSign &) {}
721  FnSign& operator=(const FnSign &) { return *this; }
722 #endif
723  typedef int type;
725 };
726 
727 template<class TP>
728 struct OpParens
729 {
731  TP Arg;
732  OpParens() { Arg = TP(); }
733  OpParens(const TP& a) : Arg(a) {}
734 };
735 
736 // Tensor functions: trace, det (determinant), and transpose
737 
738 struct FnTrace {
739 #ifdef IPPL_PURIFY
740  FnTrace() {}
741  FnTrace(const FnTrace &) {}
742  FnTrace& operator=(const FnTrace &) { return *this; }
743 #endif
745 };
746 
747 struct FnDet {
748 #ifdef IPPL_PURIFY
749  FnDet() {}
750  FnDet(const FnDet &) {}
751  FnDet& operator=(const FnDet &) { return *this; }
752 #endif
754 };
755 
756 struct FnTranspose {
757 #ifdef IPPL_PURIFY
758  FnTranspose() {}
759  FnTranspose(const FnTranspose &) {}
760  FnTranspose& operator=(const FnTranspose &) { return *this; }
761 #endif
763 };
764 
765 struct FnCofactors {
766 #ifdef IPPL_PURIFY
767  FnCofactors() {}
768  FnCofactors(const FnCofactors &) {}
769  FnCofactors& operator=(const FnCofactors &) { return *this; }
770 #endif
772 };
773 
774 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
775 
776 // Life is pretty simple if we have partial specialization.
777 
778 template<class T, unsigned Dim>
779 struct PETEUnaryReturn<Tenzor<T,Dim>, FnTrace> {
780  typedef T type;
781 };
782 
783 template<class T, unsigned Dim>
785  typedef T type;
786 };
787 
788 template<class T, unsigned Dim>
790  typedef T type;
791 };
792 
793 template<class T, unsigned Dim>
794 struct PETEUnaryReturn<Tenzor<T,Dim>, FnDet> {
795  typedef T type;
796 };
797 
798 template<class T, unsigned Dim>
799 struct PETEUnaryReturn<SymTenzor<T,Dim>, FnDet> {
800  typedef T type;
801 };
802 
803 template<class T, unsigned Dim>
805  typedef T type;
806 };
807 
808 template<class T, unsigned Dim>
810  typedef Tenzor<T,Dim> type;
811 };
812 
813 template<class T, unsigned Dim>
815  typedef SymTenzor<T,Dim> type;
816 };
817 
818 template<class T, unsigned Dim>
820  typedef AntiSymTenzor<T,Dim> type;
821 };
822 
823 template<class T, unsigned Dim>
825  typedef Tenzor<T,Dim> type;
826 };
827 
828 template<class T, unsigned Dim>
830  typedef SymTenzor<T,Dim> type;
831 };
832 
833 template<class T, unsigned Dim>
835  typedef AntiSymTenzor<T,Dim> type;
836 };
837 
838 #else
839 
840 // Life is pitiful and barely worth living without partial specialization.
841 // Sigh, I guess we'll limp along...
842 
843 #define _UNARY_TENSOR_RETURNS_(T, D)
844 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnTrace>
845 { typedef T type; };
846 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnTrace>
847 { typedef T type; };
848 template<> struct PETEUnaryReturn<AntiSymTenzor<T,D>, FnTrace>
849 { typedef T type; };
850 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnDet>
851 { typedef T type; };
852 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnDet>
853 { typedef T type; };
854 template<> struct PETEUnaryReturn<AntiSymTenzor<T,D>, FnDet>
855 { typedef T type; };
856 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnTranspose>
857 { typedef Tenzor<T,D> type; };
858 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnTranspose>
859 { typedef SymTenzor<T,D> type; };
862 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnCofactors>
863 { typedef Tenzor<T,D> type; };
864 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnCofactors>
865 { typedef Tenzor<T,D> type; };
867 { typedef SymTenzor<T,D> type; };
868 
869 _UNARY_TENSOR_RETURNS_(short,1U)
871 _UNARY_TENSOR_RETURNS_(long,1U)
872 _UNARY_TENSOR_RETURNS_(float,1U)
873 _UNARY_TENSOR_RETURNS_(double,1U)
875 
876 _UNARY_TENSOR_RETURNS_(short,2U)
878 _UNARY_TENSOR_RETURNS_(long,2U)
879 _UNARY_TENSOR_RETURNS_(float,2U)
880 _UNARY_TENSOR_RETURNS_(double,2U)
881 _UNARY_TENSOR_RETURNS_(dcomplex,2U)
882 
883 _UNARY_TENSOR_RETURNS_(short,3U)
885 _UNARY_TENSOR_RETURNS_(long,3U)
886 _UNARY_TENSOR_RETURNS_(float,3U)
887 _UNARY_TENSOR_RETURNS_(double,3U)
888 _UNARY_TENSOR_RETURNS_(dcomplex,3U)
889 
890 #undef _UNARY_TENSOR_RETURNS_
891 
892 #endif
893 
894 
896 //
897 // SPECIAL CASES FOR BINARY FUNCTIONS
898 //
900 
901 // Min and Max functions.
902 
903 struct FnMin {
904 #ifdef IPPL_PURIFY
905  FnMin() {}
906  FnMin(const FnMin &) {}
907  FnMin& operator=(const FnMin &) { return *this; }
908 #endif
910 };
911 
912 struct FnMax {
913 #ifdef IPPL_PURIFY
914  FnMax() {}
915  FnMax(const FnMax &) {}
916  FnMax& operator=(const FnMax &) { return *this; }
917 #endif
919 };
920 
921 // Dot, dot-dot, and outerProduct functions.
922 
923 struct FnDot {
924 #ifdef IPPL_PURIFY
925  FnDot() {}
926  FnDot(const FnDot &) {}
927  FnDot& operator=(const FnDot &) { return *this; }
928 #endif
930 };
931 
932 struct FnDotDot {
933 #ifdef IPPL_PURIFY
934  FnDotDot() {}
935  FnDotDot(const FnDotDot &) {}
936  FnDotDot& operator=(const FnDotDot &) { return *this; }
937 #endif
939 };
940 
942 #ifdef IPPL_PURIFY
943  FnOuterProduct() {}
944  FnOuterProduct(const FnOuterProduct &) {}
945  FnOuterProduct& operator=(const FnOuterProduct &) { return *this; }
946 #endif
948 };
949 
950 // Cross-product:
951 
952 struct FnCross {
953 #ifdef IPPL_PURIFY
954  FnCross() {}
955  FnCross(const FnCross &) {}
956  FnCross& operator=(const FnCross &) { return *this; }
957 #endif
959 };
960 
961 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
962 
963 // Life is pretty simple if we have partial specialization.
964 
965 
966 // Involving Vektors:
967 
968 template<class T1, class T2, unsigned Dim>
969 struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>, FnCross> {
971 };
972 
973 template<class T1, class T2, unsigned Dim>
976 };
977 
978 template<class T1, class T2, unsigned Dim>
979 struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
981 };
982 
983 // Involving Tenzors, but no combination with SymTenzors or AntiSymTenzors:
984 
985 template<class T1, class T2, unsigned Dim>
986 struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>,FnDot> {
988 };
989 
990 template<class T1, class T2, unsigned Dim>
991 struct PETEBinaryReturn<Vektor<T1,Dim>,Tenzor<T2,Dim>, FnDot> {
993 };
994 
995 template<class T1, class T2, unsigned Dim>
996 struct PETEBinaryReturn<Tenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
998 };
999 
1000 template<class T1, class T2, unsigned Dim>
1001 struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>,FnDotDot> {
1003 };
1004 
1005 // Involving SymTenzors, possibly combined with Tenzors:
1006 
1007 template<class T1, class T2, unsigned Dim>
1008 struct PETEBinaryReturn<SymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> {
1010  type;
1011 };
1012 
1013 template<class T1, class T2, unsigned Dim>
1016 };
1017 
1018 template<class T1, class T2, unsigned Dim>
1019 struct PETEBinaryReturn<Vektor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> {
1021 };
1022 
1023 template<class T1, class T2, unsigned Dim>
1024 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
1026 };
1027 
1028 template<class T1, class T2, unsigned Dim>
1029 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpAdd> {
1031 };
1032 
1033 template<class T1, class T2, unsigned Dim>
1036 };
1037 
1038 template<class T1, class T2, unsigned Dim>
1041 };
1042 
1043 template<class T1, class T2, unsigned Dim>
1044 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> {
1046 };
1047 
1048 template<class T1, class T2, unsigned Dim>
1049 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot> {
1051 };
1052 
1053 template<class T1, class T2, unsigned Dim>
1054 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpAdd> {
1056 };
1057 
1058 template<class T1, class T2, unsigned Dim>
1061 };
1062 
1063 template<class T1, class T2, unsigned Dim>
1064 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDot> {
1066 };
1067 
1068 template<class T1, class T2, unsigned Dim>
1069 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDotDot> {
1071 };
1072 
1073 // Involving AntiSymTenzors, possibly combined with Tenzors or SymTenzors:
1074 
1075 template<class T1, class T2, unsigned Dim>
1078  type;
1079 };
1080 
1081 template<class T1, class T2, unsigned Dim>
1083 {
1085 };
1086 
1087 template<class T1, class T2, unsigned Dim>
1088 struct PETEBinaryReturn<Vektor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot> {
1090 };
1091 
1092 template<class T1, class T2, unsigned Dim>
1093 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
1095 };
1096 
1097 template<class T1, class T2, unsigned Dim>
1100 };
1101 
1102 template<class T1, class T2, unsigned Dim>
1105 };
1106 
1107 template<class T1, class T2, unsigned Dim>
1110 };
1111 
1112 template<class T1, class T2, unsigned Dim>
1113 struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot> {
1115 };
1116 
1117 template<class T1, class T2, unsigned Dim>
1120 };
1121 
1122 template<class T1, class T2, unsigned Dim>
1125 };
1126 
1127 template<class T1, class T2, unsigned Dim>
1130 };
1131 
1132 template<class T1, class T2, unsigned Dim>
1135 };
1136 
1137 template<class T1, class T2, unsigned Dim>
1140 };
1141 
1142 template<class T1, class T2, unsigned Dim>
1145 };
1146 
1147 template<class T1, class T2, unsigned Dim>
1150 };
1151 
1152 template<class T1, class T2, unsigned Dim>
1155 };
1156 
1157 template<class T1, class T2, unsigned Dim>
1160 };
1161 
1162 template<class T1, class T2, unsigned Dim>
1165 };
1166 
1167 template<class T1, class T2, unsigned Dim>
1170 };
1171 
1172 template<class T1, class T2, unsigned Dim>
1175 };
1176 
1177 template<class T1, class T2, unsigned Dim>
1180 };
1181 
1182 template<class T1, class T2, unsigned Dim>
1185 };
1186 
1187 // Need to specify scalar operations directly.
1188 
1189 #define _SCALAR_VST_RETURNS_(Sca) \
1190 template<class T1, unsigned Dim> \
1191 struct PETEBinaryReturn<Vektor<T1,Dim>,Sca,OpMultipply> { \
1192  typedef Vektor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim> \
1193  type; \
1194 }; \
1195 template<class T2, unsigned Dim> \
1196 struct PETEBinaryReturn<Sca,Vektor<T2,Dim>,OpMultipply> { \
1197  typedef Vektor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim> \
1198  type; \
1199 }; \
1200 template<class T1, unsigned Dim> \
1201 struct PETEBinaryReturn<Vektor<T1,Dim>,Sca,OpDivide> { \
1202  typedef Vektor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim> \
1203  type; \
1204 }; \
1205 template<class T1, unsigned Dim> \
1206 struct PETEBinaryReturn<Tenzor<T1,Dim>,Sca,OpMultipply> { \
1207  typedef Tenzor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim> \
1208  type; \
1209 }; \
1210 template<class T2, unsigned Dim> \
1211 struct PETEBinaryReturn<Sca,Tenzor<T2,Dim>,OpMultipply> { \
1212  typedef Tenzor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim> \
1213  type; \
1214 }; \
1215 template<class T1, unsigned Dim> \
1216 struct PETEBinaryReturn<Tenzor<T1,Dim>,Sca,OpDivide> { \
1217  typedef Tenzor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim> \
1218  type; \
1219 }; \
1220 template<class T1, unsigned Dim> \
1221 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Sca,OpMultipply> { \
1222  typedef SymTenzor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim> \
1223  type; \
1224 }; \
1225 template<class T2, unsigned Dim> \
1226 struct PETEBinaryReturn<Sca,SymTenzor<T2,Dim>,OpMultipply> { \
1227  typedef SymTenzor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim> \
1228  type; \
1229 }; \
1230 template<class T1, unsigned Dim> \
1231 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Sca,OpDivide> { \
1232  typedef SymTenzor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim> \
1233  type; \
1234 }; \
1235 template<class T1, unsigned Dim> \
1236 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Sca,OpMultipply> { \
1237  typedef \
1238  AntiSymTenzor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim> \
1239  type; \
1240 }; \
1241 template<class T2, unsigned Dim> \
1242 struct PETEBinaryReturn<Sca,AntiSymTenzor<T2,Dim>,OpMultipply> { \
1243  typedef \
1244  AntiSymTenzor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim> \
1245  type; \
1246 }; \
1247 template<class T1, unsigned Dim> \
1248 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Sca,OpDivide> { \
1249  typedef \
1250  AntiSymTenzor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim> \
1251  type; \
1252 };
1253 
1254 _SCALAR_VST_RETURNS_(short)
1255 _SCALAR_VST_RETURNS_(int)
1256 _SCALAR_VST_RETURNS_(long)
1257 _SCALAR_VST_RETURNS_(float)
1258 _SCALAR_VST_RETURNS_(double)
1259 _SCALAR_VST_RETURNS_(dcomplex)
1260 
1261 #undef _SCALAR_VST_RETURNS_
1262 
1263 #else
1264 
1265 // Without partial specialization, we must list all the possibilities.
1266 // Life is too short to type all this stuff out, so we use macros.
1267 
1268 #define _VEKTOR_RETURNS_(T1,T2,Dim) \
1269 template<> struct \
1270  PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>, FnOuterProduct> \
1271  { typedef Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> \
1272  type; }; \
1273 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>,FnDot> \
1274  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1275 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,T2,OpMultipply> \
1276  { typedef Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> \
1277  type; }; \
1278 template<> struct PETEBinaryReturn<T2,Vektor<T1,Dim>,OpMultipply> \
1279  { typedef Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> \
1280  type; }; \
1281 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,T2,OpDivide> \
1282  { typedef Vektor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim> \
1283  type; }; \
1284 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>,FnCross> \
1285  { typedef Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };
1286 
1287 _VEKTOR_RETURNS_(short,short,1U)
1288 _VEKTOR_RETURNS_(int,int,1U)
1289 _VEKTOR_RETURNS_(long,long,1U)
1290 _VEKTOR_RETURNS_(float,float,1U)
1291 _VEKTOR_RETURNS_(double,double,1U)
1292 _VEKTOR_RETURNS_(dcomplex,dcomplex,1U)
1293 _VEKTOR_RETURNS_(int,short,1U)
1294 _VEKTOR_RETURNS_(long,short,1U)
1295 _VEKTOR_RETURNS_(long,int,1U)
1296 _VEKTOR_RETURNS_(float,short,1U)
1297 _VEKTOR_RETURNS_(float,int,1U)
1298 _VEKTOR_RETURNS_(float,long,1U)
1299 _VEKTOR_RETURNS_(double,short,1U)
1300 _VEKTOR_RETURNS_(double,int,1U)
1301 _VEKTOR_RETURNS_(double,long,1U)
1302 _VEKTOR_RETURNS_(double,float,1U)
1303 _VEKTOR_RETURNS_(dcomplex,short,1U)
1304 _VEKTOR_RETURNS_(dcomplex,int,1U)
1305 _VEKTOR_RETURNS_(dcomplex,long,1U)
1306 _VEKTOR_RETURNS_(dcomplex,float,1U)
1307 _VEKTOR_RETURNS_(dcomplex,double,1U)
1308 
1309 _VEKTOR_RETURNS_(short,short,2U)
1310 _VEKTOR_RETURNS_(int,int,2U)
1311 _VEKTOR_RETURNS_(long,long,2U)
1312 _VEKTOR_RETURNS_(float,float,2U)
1313 _VEKTOR_RETURNS_(double,double,2U)
1314 _VEKTOR_RETURNS_(dcomplex,dcomplex,2U)
1315 _VEKTOR_RETURNS_(int,short,2U)
1316 _VEKTOR_RETURNS_(long,short,2U)
1317 _VEKTOR_RETURNS_(long,int,2U)
1318 _VEKTOR_RETURNS_(float,short,2U)
1319 _VEKTOR_RETURNS_(float,int,2U)
1320 _VEKTOR_RETURNS_(float,long,2U)
1321 _VEKTOR_RETURNS_(double,short,2U)
1322 _VEKTOR_RETURNS_(double,int,2U)
1323 _VEKTOR_RETURNS_(double,long,2U)
1324 _VEKTOR_RETURNS_(double,float,2U)
1325 _VEKTOR_RETURNS_(dcomplex,short,2U)
1326 _VEKTOR_RETURNS_(dcomplex,int,2U)
1327 _VEKTOR_RETURNS_(dcomplex,long,2U)
1328 _VEKTOR_RETURNS_(dcomplex,float,2U)
1329 _VEKTOR_RETURNS_(dcomplex,double,2U)
1330 
1331 _VEKTOR_RETURNS_(short,short,3U)
1332 _VEKTOR_RETURNS_(int,int,3U)
1333 _VEKTOR_RETURNS_(long,long,3U)
1334 _VEKTOR_RETURNS_(float,float,3U)
1335 _VEKTOR_RETURNS_(double,double,3U)
1336 _VEKTOR_RETURNS_(dcomplex,dcomplex,3U)
1337 _VEKTOR_RETURNS_(int,short,3U)
1338 _VEKTOR_RETURNS_(long,short,3U)
1339 _VEKTOR_RETURNS_(long,int,3U)
1340 _VEKTOR_RETURNS_(float,short,3U)
1341 _VEKTOR_RETURNS_(float,int,3U)
1342 _VEKTOR_RETURNS_(float,long,3U)
1343 _VEKTOR_RETURNS_(double,short,3U)
1344 _VEKTOR_RETURNS_(double,int,3U)
1345 _VEKTOR_RETURNS_(double,long,3U)
1346 _VEKTOR_RETURNS_(double,float,3U)
1347 _VEKTOR_RETURNS_(dcomplex,short,3U)
1348 _VEKTOR_RETURNS_(dcomplex,int,3U)
1349 _VEKTOR_RETURNS_(dcomplex,long,3U)
1350 _VEKTOR_RETURNS_(dcomplex,float,3U)
1351 _VEKTOR_RETURNS_(dcomplex,double,3U)
1352 
1353 #undef _VEKTOR_RETURNS_
1354 
1355 #define _TENZOR_RETURNS_(T1,T2,Dim) \
1356 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>, FnDot> \
1357  { typedef \
1358  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1359 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>, FnDotDot> \
1360  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1361 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,Tenzor<T2,Dim>, FnDot> \
1362  { typedef \
1363  Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1364 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> \
1365  { typedef \
1366  Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1367 template<> struct PETEBinaryReturn<T1,Tenzor<T2,Dim>,OpMultipply> \
1368  { typedef \
1369  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1370 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,T2,OpMultipply> \
1371  { typedef \
1372  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1373 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,T2,OpDivide> \
1374  { typedef \
1375  Tenzor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim> type; };
1376 
1377 _TENZOR_RETURNS_(short,short,1U)
1378 _TENZOR_RETURNS_(int,int,1U)
1379 _TENZOR_RETURNS_(long,long,1U)
1380 _TENZOR_RETURNS_(float,float,1U)
1381 _TENZOR_RETURNS_(double,double,1U)
1382 _TENZOR_RETURNS_(dcomplex,dcomplex,1U)
1383 _TENZOR_RETURNS_(int,short,1U)
1384 _TENZOR_RETURNS_(long,short,1U)
1385 _TENZOR_RETURNS_(long,int,1U)
1386 _TENZOR_RETURNS_(float,short,1U)
1387 _TENZOR_RETURNS_(float,int,1U)
1388 _TENZOR_RETURNS_(float,long,1U)
1389 _TENZOR_RETURNS_(double,short,1U)
1390 _TENZOR_RETURNS_(double,int,1U)
1391 _TENZOR_RETURNS_(double,long,1U)
1392 _TENZOR_RETURNS_(double,float,1U)
1393 _TENZOR_RETURNS_(dcomplex,short,1U)
1394 _TENZOR_RETURNS_(dcomplex,int,1U)
1395 _TENZOR_RETURNS_(dcomplex,long,1U)
1396 _TENZOR_RETURNS_(dcomplex,float,1U)
1397 _TENZOR_RETURNS_(dcomplex,double,1U)
1398 
1399 _TENZOR_RETURNS_(short,short,2U)
1400 _TENZOR_RETURNS_(int,int,2U)
1401 _TENZOR_RETURNS_(long,long,2U)
1402 _TENZOR_RETURNS_(float,float,2U)
1403 _TENZOR_RETURNS_(double,double,2U)
1404 _TENZOR_RETURNS_(dcomplex,dcomplex,2U)
1405 _TENZOR_RETURNS_(int,short,2U)
1406 _TENZOR_RETURNS_(long,short,2U)
1407 _TENZOR_RETURNS_(long,int,2U)
1408 _TENZOR_RETURNS_(float,short,2U)
1409 _TENZOR_RETURNS_(float,int,2U)
1410 _TENZOR_RETURNS_(float,long,2U)
1411 _TENZOR_RETURNS_(double,short,2U)
1412 _TENZOR_RETURNS_(double,int,2U)
1413 _TENZOR_RETURNS_(double,long,2U)
1414 _TENZOR_RETURNS_(double,float,2U)
1415 _TENZOR_RETURNS_(dcomplex,short,2U)
1416 _TENZOR_RETURNS_(dcomplex,int,2U)
1417 _TENZOR_RETURNS_(dcomplex,long,2U)
1418 _TENZOR_RETURNS_(dcomplex,float,2U)
1419 _TENZOR_RETURNS_(dcomplex,double,2U)
1420 
1421 _TENZOR_RETURNS_(short,short,3U)
1422 _TENZOR_RETURNS_(int,int,3U)
1423 _TENZOR_RETURNS_(long,long,3U)
1424 _TENZOR_RETURNS_(float,float,3U)
1425 _TENZOR_RETURNS_(double,double,3U)
1426 _TENZOR_RETURNS_(dcomplex,dcomplex,3U)
1427 _TENZOR_RETURNS_(int,short,3U)
1428 _TENZOR_RETURNS_(long,short,3U)
1429 _TENZOR_RETURNS_(long,int,3U)
1430 _TENZOR_RETURNS_(float,short,3U)
1431 _TENZOR_RETURNS_(float,int,3U)
1432 _TENZOR_RETURNS_(float,long,3U)
1433 _TENZOR_RETURNS_(double,short,3U)
1434 _TENZOR_RETURNS_(double,int,3U)
1435 _TENZOR_RETURNS_(double,long,3U)
1436 _TENZOR_RETURNS_(double,float,3U)
1437 _TENZOR_RETURNS_(dcomplex,short,3U)
1438 _TENZOR_RETURNS_(dcomplex,int,3U)
1439 _TENZOR_RETURNS_(dcomplex,long,3U)
1440 _TENZOR_RETURNS_(dcomplex,float,3U)
1441 _TENZOR_RETURNS_(dcomplex,double,3U)
1442 
1443 #undef _TENZOR_RETURNS_
1444 
1445 
1446 #define _SYMTENZOR_RETURNS_(T1,T2,Dim) \
1447 template<> struct \
1448  PETEBinaryReturn<SymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> \
1449  { typedef \
1450  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1451 template<> struct \
1452  PETEBinaryReturn<SymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot> \
1453  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1454 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> \
1455  { typedef \
1456  Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1457 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> \
1458  { typedef \
1459  Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1460 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpAdd> \
1461  { typedef \
1462  Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; }; \
1463 template<> struct \
1464  PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpSubtract> \
1465  { typedef \
1466  Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; }; \
1467 template<> struct \
1468  PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpMultipply> \
1469  { typedef \
1470  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1471 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> \
1472  { typedef \
1473  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1474 template<> struct \
1475  PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot> \
1476  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1477 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpAdd> \
1478  { typedef \
1479  Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; }; \
1480 template<> struct \
1481  PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpSubtract> \
1482  { typedef \
1483  Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; }; \
1484 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>, FnDot> \
1485  { typedef \
1486  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1487 template<> struct \
1488  PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>, FnDotDot> \
1489  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1490 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,T2,OpMultipply> \
1491  { typedef \
1492  SymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1493 template<> struct PETEBinaryReturn<T1,SymTenzor<T2,Dim>,OpMultipply> \
1494  { typedef \
1495  SymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> \
1496  type; }; \
1497 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,T2,OpDivide> \
1498  { typedef SymTenzor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim> type; };
1499 
1500 _SYMTENZOR_RETURNS_(short,short,1U)
1502 _SYMTENZOR_RETURNS_(long,long,1U)
1503 _SYMTENZOR_RETURNS_(float,float,1U)
1504 _SYMTENZOR_RETURNS_(double,double,1U)
1505 _SYMTENZOR_RETURNS_(dcomplex,dcomplex,1U)
1506 _SYMTENZOR_RETURNS_(int,short,1U)
1507 _SYMTENZOR_RETURNS_(long,short,1U)
1509 _SYMTENZOR_RETURNS_(float,short,1U)
1510 _SYMTENZOR_RETURNS_(float,int,1U)
1511 _SYMTENZOR_RETURNS_(float,long,1U)
1512 _SYMTENZOR_RETURNS_(double,short,1U)
1513 _SYMTENZOR_RETURNS_(double,int,1U)
1514 _SYMTENZOR_RETURNS_(double,long,1U)
1515 _SYMTENZOR_RETURNS_(double,float,1U)
1516 _SYMTENZOR_RETURNS_(dcomplex,short,1U)
1517 _SYMTENZOR_RETURNS_(dcomplex,int,1U)
1518 _SYMTENZOR_RETURNS_(dcomplex,long,1U)
1519 _SYMTENZOR_RETURNS_(dcomplex,float,1U)
1520 _SYMTENZOR_RETURNS_(dcomplex,double,1U)
1521 
1522 _SYMTENZOR_RETURNS_(short,short,2U)
1524 _SYMTENZOR_RETURNS_(long,long,2U)
1525 _SYMTENZOR_RETURNS_(float,float,2U)
1526 _SYMTENZOR_RETURNS_(double,double,2U)
1527 _SYMTENZOR_RETURNS_(dcomplex,dcomplex,2U)
1528 _SYMTENZOR_RETURNS_(int,short,2U)
1529 _SYMTENZOR_RETURNS_(long,short,2U)
1531 _SYMTENZOR_RETURNS_(float,short,2U)
1532 _SYMTENZOR_RETURNS_(float,int,2U)
1533 _SYMTENZOR_RETURNS_(float,long,2U)
1534 _SYMTENZOR_RETURNS_(double,short,2U)
1535 _SYMTENZOR_RETURNS_(double,int,2U)
1536 _SYMTENZOR_RETURNS_(double,long,2U)
1537 _SYMTENZOR_RETURNS_(double,float,2U)
1538 _SYMTENZOR_RETURNS_(dcomplex,short,2U)
1539 _SYMTENZOR_RETURNS_(dcomplex,int,2U)
1540 _SYMTENZOR_RETURNS_(dcomplex,long,2U)
1541 _SYMTENZOR_RETURNS_(dcomplex,float,2U)
1542 _SYMTENZOR_RETURNS_(dcomplex,double,2U)
1543 
1544 _SYMTENZOR_RETURNS_(short,short,3U)
1546 _SYMTENZOR_RETURNS_(long,long,3U)
1547 _SYMTENZOR_RETURNS_(float,float,3U)
1548 _SYMTENZOR_RETURNS_(double,double,3U)
1549 _SYMTENZOR_RETURNS_(dcomplex,dcomplex,3U)
1550 _SYMTENZOR_RETURNS_(int,short,3U)
1551 _SYMTENZOR_RETURNS_(long,short,3U)
1553 _SYMTENZOR_RETURNS_(float,short,3U)
1554 _SYMTENZOR_RETURNS_(float,int,3U)
1555 _SYMTENZOR_RETURNS_(float,long,3U)
1556 _SYMTENZOR_RETURNS_(double,short,3U)
1557 _SYMTENZOR_RETURNS_(double,int,3U)
1558 _SYMTENZOR_RETURNS_(double,long,3U)
1559 _SYMTENZOR_RETURNS_(double,float,3U)
1560 _SYMTENZOR_RETURNS_(dcomplex,short,3U)
1561 _SYMTENZOR_RETURNS_(dcomplex,int,3U)
1562 _SYMTENZOR_RETURNS_(dcomplex,long,3U)
1563 _SYMTENZOR_RETURNS_(dcomplex,float,3U)
1564 _SYMTENZOR_RETURNS_(dcomplex,double,3U)
1565 
1566 #undef _SYMTENZOR_RETURNS_
1567 
1568 
1569 #define _ANTISYMTENZOR_RETURNS_(T1,T2,Dim) \
1570 template<> struct \
1571  PETEBinaryReturn<AntiSymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot> \
1572  { typedef \
1573  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1574 template<> struct \
1575  PETEBinaryReturn<AntiSymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot> \
1576  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1577 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,AntiSymTenzor<T2,Dim>,FnDot>\
1578  { typedef \
1579  Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1580 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Vektor<T2,Dim>,FnDot>\
1581  { typedef \
1582  Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1583 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpAdd>\
1584  { typedef \
1585  Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; }; \
1586 template<> struct \
1587  PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpSubtract> \
1588  { typedef \
1589  Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; }; \
1590 template<> struct \
1591  PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpMultipply> \
1592  { typedef \
1593  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1594 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,FnDot>\
1595  { typedef \
1596  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1597 template<> struct \
1598  PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot> \
1599  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1600 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpAdd>\
1601  { typedef \
1602  Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; }; \
1603 template<> struct \
1604  PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpSubtract> \
1605  { typedef \
1606  Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; }; \
1607 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDot>\
1608  { typedef \
1609  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1610 template<> struct \
1611  PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>, FnDotDot> \
1612  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1613 template<> \
1614 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpAdd> \
1615  { typedef \
1616  Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; }; \
1617 template<> struct \
1618  PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpSubtract> \
1619  { typedef \
1620  Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; }; \
1621 template<> struct \
1622  PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpMultipply> \
1623  { typedef \
1624  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1625 template<> \
1626 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,FnDot> \
1627  { typedef \
1628  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1629 template<> struct \
1630  PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot> \
1631  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1632 template<> \
1633 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,OpAdd> \
1634  { typedef \
1635  Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; }; \
1636 template<> struct \
1637  PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,OpSubtract> \
1638  { typedef \
1639  Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; }; \
1640 template<> \
1641 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,FnDot> \
1642  { typedef \
1643  Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1644 template<> struct \
1645  PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot> \
1646  { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; }; \
1647 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,T2,OpMultipply> \
1648  { typedef \
1649  AntiSymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; }; \
1650 template<> struct PETEBinaryReturn<T1,AntiSymTenzor<T2,Dim>,OpMultipply> \
1651  { typedef \
1652  AntiSymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> \
1653  type; }; \
1654 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,T2,OpDivide> \
1655  { typedef AntiSymTenzor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim> type; };
1656 
1661 _ANTISYMTENZOR_RETURNS_(double,double,1U)
1662 _ANTISYMTENZOR_RETURNS_(dcomplex,dcomplex,1U)
1669 _ANTISYMTENZOR_RETURNS_(double,short,1U)
1672 _ANTISYMTENZOR_RETURNS_(double,float,1U)
1673 _ANTISYMTENZOR_RETURNS_(dcomplex,short,1U)
1674 _ANTISYMTENZOR_RETURNS_(dcomplex,int,1U)
1675 _ANTISYMTENZOR_RETURNS_(dcomplex,long,1U)
1676 _ANTISYMTENZOR_RETURNS_(dcomplex,float,1U)
1677 _ANTISYMTENZOR_RETURNS_(dcomplex,double,1U)
1678 
1683 _ANTISYMTENZOR_RETURNS_(double,double,2U)
1684 _ANTISYMTENZOR_RETURNS_(dcomplex,dcomplex,2U)
1691 _ANTISYMTENZOR_RETURNS_(double,short,2U)
1694 _ANTISYMTENZOR_RETURNS_(double,float,2U)
1695 _ANTISYMTENZOR_RETURNS_(dcomplex,short,2U)
1696 _ANTISYMTENZOR_RETURNS_(dcomplex,int,2U)
1697 _ANTISYMTENZOR_RETURNS_(dcomplex,long,2U)
1698 _ANTISYMTENZOR_RETURNS_(dcomplex,float,2U)
1699 _ANTISYMTENZOR_RETURNS_(dcomplex,double,2U)
1700 
1705 _ANTISYMTENZOR_RETURNS_(double,double,3U)
1706 _ANTISYMTENZOR_RETURNS_(dcomplex,dcomplex,3U)
1713 _ANTISYMTENZOR_RETURNS_(double,short,3U)
1716 _ANTISYMTENZOR_RETURNS_(double,float,3U)
1717 _ANTISYMTENZOR_RETURNS_(dcomplex,short,3U)
1718 _ANTISYMTENZOR_RETURNS_(dcomplex,int,3U)
1719 _ANTISYMTENZOR_RETURNS_(dcomplex,long,3U)
1720 _ANTISYMTENZOR_RETURNS_(dcomplex,float,3U)
1721 _ANTISYMTENZOR_RETURNS_(dcomplex,double,3U)
1722 
1723 #undef _SYMTENZOR_RETURNS_
1724 
1725 
1726 #endif
1727 
1728 
1730 //
1731 // ASSIGNMENT OPERATORS: min=, max=, &&=, ||=
1732 //
1734 
1735 struct OpMinAssign {
1736 #ifdef IPPL_PURIFY
1737  OpMinAssign() {}
1738  OpMinAssign(const OpMinAssign &) {}
1739  OpMinAssign& operator=(const OpMinAssign &) { return *this; }
1740 #endif
1742 };
1743 
1744 struct OpMaxAssign {
1745 #ifdef IPPL_PURIFY
1746  OpMaxAssign() {}
1747  OpMaxAssign(const OpMaxAssign &) {}
1748  OpMaxAssign& operator=(const OpMaxAssign &) { return *this; }
1749 #endif
1751 };
1752 
1753 struct OpAndAssign {
1754 #ifdef IPPL_PURIFY
1755  OpAndAssign() {}
1756  OpAndAssign(const OpAndAssign &) {}
1757  OpAndAssign& operator=(const OpAndAssign &) { return *this; }
1758 #endif
1760 };
1761 
1762 struct OpOrAssign {
1763 #ifdef IPPL_PURIFY
1764  OpOrAssign() {}
1765  OpOrAssign(const OpOrAssign &) {}
1766  OpOrAssign& operator=(const OpOrAssign &) { return *this; }
1767 #endif
1769 };
1770 
1771 
1773 //
1774 // OPERATOR()
1775 //
1777 
1778 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
1779 
1780 template<class T, class TP, unsigned Dim>
1781 struct PETEUnaryReturn< Vektor<T, Dim>, OpParens<TP> > {
1782  typedef T type;
1783 };
1784 
1785 template<class T, class TP, unsigned Dim>
1786 struct PETEUnaryReturn< AntiSymTenzor<T, Dim>, OpParens<TP> > {
1787  typedef T type;
1788 };
1789 
1790 template<class T, class TP, unsigned Dim>
1791 struct PETEUnaryReturn< SymTenzor<T, Dim>, OpParens<TP> > {
1792  typedef T type;
1793 };
1794 
1795 template<class T, class TP, unsigned Dim>
1796 struct PETEUnaryReturn< Tenzor<T, Dim>, OpParens<TP> > {
1797  typedef T type;
1798 };
1799 
1800 #else
1801 
1802 // More Yucko non-partial-specialization stuff...
1803 
1804 #define _PETE_DEFINE_PARENS_RETURNS_(T,D) \
1805 template<> struct PETEUnaryReturn<class Vektor<T,D>,OpParens<int> > \
1806  { typedef T type; }; \
1807 template<> struct \
1808  PETEUnaryReturn<class Tenzor<T,D>,OpParens<std::pair<int,int> > > \
1809  { typedef T type; }; \
1810 template<> struct \
1811  PETEUnaryReturn<class AntiSymTenzor<T,D>,OpParens<std::pair<int,int> > > \
1812  { typedef T type; }; \
1813 template<> struct \
1814  PETEUnaryReturn<class SymTenzor<T,D>,OpParens<std::pair<int,int> > > \
1815  { typedef T type; };
1816 
1835 
1836 #undef _PETE_DEFINE_PARENS_RETURNS_
1837 
1838 #endif
1839 
1840 
1842 //
1843 // END OF FILE
1844 //
1846 
1847 #endif // IPPL_TYPE_COMPUTATIONS_H
1848 
1849 /***************************************************************************
1850  * $RCSfile: IpplTypeComputations.h,v $ $Author: adelmann $
1851  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:28 $
1852  * IPPL_VERSION_ID: $Id: IpplTypeComputations.h,v 1.1.1.1 2003/01/23 07:40:28 adelmann Exp $
1853  ***************************************************************************/
#define _ANTISYMTENZOR_RETURNS_(T1, T2, Dim)
Vektor< short, 2U > type
Definition: TSVMeta.h:24
Definition: rbendmap.h:8
Vektor< double, 1U > type
SymTenzor< dcomplex, 3U > type
SymTenzor< short, 3U > type
const int PETE_BinaryUseLeftTag
const int PETE_BinaryPromoteTag
Vektor< float, 2U > type
Tenzor< float, 1U > type
SymTenzor< double, 2U > type
SymTenzor< long, 1U > type
std::complex< double > dcomplex
Definition: dcomplex.h:30
PETE_ComputeUnaryType< PETE_Type2Index< T >::val, Op::tag >::type type
SymTenzor< short, 1U > type
#define _SYMTENZOR_RETURNS_(T1, T2, Dim)
#define _VEKTOR_RETURNS_(T1, T2, Dim)
SymTenzor< dcomplex, 1U > type
Tenzor< dcomplex, 2U > type
SymTenzor< float, 3U > type
SymTenzor< long, 2U > type
SymTenzor< float, 1U > type
Tenzor< dcomplex, 1U > type
Vektor< double, 3U > type
#define _UNARY_TENSOR_RETURNS_(T, D)
Vektor< short, 3U > type
#define _TENZOR_RETURNS_(T1, T2, Dim)
#define _PETE_DEFINE_PARENS_RETURNS_(T, D)
Vektor< dcomplex, 3U > type
const int PETE_UnaryPassThruTag
Tenzor< float, 3U > type
Tenzor< double, 3U > type
SymTenzor< int, 1U > type
SymTenzor< int, 3U > type
SymTenzor< long, 3U > type
SymTenzor< int, 2U > type
OpParens(const TP &a)
PETE_ComputeBinaryType< PETE_Type2Index< T1 >::val, PETE_Type2Index< T2 >::val, Op::tag >::type type
Tenzor< short, 3U > type
Tenzor< short, 1U > type
#define _PETE_RNG_RETURNS_(GEN)
FnArg FnReal sign(a))
Vektor< float, 3U > type
Vektor< dcomplex, 1U > type
Tenzor< dcomplex, 3U > type
Vektor< double, 2U > type
Tenzor< double, 1U > type
Definition: RNGXCI.h:44
short short FnDot
Tenzor< double, 2U > type
Vektor< short, 1U > type
Vektor< dcomplex, 2U > type
const unsigned Dim
SymTenzor< short, 2U > type
short FnDotDot
SymTenzor< dcomplex, 2U > type
SymTenzor< double, 1U > type
Vektor< float, 1U > type
SymTenzor< double, 3U > type
SymTenzor< float, 2U > type
Tenzor< float, 2U > type
Tenzor< short, 2U > type