src/PETE/IpplTypeComputations.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 
00013 //
00014 // FILE NAME
00015 //    IpplTypeComputations.h
00016 //
00017 // CREATED
00018 //    July 11, 1997
00019 //
00020 // DESCRIPTION
00021 //    PETE: Portable Expression Template Engine.
00022 //
00023 //    This header file contains IPPL-specific type computations.
00024 //
00026 
00027 #ifndef IPPL_TYPE_COMPUTATIONS_H
00028 #define IPPL_TYPE_COMPUTATIONS_H
00029 
00030 
00031 // include files
00032 #include "PETE/TypeComputations.h"
00033 #include "AppTypes/dcomplex.h"
00034 
00035 
00036 // forward declarations
00037 template<class T, unsigned D> class Vektor;
00038 template<class T, unsigned D> class Tenzor;
00039 template<class T, unsigned D> class AntiSymTenzor;
00040 template<class T, unsigned D> class SymTenzor;
00041 class RNGBitReverse;
00042 template <class T> class RNGLattice;
00043 class RNGSimple;
00044 class RNGRand;
00045 class RNGXDiv;
00046 class RNGXCI;
00047 
00048 
00049 // definition of global sign function
00050 template<class T>
00051 inline int sign(T a) { return ((a > 0) ? 1 : (a == 0 ? 0 : -1)); }
00052 
00053 
00055 //
00056 // PETE_Type2Index FOR USER TYPES
00057 //
00059 
00060 // Complex numbers.
00061 
00062 template<> struct PETE_Type2Index<dcomplex> {
00063   enum { val = 8 };
00064 };
00065 
00066 // Return types for scalar ops with RNGs.
00067 
00068 #define _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OP)                             \
00069 template <>                                                             \
00070 struct PETEBinaryReturn<GEN,SCA,OP> {                                   \
00071   typedef PETEBinaryReturn<double,SCA,OP>::type type;                   \
00072 };                                                                      \
00073 template <>                                                             \
00074 struct PETEBinaryReturn<SCA,GEN,OP> {                                   \
00075   typedef PETEBinaryReturn<SCA,double,OP>::type type;                   \
00076 };
00077 
00078 #define _SCALAR_RNG_RETURNS_(GEN,SCA)                                   \
00079 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpAdd)                                  \
00080 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpSubtract)                             \
00081 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpMultipply)                             \
00082 _SCALAR_RNG_OP_RETURNS_(GEN,SCA,OpDivide)
00083 
00084 #define _PETE_RNG_RETURNS_(GEN)                                         \
00085                                                                         \
00086 template <> struct PETE_Type2Index< GEN > {                             \
00087   enum { val = PETE_Type2Index<double>::val };                          \
00088 };                                                                      \
00089                                                                         \
00090 _SCALAR_RNG_RETURNS_(GEN,short)                                         \
00091 _SCALAR_RNG_RETURNS_(GEN,int)                                           \
00092 _SCALAR_RNG_RETURNS_(GEN,long)                                          \
00093 _SCALAR_RNG_RETURNS_(GEN,float)                                         \
00094 _SCALAR_RNG_RETURNS_(GEN,double)                                        \
00095 _SCALAR_RNG_RETURNS_(GEN,dcomplex)
00096 
00097 _PETE_RNG_RETURNS_(RNGBitReverse)
00098 _PETE_RNG_RETURNS_(RNGLattice<float>)
00099 _PETE_RNG_RETURNS_(RNGLattice<double>)
00100 _PETE_RNG_RETURNS_(RNGSimple)
00101 _PETE_RNG_RETURNS_(RNGRand)
00102 _PETE_RNG_RETURNS_(RNGXDiv)
00103 _PETE_RNG_RETURNS_(RNGXCI)
00104 
00105 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
00106 
00107 // Life is way easier with this feature.
00108 
00109 template<class T, unsigned Dim>
00110 struct PETE_Type2Index< Vektor<T, Dim> > {
00111   enum { val = 20 + 10 * Dim + PETE_Type2Index<T>::val };
00112 };
00113 
00114 template<class T, unsigned Dim>
00115 struct PETE_Type2Index< SymTenzor<T, Dim> > {
00116   enum { val = 120 + 10 * Dim + PETE_Type2Index<T>::val };
00117 };
00118 
00119 template<class T, unsigned Dim>
00120 struct PETE_Type2Index< Tenzor<T, Dim> > {
00121   enum { val = 220 + 10 * Dim + PETE_Type2Index<T>::val };
00122 };
00123 
00124 template<class T, unsigned Dim>
00125 struct PETE_Type2Index< AntiSymTenzor<T, Dim> > {
00126   enum { val = 320 + 10 * Dim + PETE_Type2Index<T>::val };
00127 };
00128 
00129 #else
00130 
00131 // Without partial specialization, we must give all the cases. Yuuuck!
00132 
00133 // Vectors of size 1.
00134 
00135 template<> struct PETE_Type2Index< Vektor<short, 1U> > {
00136   enum { val = 30 };
00137 };
00138 
00139 template<> struct PETE_Type2Index< Vektor<int, 1U> > {
00140   enum { val = 31 };
00141 };
00142 
00143 template<> struct PETE_Type2Index< Vektor<long, 1U> > {
00144   enum { val = 32 };
00145 };
00146 
00147 template<> struct PETE_Type2Index< Vektor<float, 1U> > {
00148   enum { val = 33 };
00149 };
00150 
00151 template<> struct PETE_Type2Index< Vektor<double, 1U> > {
00152   enum { val = 34 };
00153 };
00154 
00155 template<> struct PETE_Type2Index< Vektor<dcomplex, 1U> > {
00156   enum { val = 35 };
00157 };
00158 
00159 // Vectors of size 2.
00160 
00161 template<> struct PETE_Type2Index< Vektor<short, 2U> > {
00162   enum { val = 40 };
00163 };
00164 
00165 template<> struct PETE_Type2Index< Vektor<int, 2U> > {
00166   enum { val = 41 };
00167 };
00168 
00169 template<> struct PETE_Type2Index< Vektor<long, 2U> > {
00170   enum { val = 42 };
00171 };
00172 
00173 template<> struct PETE_Type2Index< Vektor<float, 2U> > {
00174   enum { val = 43 };
00175 };
00176 
00177 template<> struct PETE_Type2Index< Vektor<double, 2U> > {
00178   enum { val = 44 };
00179 };
00180 
00181 template<> struct PETE_Type2Index< Vektor<dcomplex, 2U> > {
00182   enum { val = 45 };
00183 };
00184 
00185 // Vectors of size 3.
00186 
00187 template<> struct PETE_Type2Index< Vektor<short, 3U> > {
00188   enum { val = 50 };
00189 };
00190 
00191 template<> struct PETE_Type2Index< Vektor<int, 3U> > {
00192   enum { val = 51 };
00193 };
00194 
00195 template<> struct PETE_Type2Index< Vektor<long, 3U> > {
00196   enum { val = 52 };
00197 };
00198 
00199 template<> struct PETE_Type2Index< Vektor<float, 3U> > {
00200   enum { val = 53 };
00201 };
00202 
00203 template<> struct PETE_Type2Index< Vektor<double, 3U> > {
00204   enum { val = 54 };
00205 };
00206 
00207 template<> struct PETE_Type2Index< Vektor<dcomplex, 3U> > {
00208   enum { val = 55 };
00209 };
00210 
00211 // SymTensors of size 1.
00212 
00213 template<> struct PETE_Type2Index< SymTenzor<short, 1U> > {
00214   enum { val = 130 };
00215 };
00216 
00217 template<> struct PETE_Type2Index< SymTenzor<int, 1U> > {
00218   enum { val = 131 };
00219 };
00220 
00221 template<> struct PETE_Type2Index< SymTenzor<long, 1U> > {
00222   enum { val = 132 };
00223 };
00224 
00225 template<> struct PETE_Type2Index< SymTenzor<float, 1U> > {
00226   enum { val = 133 };
00227 };
00228 
00229 template<> struct PETE_Type2Index< SymTenzor<double, 1U> > {
00230   enum { val = 134 };
00231 };
00232 
00233 template<> struct PETE_Type2Index< SymTenzor<dcomplex, 1U> > {
00234   enum { val = 135 };
00235 };
00236 
00237 // SymTensors of size 2.
00238 
00239 template<> struct PETE_Type2Index< SymTenzor<short, 2U> > {
00240   enum { val = 140 };
00241 };
00242 
00243 template<> struct PETE_Type2Index< SymTenzor<int, 2U> > {
00244   enum { val = 141 };
00245 };
00246 
00247 template<> struct PETE_Type2Index< SymTenzor<long, 2U> > {
00248   enum { val = 142 };
00249 };
00250 
00251 template<> struct PETE_Type2Index< SymTenzor<float, 2U> > {
00252   enum { val = 143 };
00253 };
00254 
00255 template<> struct PETE_Type2Index< SymTenzor<double, 2U> > {
00256   enum { val = 144 };
00257 };
00258 
00259 template<> struct PETE_Type2Index< SymTenzor<dcomplex, 2U> > {
00260   enum { val = 145 };
00261 };
00262 
00263 // SymTensors of size 3.
00264 
00265 template<> struct PETE_Type2Index< SymTenzor<short, 3U> > {
00266   enum { val = 150 };
00267 };
00268 
00269 template<> struct PETE_Type2Index< SymTenzor<int, 3U> > {
00270   enum { val = 151 };
00271 };
00272 
00273 template<> struct PETE_Type2Index< SymTenzor<long, 3U> > {
00274   enum { val = 152 };
00275 };
00276 
00277 template<> struct PETE_Type2Index< SymTenzor<float, 3U> > {
00278   enum { val = 153 };
00279 };
00280 
00281 template<> struct PETE_Type2Index< SymTenzor<double, 3U> > {
00282   enum { val = 154 };
00283 };
00284 
00285 template<> struct PETE_Type2Index< SymTenzor<dcomplex, 3U> > {
00286   enum { val = 155 };
00287 };
00288 
00289 // Tensors of size 1.
00290 
00291 template<> struct PETE_Type2Index< Tenzor<short, 1U> > {
00292   enum { val = 230 };
00293 };
00294 
00295 template<> struct PETE_Type2Index< Tenzor<int, 1U> > {
00296   enum { val = 231 };
00297 };
00298 
00299 template<> struct PETE_Type2Index< Tenzor<long, 1U> > {
00300   enum { val = 232 };
00301 };
00302 
00303 template<> struct PETE_Type2Index< Tenzor<float, 1U> > {
00304   enum { val = 233 };
00305 };
00306 
00307 template<> struct PETE_Type2Index< Tenzor<double, 1U> > {
00308   enum { val = 234 };
00309 };
00310 
00311 template<> struct PETE_Type2Index< Tenzor<dcomplex, 1U> > {
00312   enum { val = 235 };
00313 };
00314 
00315 // Tensors of size 2.
00316 
00317 template<> struct PETE_Type2Index< Tenzor<short, 2U> > {
00318   enum { val = 240 };
00319 };
00320 
00321 template<> struct PETE_Type2Index< Tenzor<int, 2U> > {
00322   enum { val = 241 };
00323 };
00324 
00325 template<> struct PETE_Type2Index< Tenzor<long, 2U> > {
00326   enum { val = 242 };
00327 };
00328 
00329 template<> struct PETE_Type2Index< Tenzor<float, 2U> > {
00330   enum { val = 243 };
00331 };
00332 
00333 template<> struct PETE_Type2Index< Tenzor<double, 2U> > {
00334   enum { val = 244 };
00335 };
00336 
00337 template<> struct PETE_Type2Index< Tenzor<dcomplex, 2U> > {
00338   enum { val = 245 };
00339 };
00340 
00341 // Tensors of size 3.
00342 
00343 template<> struct PETE_Type2Index< Tenzor<short, 3U> > {
00344   enum { val = 250 };
00345 };
00346 
00347 template<> struct PETE_Type2Index< Tenzor<int, 3U> > {
00348   enum { val = 251 };
00349 };
00350 
00351 template<> struct PETE_Type2Index< Tenzor<long, 3U> > {
00352   enum { val = 252 };
00353 };
00354 
00355 template<> struct PETE_Type2Index< Tenzor<float, 3U> > {
00356   enum { val = 253 };
00357 };
00358 
00359 template<> struct PETE_Type2Index< Tenzor<double, 3U> > {
00360   enum { val = 254 };
00361 };
00362 
00363 template<> struct PETE_Type2Index< Tenzor<dcomplex, 3U> > {
00364   enum { val = 255 };
00365 };
00366 
00367 #endif
00368 
00369 
00371 //
00372 // PETE_Index2Type FOR USER TYPES
00373 //
00375 
00376 #if !defined(IPPL_USE_PARTIAL_SPECIALIZATION)
00377 
00378 // Complex numbers.
00379 
00380 template<> struct PETE_Index2Type<8> {
00381   typedef dcomplex type;
00382 };
00383 
00384 // Vectors of length 1.
00385 
00386 template<> struct PETE_Index2Type<30> {
00387   typedef Vektor<short, 1U> type;
00388 };
00389 
00390 template<> struct PETE_Index2Type<31> {
00391   typedef Vektor<int, 1U> type;
00392 };
00393 
00394 template<> struct PETE_Index2Type<32> {
00395   typedef Vektor<long, 1U> type;
00396 };
00397 
00398 template<> struct PETE_Index2Type<33> {
00399   typedef Vektor<float, 1U> type;
00400 };
00401 
00402 template<> struct PETE_Index2Type<34> {
00403   typedef Vektor<double, 1U> type;
00404 };
00405 
00406 template<> struct PETE_Index2Type<35> {
00407   typedef Vektor<dcomplex, 1U> type;
00408 };
00409 
00410 // Vectors of length 2.
00411 
00412 template<> struct PETE_Index2Type<40> {
00413   typedef Vektor<short, 2U> type;
00414 };
00415 
00416 template<> struct PETE_Index2Type<41> {
00417   typedef Vektor<int, 2U> type;
00418 };
00419 
00420 template<> struct PETE_Index2Type<42> {
00421   typedef Vektor<long, 2U> type;
00422 };
00423 
00424 template<> struct PETE_Index2Type<43> {
00425   typedef Vektor<float, 2U> type;
00426 };
00427 
00428 template<> struct PETE_Index2Type<44> {
00429   typedef Vektor<double, 2U> type;
00430 };
00431 
00432 template<> struct PETE_Index2Type<45> {
00433   typedef Vektor<dcomplex, 2U> type;
00434 };
00435 
00436 // Vectors of length 3.
00437 
00438 template<> struct PETE_Index2Type<50> {
00439   typedef Vektor<short, 3U> type;
00440 };
00441 
00442 template<> struct PETE_Index2Type<51> {
00443   typedef Vektor<int, 3U> type;
00444 };
00445 
00446 template<> struct PETE_Index2Type<52> {
00447   typedef Vektor<long, 3U> type;
00448 };
00449 
00450 template<> struct PETE_Index2Type<53> {
00451   typedef Vektor<float, 3U> type;
00452 };
00453 
00454 template<> struct PETE_Index2Type<54> {
00455   typedef Vektor<double, 3U> type;
00456 };
00457 
00458 template<> struct PETE_Index2Type<55> {
00459   typedef Vektor<dcomplex, 3U> type;
00460 };
00461 
00462 // SymTensors of length 1.
00463 
00464 template<> struct PETE_Index2Type<130> {
00465   typedef SymTenzor<short, 1U> type;
00466 };
00467 
00468 template<> struct PETE_Index2Type<131> {
00469   typedef SymTenzor<int, 1U> type;
00470 };
00471 
00472 template<> struct PETE_Index2Type<132> {
00473   typedef SymTenzor<long, 1U> type;
00474 };
00475 
00476 template<> struct PETE_Index2Type<133> {
00477   typedef SymTenzor<float, 1U> type;
00478 };
00479 
00480 template<> struct PETE_Index2Type<134> {
00481   typedef SymTenzor<double, 1U> type;
00482 };
00483 
00484 template<> struct PETE_Index2Type<135> {
00485   typedef SymTenzor<dcomplex, 1U> type;
00486 };
00487 
00488 // SymTensors of length 2.
00489 
00490 template<> struct PETE_Index2Type<140> {
00491   typedef SymTenzor<short, 2U> type;
00492 };
00493 
00494 template<> struct PETE_Index2Type<141> {
00495   typedef SymTenzor<int, 2U> type;
00496 };
00497 
00498 template<> struct PETE_Index2Type<142> {
00499   typedef SymTenzor<long, 2U> type;
00500 };
00501 
00502 template<> struct PETE_Index2Type<143> {
00503   typedef SymTenzor<float, 2U> type;
00504 };
00505 
00506 template<> struct PETE_Index2Type<144> {
00507   typedef SymTenzor<double, 2U> type;
00508 };
00509 
00510 template<> struct PETE_Index2Type<145> {
00511   typedef SymTenzor<dcomplex, 2U> type;
00512 };
00513 
00514 // SymTensors of length 3.
00515 
00516 template<> struct PETE_Index2Type<150> {
00517   typedef SymTenzor<short, 3U> type;
00518 };
00519 
00520 template<> struct PETE_Index2Type<151> {
00521   typedef SymTenzor<int, 3U> type;
00522 };
00523 
00524 template<> struct PETE_Index2Type<152> {
00525   typedef SymTenzor<long, 3U> type;
00526 };
00527 
00528 template<> struct PETE_Index2Type<153> {
00529   typedef SymTenzor<float, 3U> type;
00530 };
00531 
00532 template<> struct PETE_Index2Type<154> {
00533   typedef SymTenzor<double, 3U> type;
00534 };
00535 
00536 template<> struct PETE_Index2Type<155> {
00537   typedef SymTenzor<dcomplex, 3U> type;
00538 };
00539 
00540 // Tensors of length 1.
00541 
00542 template<> struct PETE_Index2Type<230> {
00543   typedef Tenzor<short, 1U> type;
00544 };
00545 
00546 template<> struct PETE_Index2Type<231> {
00547   typedef Tenzor<int, 1U> type;
00548 };
00549 
00550 template<> struct PETE_Index2Type<232> {
00551   typedef Tenzor<long, 1U> type;
00552 };
00553 
00554 template<> struct PETE_Index2Type<233> {
00555   typedef Tenzor<float, 1U> type;
00556 };
00557 
00558 template<> struct PETE_Index2Type<234> {
00559   typedef Tenzor<double, 1U> type;
00560 };
00561 
00562 template<> struct PETE_Index2Type<235> {
00563   typedef Tenzor<dcomplex, 1U> type;
00564 };
00565 
00566 // Tensors of length 2.
00567 
00568 template<> struct PETE_Index2Type<240> {
00569   typedef Tenzor<short, 2U> type;
00570 };
00571 
00572 template<> struct PETE_Index2Type<241> {
00573   typedef Tenzor<int, 2U> type;
00574 };
00575 
00576 template<> struct PETE_Index2Type<242> {
00577   typedef Tenzor<long, 2U> type;
00578 };
00579 
00580 template<> struct PETE_Index2Type<243> {
00581   typedef Tenzor<float, 2U> type;
00582 };
00583 
00584 template<> struct PETE_Index2Type<244> {
00585   typedef Tenzor<double, 2U> type;
00586 };
00587 
00588 template<> struct PETE_Index2Type<245> {
00589   typedef Tenzor<dcomplex, 2U> type;
00590 };
00591 
00592 // Tensors of length 3.
00593 
00594 template<> struct PETE_Index2Type<250> {
00595   typedef Tenzor<short, 3U> type;
00596 };
00597 
00598 template<> struct PETE_Index2Type<251> {
00599   typedef Tenzor<int, 3U> type;
00600 };
00601 
00602 template<> struct PETE_Index2Type<252> {
00603   typedef Tenzor<long, 3U> type;
00604 };
00605 
00606 template<> struct PETE_Index2Type<253> {
00607   typedef Tenzor<float, 3U> type;
00608 };
00609 
00610 template<> struct PETE_Index2Type<254> {
00611   typedef Tenzor<double, 3U> type;
00612 };
00613 
00614 template<> struct PETE_Index2Type<255> {
00615   typedef Tenzor<dcomplex, 3U> type;
00616 };
00617 
00618 #endif
00619 
00620 
00622 //
00623 // SPECIAL CASES FOR UNARY FUNCTIONS
00624 //
00626 
00627 // Abs function: special return for complex numbers.
00628 
00629 struct FnAbs {
00630 #ifdef IPPL_PURIFY
00631   FnAbs() {}
00632   FnAbs(const FnAbs &) {}
00633   FnAbs& operator=(const FnAbs &) { return *this; }
00634 #endif
00635   enum { tag = PETE_UnaryPassThruTag };
00636 };
00637 
00638 template<> struct PETEUnaryReturn<dcomplex, FnAbs> {
00639   typedef double type;
00640 };
00641 
00642 // The conj, norm, arg, real, and imag functions for complex numbers.
00643 
00644 struct FnConj {
00645 #ifdef IPPL_PURIFY
00646   FnConj() {}
00647   FnConj(const FnConj &) {}
00648   FnConj& operator=(const FnConj &) { return *this; }
00649 #endif
00650   enum { tag = PETE_UnaryPassThruTag };
00651 };
00652 
00653 struct FnNorm {
00654 #ifdef IPPL_PURIFY
00655   FnNorm() {}
00656   FnNorm(const FnNorm &) {}
00657   FnNorm& operator=(const FnNorm &) { return *this; }
00658 #endif
00659   typedef double type;
00660   enum { tag = PETE_Type2Index<double>::val };
00661 };
00662 
00663 template<> struct PETEUnaryReturn<dcomplex, FnNorm> {
00664   typedef double type;
00665 };
00666 
00667 struct FnArg {
00668 #ifdef IPPL_PURIFY
00669   FnArg() {}
00670   FnArg(const FnArg &) {}
00671   FnArg& operator=(const FnArg &) { return *this; }
00672 #endif
00673   typedef double type;
00674   enum { tag = PETE_Type2Index<double>::val };
00675 };
00676 
00677 template<> struct PETEUnaryReturn<dcomplex, FnArg> {
00678   typedef double type;
00679 };
00680 
00681 struct FnReal {
00682 #ifdef IPPL_PURIFY
00683   FnReal() {}
00684   FnReal(const FnReal &) {}
00685   FnReal& operator=(const FnReal &) { return *this; }
00686 #endif
00687   typedef double type;
00688   enum { tag = PETE_Type2Index<double>::val };
00689 };
00690 
00691 template<> struct PETEUnaryReturn<dcomplex, FnReal> {
00692   typedef double type;
00693 };
00694 
00695 struct FnImag {
00696 #ifdef IPPL_PURIFY
00697   FnImag() {}
00698   FnImag(const FnImag &) {}
00699   FnImag& operator=(const FnImag &) { return *this; }
00700 #endif
00701   typedef double type;
00702   enum { tag = PETE_Type2Index<double>::val };
00703 };
00704 
00705 template<> struct PETEUnaryReturn<dcomplex, FnImag> {
00706   typedef double type;
00707 };
00708 
00709 // The sign function.
00710 
00711 struct FnSign {
00712 #ifdef IPPL_PURIFY
00713   FnSign() {}
00714   FnSign(const FnSign &) {}
00715   FnSign& operator=(const FnSign &) { return *this; }
00716 #endif
00717   typedef int type;
00718   enum { tag = PETE_Type2Index<int>::val };
00719 };
00720 
00721 template<class TP>
00722 struct OpParens
00723 {
00724   enum { tag = PETE_UnaryPassThruTag };
00725   TP Arg;
00726   OpParens() { Arg = TP(); }
00727   OpParens(const TP& a) : Arg(a) {}
00728 };
00729 
00730 // Tensor functions: trace, det (determinant),  and transpose
00731 
00732 struct FnTrace {
00733 #ifdef IPPL_PURIFY
00734   FnTrace() {}
00735   FnTrace(const FnTrace &) {}
00736   FnTrace& operator=(const FnTrace &) { return *this; }
00737 #endif
00738   enum { tag = PETE_UnaryPassThruTag };
00739 };
00740 
00741 struct FnDet {
00742 #ifdef IPPL_PURIFY
00743   FnDet() {}
00744   FnDet(const FnDet &) {}
00745   FnDet& operator=(const FnDet &) { return *this; }
00746 #endif
00747   enum { tag = PETE_UnaryPassThruTag };
00748 };
00749 
00750 struct FnTranspose {
00751 #ifdef IPPL_PURIFY
00752   FnTranspose() {}
00753   FnTranspose(const FnTranspose &) {}
00754   FnTranspose& operator=(const FnTranspose &) { return *this; }
00755 #endif
00756   enum { tag = PETE_UnaryPassThruTag };
00757 };
00758 
00759 struct FnCofactors {
00760 #ifdef IPPL_PURIFY
00761   FnCofactors() {}
00762   FnCofactors(const FnCofactors &) {}
00763   FnCofactors& operator=(const FnCofactors &) { return *this; }
00764 #endif
00765   enum { tag = PETE_UnaryPassThruTag };
00766 };
00767 
00768 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
00769 
00770 // Life is pretty simple if we have partial specialization.
00771 
00772 template<class T, unsigned Dim>
00773 struct PETEUnaryReturn<Tenzor<T,Dim>, FnTrace> {
00774   typedef T type;
00775 };
00776 
00777 template<class T, unsigned Dim>
00778 struct PETEUnaryReturn<SymTenzor<T,Dim>, FnTrace> {
00779   typedef T type;
00780 };
00781 
00782 template<class T, unsigned Dim>
00783 struct PETEUnaryReturn<AntiSymTenzor<T,Dim>, FnTrace> {
00784   typedef T type;
00785 };
00786 
00787 template<class T, unsigned Dim>
00788 struct PETEUnaryReturn<Tenzor<T,Dim>, FnDet> {
00789   typedef T type;
00790 };
00791 
00792 template<class T, unsigned Dim>
00793 struct PETEUnaryReturn<SymTenzor<T,Dim>, FnDet> {
00794   typedef T type;
00795 };
00796 
00797 template<class T, unsigned Dim>
00798 struct PETEUnaryReturn<AntiSymTenzor<T,Dim>, FnDet> {
00799   typedef T type;
00800 };
00801 
00802 template<class T, unsigned Dim>
00803 struct PETEUnaryReturn<Tenzor<T,Dim>, FnTranspose> {
00804   typedef Tenzor<T,Dim> type;
00805 };
00806 
00807 template<class T, unsigned Dim>
00808 struct PETEUnaryReturn<SymTenzor<T,Dim>, FnTranspose> {
00809   typedef SymTenzor<T,Dim> type;
00810 };
00811 
00812 template<class T, unsigned Dim>
00813 struct PETEUnaryReturn<AntiSymTenzor<T,Dim>, FnTranspose> {
00814   typedef AntiSymTenzor<T,Dim> type;
00815 };
00816 
00817 template<class T, unsigned Dim>
00818 struct PETEUnaryReturn<Tenzor<T,Dim>, FnCofactors> {
00819   typedef Tenzor<T,Dim> type;
00820 };
00821 
00822 template<class T, unsigned Dim>
00823 struct PETEUnaryReturn<SymTenzor<T,Dim>, FnCofactors> {
00824   typedef SymTenzor<T,Dim> type;
00825 };
00826 
00827 template<class T, unsigned Dim>
00828 struct PETEUnaryReturn<AntiSymTenzor<T,Dim>, FnCofactors> {
00829   typedef AntiSymTenzor<T,Dim> type;
00830 };
00831 
00832 #else
00833 
00834 // Life is pitiful and barely worth living without partial specialization.
00835 // Sigh, I guess we'll limp along...
00836 
00837 #define _UNARY_TENSOR_RETURNS_(T, D)                                        \
00838 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnTrace>                     \
00839 { typedef T type; };                                                        \
00840 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnTrace>                  \
00841 { typedef T type; };                                                        \
00842 template<> struct PETEUnaryReturn<AntiSymTenzor<T,D>, FnTrace>              \
00843 { typedef T type; };                                                        \
00844 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnDet>                       \
00845 { typedef T type; };                                                        \
00846 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnDet>                    \
00847 { typedef T type; };                                                        \
00848 template<> struct PETEUnaryReturn<AntiSymTenzor<T,D>, FnDet>                \
00849 { typedef T type; };                                                        \
00850 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnTranspose>                 \
00851 { typedef Tenzor<T,D> type; };                                              \
00852 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnTranspose>              \
00853 { typedef SymTenzor<T,D> type; }                                            \
00854 template<> struct PETEUnaryReturn<AntiSymTenzor<T,D>, FnTranspose>          \
00855 { typedef AntiSymTenzor<T,D> type; }                                        \
00856 template<> struct PETEUnaryReturn<Tenzor<T,D>, FnCofactors>                 \
00857 { typedef Tenzor<T,D> type; };                                              \
00858 template<> struct PETEUnaryReturn<SymTenzor<T,D>, FnCofactors>              \
00859 { typedef Tenzor<T,D> type; }                                               \
00860 template<> struct PETEUnaryReturn<AntiSymTenzor<T,D>, FnCofactors>          \
00861 { typedef SymTenzor<T,D> type; }
00862 
00863 _UNARY_TENSOR_RETURNS_(short,1U)
00864 _UNARY_TENSOR_RETURNS_(int,1U)
00865 _UNARY_TENSOR_RETURNS_(long,1U)
00866 _UNARY_TENSOR_RETURNS_(float,1U)
00867 _UNARY_TENSOR_RETURNS_(double,1U)
00868 _UNARY_TENSOR_RETURNS_(dcomplex,1U)
00869 
00870 _UNARY_TENSOR_RETURNS_(short,2U)
00871 _UNARY_TENSOR_RETURNS_(int,2U)
00872 _UNARY_TENSOR_RETURNS_(long,2U)
00873 _UNARY_TENSOR_RETURNS_(float,2U)
00874 _UNARY_TENSOR_RETURNS_(double,2U)
00875 _UNARY_TENSOR_RETURNS_(dcomplex,2U)
00876 
00877 _UNARY_TENSOR_RETURNS_(short,3U)
00878 _UNARY_TENSOR_RETURNS_(int,3U)
00879 _UNARY_TENSOR_RETURNS_(long,3U)
00880 _UNARY_TENSOR_RETURNS_(float,3U)
00881 _UNARY_TENSOR_RETURNS_(double,3U)
00882 _UNARY_TENSOR_RETURNS_(dcomplex,3U)
00883 
00884 #undef _UNARY_TENSOR_RETURNS_
00885 
00886 #endif
00887 
00888 
00890 //
00891 // SPECIAL CASES FOR BINARY FUNCTIONS
00892 //
00894 
00895 // Min and Max functions.
00896 
00897 struct FnMin {
00898 #ifdef IPPL_PURIFY
00899   FnMin() {}
00900   FnMin(const FnMin &) {}
00901   FnMin& operator=(const FnMin &) { return *this; }
00902 #endif
00903   enum { tag = PETE_BinaryPromoteTag };
00904 };
00905 
00906 struct FnMax {
00907 #ifdef IPPL_PURIFY
00908   FnMax() {}
00909   FnMax(const FnMax &) {}
00910   FnMax& operator=(const FnMax &) { return *this; }
00911 #endif
00912   enum { tag = PETE_BinaryPromoteTag };
00913 };
00914 
00915 // Dot, dot-dot, and outerProduct functions.
00916 
00917 struct FnDot {
00918 #ifdef IPPL_PURIFY
00919   FnDot() {}
00920   FnDot(const FnDot &) {}
00921   FnDot& operator=(const FnDot &) { return *this; }
00922 #endif
00923   enum { tag = PETE_BinaryPromoteTag };
00924 };
00925 
00926 struct FnDotDot {
00927 #ifdef IPPL_PURIFY
00928   FnDotDot() {}
00929   FnDotDot(const FnDotDot &) {}
00930   FnDotDot& operator=(const FnDotDot &) { return *this; }
00931 #endif
00932   enum { tag = PETE_BinaryPromoteTag };
00933 };
00934 
00935 struct FnOuterProduct {
00936 #ifdef IPPL_PURIFY
00937   FnOuterProduct() {}
00938   FnOuterProduct(const FnOuterProduct &) {}
00939   FnOuterProduct& operator=(const FnOuterProduct &) { return *this; }
00940 #endif
00941   enum { tag = PETE_BinaryPromoteTag };
00942 };
00943 
00944 // Cross-product:
00945 
00946 struct FnCross {
00947 #ifdef IPPL_PURIFY
00948   FnCross() {}
00949   FnCross(const FnCross &) {}
00950   FnCross& operator=(const FnCross &) { return *this; }
00951 #endif
00952   enum { tag = PETE_BinaryPromoteTag };
00953 };
00954 
00955 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
00956 
00957 // Life is pretty simple if we have partial specialization.
00958 
00959 
00960 // Involving Vektors:
00961 
00962 template<class T1, class T2, unsigned Dim>
00963 struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>, FnCross> {
00964   typedef Vektor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
00965 };
00966 
00967 template<class T1, class T2, unsigned Dim>
00968 struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>, FnOuterProduct> {
00969   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
00970 };
00971 
00972 template<class T1, class T2, unsigned Dim>
00973 struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
00974   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
00975 };
00976 
00977 // Involving Tenzors, but no combination with SymTenzors or AntiSymTenzors:
00978 
00979 template<class T1, class T2, unsigned Dim>
00980 struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>,FnDot> {
00981   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
00982 };
00983 
00984 template<class T1, class T2, unsigned Dim>
00985 struct PETEBinaryReturn<Vektor<T1,Dim>,Tenzor<T2,Dim>, FnDot> {
00986   typedef Vektor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
00987 };
00988 
00989 template<class T1, class T2, unsigned Dim>
00990 struct PETEBinaryReturn<Tenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
00991   typedef Vektor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
00992 };
00993 
00994 template<class T1, class T2, unsigned Dim>
00995 struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>,FnDotDot> {
00996   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
00997 };
00998 
00999 // Involving SymTenzors, possibly combined with Tenzors:
01000 
01001 template<class T1, class T2, unsigned Dim>
01002 struct PETEBinaryReturn<SymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> {
01003   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> 
01004     type;
01005 };
01006 
01007 template<class T1, class T2, unsigned Dim>
01008 struct PETEBinaryReturn<SymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot> {
01009   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01010 };
01011 
01012 template<class T1, class T2, unsigned Dim>
01013 struct PETEBinaryReturn<Vektor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> {
01014   typedef Vektor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01015 };
01016 
01017 template<class T1, class T2, unsigned Dim>
01018 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
01019   typedef Vektor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01020 };
01021 
01022 template<class T1, class T2, unsigned Dim>
01023 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpAdd> {
01024   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type;
01025 };
01026 
01027 template<class T1, class T2, unsigned Dim>
01028 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpSubtract> {
01029   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type;
01030 };
01031 
01032 template<class T1, class T2, unsigned Dim>
01033 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpMultipply> {
01034   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01035 };
01036 
01037 template<class T1, class T2, unsigned Dim>
01038 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> {
01039   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01040 };
01041 
01042 template<class T1, class T2, unsigned Dim>
01043 struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot> {
01044   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01045 };
01046 
01047 template<class T1, class T2, unsigned Dim>
01048 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpAdd> {
01049   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type;
01050 };
01051 
01052 template<class T1, class T2, unsigned Dim>
01053 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpSubtract> {
01054   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type;
01055 };
01056 
01057 template<class T1, class T2, unsigned Dim>
01058 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDot> {
01059   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01060 };
01061 
01062 template<class T1, class T2, unsigned Dim>
01063 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDotDot> {
01064   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01065 };
01066 
01067 // Involving AntiSymTenzors, possibly combined with Tenzors or SymTenzors:
01068 
01069 template<class T1, class T2, unsigned Dim>
01070 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot> {
01071   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> 
01072     type;
01073 };
01074 
01075 template<class T1, class T2, unsigned Dim>
01076 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot>
01077 {
01078   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01079 };
01080 
01081 template<class T1, class T2, unsigned Dim>
01082 struct PETEBinaryReturn<Vektor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot> {
01083   typedef Vektor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01084 };
01085 
01086 template<class T1, class T2, unsigned Dim>
01087 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> {
01088   typedef Vektor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01089 };
01090 
01091 template<class T1, class T2, unsigned Dim>
01092 struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpAdd> {
01093   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type;
01094 };
01095 
01096 template<class T1, class T2, unsigned Dim>
01097 struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpSubtract> {
01098   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type;
01099 };
01100 
01101 template<class T1, class T2, unsigned Dim>
01102 struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpMultipply> {
01103   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01104 };
01105 
01106 template<class T1, class T2, unsigned Dim>
01107 struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot> {
01108   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01109 };
01110 
01111 template<class T1, class T2, unsigned Dim>
01112 struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot> {
01113   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01114 };
01115 
01116 template<class T1, class T2, unsigned Dim>
01117 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpAdd> {
01118   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type;
01119 };
01120 
01121 template<class T1, class T2, unsigned Dim>
01122 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpSubtract> {
01123   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type;
01124 };
01125 
01126 template<class T1, class T2, unsigned Dim>
01127 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDot> {
01128   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01129 };
01130 
01131 template<class T1, class T2, unsigned Dim>
01132 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDotDot> {
01133   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01134 };
01135 
01136 template<class T1, class T2, unsigned Dim>
01137 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpAdd> {
01138   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type;
01139 };
01140 
01141 template<class T1, class T2, unsigned Dim>
01142 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpSubtract> {
01143   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type;
01144 };
01145 
01146 template<class T1, class T2, unsigned Dim>
01147 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpMultipply> {
01148   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01149 };
01150 
01151 template<class T1, class T2, unsigned Dim>
01152 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot> {
01153   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01154 };
01155 
01156 template<class T1, class T2, unsigned Dim>
01157 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot> {
01158   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01159 };
01160 
01161 template<class T1, class T2, unsigned Dim>
01162 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,OpAdd> {
01163   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type;
01164 };
01165 
01166 template<class T1, class T2, unsigned Dim>
01167 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,OpSubtract> {
01168   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type;
01169 };
01170 
01171 template<class T1, class T2, unsigned Dim>
01172 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,FnDot> {
01173   typedef Tenzor<typename PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type;
01174 };
01175 
01176 template<class T1, class T2, unsigned Dim>
01177 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,FnDotDot> {
01178   typedef typename PETEBinaryReturn<T1,T2,OpMultipply>::type type;
01179 };
01180 
01181 // Need to specify scalar operations directly.
01182 
01183 #define _SCALAR_VST_RETURNS_(Sca)                                           \
01184 template<class T1, unsigned Dim>                                            \
01185 struct PETEBinaryReturn<Vektor<T1,Dim>,Sca,OpMultipply> {                    \
01186   typedef Vektor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim>    \
01187     type;                                                                   \
01188 };                                                                          \
01189 template<class T2, unsigned Dim>                                            \
01190 struct PETEBinaryReturn<Sca,Vektor<T2,Dim>,OpMultipply> {                    \
01191   typedef Vektor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim>    \
01192     type;                                                                   \
01193 };                                                                          \
01194 template<class T1, unsigned Dim>                                            \
01195 struct PETEBinaryReturn<Vektor<T1,Dim>,Sca,OpDivide> {                      \
01196   typedef Vektor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim>      \
01197     type;                                                                   \
01198 };                                                                          \
01199 template<class T1, unsigned Dim>                                            \
01200 struct PETEBinaryReturn<Tenzor<T1,Dim>,Sca,OpMultipply> {                    \
01201   typedef Tenzor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim>    \
01202     type;                                                                   \
01203 };                                                                          \
01204 template<class T2, unsigned Dim>                                            \
01205 struct PETEBinaryReturn<Sca,Tenzor<T2,Dim>,OpMultipply> {                    \
01206   typedef Tenzor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim>    \
01207     type;                                                                   \
01208 };                                                                          \
01209 template<class T1, unsigned Dim>                                            \
01210 struct PETEBinaryReturn<Tenzor<T1,Dim>,Sca,OpDivide> {                      \
01211   typedef Tenzor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim>      \
01212     type;                                                                   \
01213 };                                                                          \
01214 template<class T1, unsigned Dim>                                            \
01215 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Sca,OpMultipply> {                 \
01216   typedef SymTenzor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim> \
01217     type;                                                                   \
01218 };                                                                          \
01219 template<class T2, unsigned Dim>                                            \
01220 struct PETEBinaryReturn<Sca,SymTenzor<T2,Dim>,OpMultipply> {                 \
01221   typedef SymTenzor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim> \
01222     type;                                                                   \
01223 };                                                                          \
01224 template<class T1, unsigned Dim>                                            \
01225 struct PETEBinaryReturn<SymTenzor<T1,Dim>,Sca,OpDivide> {                   \
01226   typedef SymTenzor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim>   \
01227     type;                                                                   \
01228 };                                                                          \
01229 template<class T1, unsigned Dim>                                            \
01230 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Sca,OpMultipply> {             \
01231   typedef                                                                   \
01232   AntiSymTenzor<typename PETEBinaryReturn<T1,Sca,OpMultipply>::type,Dim>     \
01233     type;                                                                   \
01234 };                                                                          \
01235 template<class T2, unsigned Dim>                                            \
01236 struct PETEBinaryReturn<Sca,AntiSymTenzor<T2,Dim>,OpMultipply> {             \
01237   typedef                                                                   \
01238   AntiSymTenzor<typename PETEBinaryReturn<Sca,T2,OpMultipply>::type,Dim>     \
01239     type;                                                                   \
01240 };                                                                          \
01241 template<class T1, unsigned Dim>                                            \
01242 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Sca,OpDivide> {               \
01243   typedef                                                                   \
01244   AntiSymTenzor<typename PETEBinaryReturn<T1,Sca,OpDivide>::type,Dim>       \
01245     type;                                                                   \
01246 };
01247 
01248 _SCALAR_VST_RETURNS_(short)
01249 _SCALAR_VST_RETURNS_(int)
01250 _SCALAR_VST_RETURNS_(long)
01251 _SCALAR_VST_RETURNS_(float)
01252 _SCALAR_VST_RETURNS_(double)
01253 _SCALAR_VST_RETURNS_(dcomplex)
01254 
01255 #undef _SCALAR_VST_RETURNS_
01256 
01257 #else
01258 
01259 // Without partial specialization, we must list all the possibilities.
01260 // Life is too short to type all this stuff out, so we use macros.
01261 
01262 #define _VEKTOR_RETURNS_(T1,T2,Dim)                                         \
01263 template<> struct                                                           \
01264   PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>, FnOuterProduct>           \
01265   { typedef Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim>            \
01266     type; };                                                                \
01267 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>,FnDot>     \
01268   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };              \
01269 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,T2,OpMultipply>           \
01270   { typedef Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim>            \
01271     type; };                                                                \
01272 template<> struct PETEBinaryReturn<T2,Vektor<T1,Dim>,OpMultipply>           \
01273   { typedef Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim>            \
01274     type; };                                                                \
01275 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,T2,OpDivide>              \
01276   { typedef Vektor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim>              \
01277     type; };                                                                \
01278 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,Vektor<T2,Dim>,FnCross>   \
01279   { typedef Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };
01280 
01281 _VEKTOR_RETURNS_(short,short,1U)
01282 _VEKTOR_RETURNS_(int,int,1U)
01283 _VEKTOR_RETURNS_(long,long,1U)
01284 _VEKTOR_RETURNS_(float,float,1U)
01285 _VEKTOR_RETURNS_(double,double,1U)
01286 _VEKTOR_RETURNS_(dcomplex,dcomplex,1U)
01287 _VEKTOR_RETURNS_(int,short,1U)
01288 _VEKTOR_RETURNS_(long,short,1U)
01289 _VEKTOR_RETURNS_(long,int,1U)
01290 _VEKTOR_RETURNS_(float,short,1U)
01291 _VEKTOR_RETURNS_(float,int,1U)
01292 _VEKTOR_RETURNS_(float,long,1U)
01293 _VEKTOR_RETURNS_(double,short,1U)
01294 _VEKTOR_RETURNS_(double,int,1U)
01295 _VEKTOR_RETURNS_(double,long,1U)
01296 _VEKTOR_RETURNS_(double,float,1U)
01297 _VEKTOR_RETURNS_(dcomplex,short,1U)
01298 _VEKTOR_RETURNS_(dcomplex,int,1U)
01299 _VEKTOR_RETURNS_(dcomplex,long,1U)
01300 _VEKTOR_RETURNS_(dcomplex,float,1U)
01301 _VEKTOR_RETURNS_(dcomplex,double,1U)
01302 
01303 _VEKTOR_RETURNS_(short,short,2U)
01304 _VEKTOR_RETURNS_(int,int,2U)
01305 _VEKTOR_RETURNS_(long,long,2U)
01306 _VEKTOR_RETURNS_(float,float,2U)
01307 _VEKTOR_RETURNS_(double,double,2U)
01308 _VEKTOR_RETURNS_(dcomplex,dcomplex,2U)
01309 _VEKTOR_RETURNS_(int,short,2U)
01310 _VEKTOR_RETURNS_(long,short,2U)
01311 _VEKTOR_RETURNS_(long,int,2U)
01312 _VEKTOR_RETURNS_(float,short,2U)
01313 _VEKTOR_RETURNS_(float,int,2U)
01314 _VEKTOR_RETURNS_(float,long,2U)
01315 _VEKTOR_RETURNS_(double,short,2U)
01316 _VEKTOR_RETURNS_(double,int,2U)
01317 _VEKTOR_RETURNS_(double,long,2U)
01318 _VEKTOR_RETURNS_(double,float,2U)
01319 _VEKTOR_RETURNS_(dcomplex,short,2U)
01320 _VEKTOR_RETURNS_(dcomplex,int,2U)
01321 _VEKTOR_RETURNS_(dcomplex,long,2U)
01322 _VEKTOR_RETURNS_(dcomplex,float,2U)
01323 _VEKTOR_RETURNS_(dcomplex,double,2U)
01324 
01325 _VEKTOR_RETURNS_(short,short,3U)
01326 _VEKTOR_RETURNS_(int,int,3U)
01327 _VEKTOR_RETURNS_(long,long,3U)
01328 _VEKTOR_RETURNS_(float,float,3U)
01329 _VEKTOR_RETURNS_(double,double,3U)
01330 _VEKTOR_RETURNS_(dcomplex,dcomplex,3U)
01331 _VEKTOR_RETURNS_(int,short,3U)
01332 _VEKTOR_RETURNS_(long,short,3U)
01333 _VEKTOR_RETURNS_(long,int,3U)
01334 _VEKTOR_RETURNS_(float,short,3U)
01335 _VEKTOR_RETURNS_(float,int,3U)
01336 _VEKTOR_RETURNS_(float,long,3U)
01337 _VEKTOR_RETURNS_(double,short,3U)
01338 _VEKTOR_RETURNS_(double,int,3U)
01339 _VEKTOR_RETURNS_(double,long,3U)
01340 _VEKTOR_RETURNS_(double,float,3U)
01341 _VEKTOR_RETURNS_(dcomplex,short,3U)
01342 _VEKTOR_RETURNS_(dcomplex,int,3U)
01343 _VEKTOR_RETURNS_(dcomplex,long,3U)
01344 _VEKTOR_RETURNS_(dcomplex,float,3U)
01345 _VEKTOR_RETURNS_(dcomplex,double,3U)
01346 
01347 #undef _VEKTOR_RETURNS_
01348 
01349 #define _TENZOR_RETURNS_(T1,T2,Dim)                                         \
01350 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>, FnDot>    \
01351   { typedef                                                                 \
01352     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01353 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,Tenzor<T2,Dim>, FnDotDot> \
01354   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };              \
01355 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,Tenzor<T2,Dim>, FnDot>    \
01356   { typedef                                                                 \
01357     Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01358 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,Vektor<T2,Dim>, FnDot>    \
01359   { typedef                                                                 \
01360     Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01361 template<> struct PETEBinaryReturn<T1,Tenzor<T2,Dim>,OpMultipply>           \
01362   { typedef                                                                 \
01363     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01364 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,T2,OpMultipply>           \
01365   { typedef                                                                 \
01366     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01367 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,T2,OpDivide>              \
01368   { typedef                                                                 \
01369     Tenzor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim> type; };
01370 
01371 _TENZOR_RETURNS_(short,short,1U)
01372 _TENZOR_RETURNS_(int,int,1U)
01373 _TENZOR_RETURNS_(long,long,1U)
01374 _TENZOR_RETURNS_(float,float,1U)
01375 _TENZOR_RETURNS_(double,double,1U)
01376 _TENZOR_RETURNS_(dcomplex,dcomplex,1U)
01377 _TENZOR_RETURNS_(int,short,1U)
01378 _TENZOR_RETURNS_(long,short,1U)
01379 _TENZOR_RETURNS_(long,int,1U)
01380 _TENZOR_RETURNS_(float,short,1U)
01381 _TENZOR_RETURNS_(float,int,1U)
01382 _TENZOR_RETURNS_(float,long,1U)
01383 _TENZOR_RETURNS_(double,short,1U)
01384 _TENZOR_RETURNS_(double,int,1U)
01385 _TENZOR_RETURNS_(double,long,1U)
01386 _TENZOR_RETURNS_(double,float,1U)
01387 _TENZOR_RETURNS_(dcomplex,short,1U)
01388 _TENZOR_RETURNS_(dcomplex,int,1U)
01389 _TENZOR_RETURNS_(dcomplex,long,1U)
01390 _TENZOR_RETURNS_(dcomplex,float,1U)
01391 _TENZOR_RETURNS_(dcomplex,double,1U)
01392 
01393 _TENZOR_RETURNS_(short,short,2U)
01394 _TENZOR_RETURNS_(int,int,2U)
01395 _TENZOR_RETURNS_(long,long,2U)
01396 _TENZOR_RETURNS_(float,float,2U)
01397 _TENZOR_RETURNS_(double,double,2U)
01398 _TENZOR_RETURNS_(dcomplex,dcomplex,2U)
01399 _TENZOR_RETURNS_(int,short,2U)
01400 _TENZOR_RETURNS_(long,short,2U)
01401 _TENZOR_RETURNS_(long,int,2U)
01402 _TENZOR_RETURNS_(float,short,2U)
01403 _TENZOR_RETURNS_(float,int,2U)
01404 _TENZOR_RETURNS_(float,long,2U)
01405 _TENZOR_RETURNS_(double,short,2U)
01406 _TENZOR_RETURNS_(double,int,2U)
01407 _TENZOR_RETURNS_(double,long,2U)
01408 _TENZOR_RETURNS_(double,float,2U)
01409 _TENZOR_RETURNS_(dcomplex,short,2U)
01410 _TENZOR_RETURNS_(dcomplex,int,2U)
01411 _TENZOR_RETURNS_(dcomplex,long,2U)
01412 _TENZOR_RETURNS_(dcomplex,float,2U)
01413 _TENZOR_RETURNS_(dcomplex,double,2U)
01414 
01415 _TENZOR_RETURNS_(short,short,3U)
01416 _TENZOR_RETURNS_(int,int,3U)
01417 _TENZOR_RETURNS_(long,long,3U)
01418 _TENZOR_RETURNS_(float,float,3U)
01419 _TENZOR_RETURNS_(double,double,3U)
01420 _TENZOR_RETURNS_(dcomplex,dcomplex,3U)
01421 _TENZOR_RETURNS_(int,short,3U)
01422 _TENZOR_RETURNS_(long,short,3U)
01423 _TENZOR_RETURNS_(long,int,3U)
01424 _TENZOR_RETURNS_(float,short,3U)
01425 _TENZOR_RETURNS_(float,int,3U)
01426 _TENZOR_RETURNS_(float,long,3U)
01427 _TENZOR_RETURNS_(double,short,3U)
01428 _TENZOR_RETURNS_(double,int,3U)
01429 _TENZOR_RETURNS_(double,long,3U)
01430 _TENZOR_RETURNS_(double,float,3U)
01431 _TENZOR_RETURNS_(dcomplex,short,3U)
01432 _TENZOR_RETURNS_(dcomplex,int,3U)
01433 _TENZOR_RETURNS_(dcomplex,long,3U)
01434 _TENZOR_RETURNS_(dcomplex,float,3U)
01435 _TENZOR_RETURNS_(dcomplex,double,3U)
01436 
01437 #undef _TENZOR_RETURNS_
01438 
01439 
01440 #define _SYMTENZOR_RETURNS_(T1,T2,Dim)                                      \
01441 template<> struct                                                           \
01442   PETEBinaryReturn<SymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot>              \
01443   { typedef                                                                 \
01444       Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };         \
01445 template<> struct                                                           \
01446   PETEBinaryReturn<SymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot>           \
01447   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };              \
01448 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> \
01449   { typedef                                                                 \
01450     Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01451 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,Vektor<T2,Dim>, FnDot> \
01452   { typedef                                                                 \
01453     Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01454 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpAdd>  \
01455   { typedef                                                                 \
01456     Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; };                \
01457 template<> struct                                                           \
01458   PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpSubtract>             \
01459   { typedef                                                                 \
01460     Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; };           \
01461 template<> struct                                                           \
01462   PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>,OpMultipply>                    \
01463   { typedef                                                                 \
01464     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01465 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDot> \
01466   { typedef                                                                 \
01467     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01468 template<> struct                                                           \
01469   PETEBinaryReturn<Tenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot>              \
01470   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };              \
01471 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpAdd>  \
01472   { typedef                                                                 \
01473     Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; };                \
01474 template<> struct                                                           \
01475   PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpSubtract>             \
01476   { typedef                                                                 \
01477     Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; };           \
01478 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>, FnDot> \
01479   { typedef                                                                 \
01480     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01481 template<> struct                                                           \
01482   PETEBinaryReturn<SymTenzor<T1,Dim>,Tenzor<T2,Dim>, FnDotDot>              \
01483   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };              \
01484 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,T2,OpMultipply>        \
01485   { typedef                                                                 \
01486       SymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };      \
01487 template<> struct PETEBinaryReturn<T1,SymTenzor<T2,Dim>,OpMultipply>        \
01488   { typedef                                                                 \
01489       SymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim>               \
01490       type; };                                                              \
01491 template<> struct PETEBinaryReturn<SymTenzor<T1,Dim>,T2,OpDivide>           \
01492   { typedef SymTenzor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim> type; };
01493 
01494 _SYMTENZOR_RETURNS_(short,short,1U)
01495 _SYMTENZOR_RETURNS_(int,int,1U)
01496 _SYMTENZOR_RETURNS_(long,long,1U)
01497 _SYMTENZOR_RETURNS_(float,float,1U)
01498 _SYMTENZOR_RETURNS_(double,double,1U)
01499 _SYMTENZOR_RETURNS_(dcomplex,dcomplex,1U)
01500 _SYMTENZOR_RETURNS_(int,short,1U)
01501 _SYMTENZOR_RETURNS_(long,short,1U)
01502 _SYMTENZOR_RETURNS_(long,int,1U)
01503 _SYMTENZOR_RETURNS_(float,short,1U)
01504 _SYMTENZOR_RETURNS_(float,int,1U)
01505 _SYMTENZOR_RETURNS_(float,long,1U)
01506 _SYMTENZOR_RETURNS_(double,short,1U)
01507 _SYMTENZOR_RETURNS_(double,int,1U)
01508 _SYMTENZOR_RETURNS_(double,long,1U)
01509 _SYMTENZOR_RETURNS_(double,float,1U)
01510 _SYMTENZOR_RETURNS_(dcomplex,short,1U)
01511 _SYMTENZOR_RETURNS_(dcomplex,int,1U)
01512 _SYMTENZOR_RETURNS_(dcomplex,long,1U)
01513 _SYMTENZOR_RETURNS_(dcomplex,float,1U)
01514 _SYMTENZOR_RETURNS_(dcomplex,double,1U)
01515 
01516 _SYMTENZOR_RETURNS_(short,short,2U)
01517 _SYMTENZOR_RETURNS_(int,int,2U)
01518 _SYMTENZOR_RETURNS_(long,long,2U)
01519 _SYMTENZOR_RETURNS_(float,float,2U)
01520 _SYMTENZOR_RETURNS_(double,double,2U)
01521 _SYMTENZOR_RETURNS_(dcomplex,dcomplex,2U)
01522 _SYMTENZOR_RETURNS_(int,short,2U)
01523 _SYMTENZOR_RETURNS_(long,short,2U)
01524 _SYMTENZOR_RETURNS_(long,int,2U)
01525 _SYMTENZOR_RETURNS_(float,short,2U)
01526 _SYMTENZOR_RETURNS_(float,int,2U)
01527 _SYMTENZOR_RETURNS_(float,long,2U)
01528 _SYMTENZOR_RETURNS_(double,short,2U)
01529 _SYMTENZOR_RETURNS_(double,int,2U)
01530 _SYMTENZOR_RETURNS_(double,long,2U)
01531 _SYMTENZOR_RETURNS_(double,float,2U)
01532 _SYMTENZOR_RETURNS_(dcomplex,short,2U)
01533 _SYMTENZOR_RETURNS_(dcomplex,int,2U)
01534 _SYMTENZOR_RETURNS_(dcomplex,long,2U)
01535 _SYMTENZOR_RETURNS_(dcomplex,float,2U)
01536 _SYMTENZOR_RETURNS_(dcomplex,double,2U)
01537 
01538 _SYMTENZOR_RETURNS_(short,short,3U)
01539 _SYMTENZOR_RETURNS_(int,int,3U)
01540 _SYMTENZOR_RETURNS_(long,long,3U)
01541 _SYMTENZOR_RETURNS_(float,float,3U)
01542 _SYMTENZOR_RETURNS_(double,double,3U)
01543 _SYMTENZOR_RETURNS_(dcomplex,dcomplex,3U)
01544 _SYMTENZOR_RETURNS_(int,short,3U)
01545 _SYMTENZOR_RETURNS_(long,short,3U)
01546 _SYMTENZOR_RETURNS_(long,int,3U)
01547 _SYMTENZOR_RETURNS_(float,short,3U)
01548 _SYMTENZOR_RETURNS_(float,int,3U)
01549 _SYMTENZOR_RETURNS_(float,long,3U)
01550 _SYMTENZOR_RETURNS_(double,short,3U)
01551 _SYMTENZOR_RETURNS_(double,int,3U)
01552 _SYMTENZOR_RETURNS_(double,long,3U)
01553 _SYMTENZOR_RETURNS_(double,float,3U)
01554 _SYMTENZOR_RETURNS_(dcomplex,short,3U)
01555 _SYMTENZOR_RETURNS_(dcomplex,int,3U)
01556 _SYMTENZOR_RETURNS_(dcomplex,long,3U)
01557 _SYMTENZOR_RETURNS_(dcomplex,float,3U)
01558 _SYMTENZOR_RETURNS_(dcomplex,double,3U)
01559 
01560 #undef _SYMTENZOR_RETURNS_
01561 
01562 
01563 #define _ANTISYMTENZOR_RETURNS_(T1,T2,Dim)                                    \
01564 template<> struct                                                             \
01565   PETEBinaryReturn<AntiSymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDot>        \
01566   { typedef                                                                   \
01567       Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };           \
01568 template<> struct                                                             \
01569   PETEBinaryReturn<AntiSymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot>     \
01570   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };                \
01571 template<> struct PETEBinaryReturn<Vektor<T1,Dim>,AntiSymTenzor<T2,Dim>,FnDot>\
01572   { typedef                                                                   \
01573     Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01574 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Vektor<T2,Dim>,FnDot>\
01575   { typedef                                                                   \
01576     Vektor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01577 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpAdd>\
01578   { typedef                                                                   \
01579     Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; };                  \
01580 template<> struct                                                             \
01581   PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpSubtract>           \
01582   { typedef                                                                   \
01583     Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; };             \
01584 template<> struct                                                             \
01585   PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpMultipply>          \
01586   { typedef                                                                   \
01587     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01588 template<> struct PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,FnDot>\
01589   { typedef                                                                   \
01590     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01591 template<> struct                                                             \
01592   PETEBinaryReturn<Tenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot>            \
01593   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };                \
01594 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpAdd>\
01595   { typedef                                                                   \
01596     Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; };                  \
01597 template<> struct                                                             \
01598   PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,OpSubtract>           \
01599   { typedef                                                                   \
01600     Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; };             \
01601 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>,FnDot>\
01602   { typedef                                                                   \
01603     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01604 template<> struct                                                             \
01605   PETEBinaryReturn<AntiSymTenzor<T1,Dim>,Tenzor<T2,Dim>, FnDotDot>            \
01606   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };                \
01607 template<>                                                                    \
01608 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpAdd>        \
01609   { typedef                                                                   \
01610     Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; };                  \
01611 template<> struct                                                             \
01612   PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpSubtract>        \
01613   { typedef                                                                   \
01614     Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; };             \
01615 template<> struct                                                             \
01616   PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,OpMultipply>       \
01617   { typedef                                                                   \
01618     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01619 template<>                                                                    \
01620 struct PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>,FnDot>        \
01621   { typedef                                                                   \
01622     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01623 template<> struct                                                             \
01624   PETEBinaryReturn<SymTenzor<T1,Dim>,AntiSymTenzor<T2,Dim>, FnDotDot>         \
01625   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };                \
01626 template<>                                                                    \
01627 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,OpAdd>        \
01628   { typedef                                                                   \
01629     Tenzor<PETEBinaryReturn<T1,T2,OpAdd>::type,Dim> type; };                  \
01630 template<> struct                                                             \
01631   PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,OpSubtract>        \
01632   { typedef                                                                   \
01633     Tenzor<PETEBinaryReturn<T1,T2,OpSubtract>::type,Dim> type; };             \
01634 template<>                                                                    \
01635 struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>,FnDot>        \
01636   { typedef                                                                   \
01637     Tenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };             \
01638 template<> struct                                                             \
01639   PETEBinaryReturn<AntiSymTenzor<T1,Dim>,SymTenzor<T2,Dim>, FnDotDot>         \
01640   { typedef PETEBinaryReturn<T1,T2,OpMultipply>::type type; };                \
01641 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,T2,OpMultipply>              \
01642   { typedef                                                                   \
01643       AntiSymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim> type; };    \
01644 template<> struct PETEBinaryReturn<T1,AntiSymTenzor<T2,Dim>,OpMultipply>              \
01645   { typedef                                                                   \
01646       AntiSymTenzor<PETEBinaryReturn<T1,T2,OpMultipply>::type,Dim>             \
01647       type; };                                                                \
01648 template<> struct PETEBinaryReturn<AntiSymTenzor<T1,Dim>,T2,OpDivide>         \
01649   { typedef AntiSymTenzor<PETEBinaryReturn<T1,T2,OpDivide>::type,Dim> type; };
01650 
01651 _ANTISYMTENZOR_RETURNS_(short,short,1U)
01652 _ANTISYMTENZOR_RETURNS_(int,int,1U)
01653 _ANTISYMTENZOR_RETURNS_(long,long,1U)
01654 _ANTISYMTENZOR_RETURNS_(float,float,1U)
01655 _ANTISYMTENZOR_RETURNS_(double,double,1U)
01656 _ANTISYMTENZOR_RETURNS_(dcomplex,dcomplex,1U)
01657 _ANTISYMTENZOR_RETURNS_(int,short,1U)
01658 _ANTISYMTENZOR_RETURNS_(long,short,1U)
01659 _ANTISYMTENZOR_RETURNS_(long,int,1U)
01660 _ANTISYMTENZOR_RETURNS_(float,short,1U)
01661 _ANTISYMTENZOR_RETURNS_(float,int,1U)
01662 _ANTISYMTENZOR_RETURNS_(float,long,1U)
01663 _ANTISYMTENZOR_RETURNS_(double,short,1U)
01664 _ANTISYMTENZOR_RETURNS_(double,int,1U)
01665 _ANTISYMTENZOR_RETURNS_(double,long,1U)
01666 _ANTISYMTENZOR_RETURNS_(double,float,1U)
01667 _ANTISYMTENZOR_RETURNS_(dcomplex,short,1U)
01668 _ANTISYMTENZOR_RETURNS_(dcomplex,int,1U)
01669 _ANTISYMTENZOR_RETURNS_(dcomplex,long,1U)
01670 _ANTISYMTENZOR_RETURNS_(dcomplex,float,1U)
01671 _ANTISYMTENZOR_RETURNS_(dcomplex,double,1U)
01672 
01673 _ANTISYMTENZOR_RETURNS_(short,short,2U)
01674 _ANTISYMTENZOR_RETURNS_(int,int,2U)
01675 _ANTISYMTENZOR_RETURNS_(long,long,2U)
01676 _ANTISYMTENZOR_RETURNS_(float,float,2U)
01677 _ANTISYMTENZOR_RETURNS_(double,double,2U)
01678 _ANTISYMTENZOR_RETURNS_(dcomplex,dcomplex,2U)
01679 _ANTISYMTENZOR_RETURNS_(int,short,2U)
01680 _ANTISYMTENZOR_RETURNS_(long,short,2U)
01681 _ANTISYMTENZOR_RETURNS_(long,int,2U)
01682 _ANTISYMTENZOR_RETURNS_(float,short,2U)
01683 _ANTISYMTENZOR_RETURNS_(float,int,2U)
01684 _ANTISYMTENZOR_RETURNS_(float,long,2U)
01685 _ANTISYMTENZOR_RETURNS_(double,short,2U)
01686 _ANTISYMTENZOR_RETURNS_(double,int,2U)
01687 _ANTISYMTENZOR_RETURNS_(double,long,2U)
01688 _ANTISYMTENZOR_RETURNS_(double,float,2U)
01689 _ANTISYMTENZOR_RETURNS_(dcomplex,short,2U)
01690 _ANTISYMTENZOR_RETURNS_(dcomplex,int,2U)
01691 _ANTISYMTENZOR_RETURNS_(dcomplex,long,2U)
01692 _ANTISYMTENZOR_RETURNS_(dcomplex,float,2U)
01693 _ANTISYMTENZOR_RETURNS_(dcomplex,double,2U)
01694 
01695 _ANTISYMTENZOR_RETURNS_(short,short,3U)
01696 _ANTISYMTENZOR_RETURNS_(int,int,3U)
01697 _ANTISYMTENZOR_RETURNS_(long,long,3U)
01698 _ANTISYMTENZOR_RETURNS_(float,float,3U)
01699 _ANTISYMTENZOR_RETURNS_(double,double,3U)
01700 _ANTISYMTENZOR_RETURNS_(dcomplex,dcomplex,3U)
01701 _ANTISYMTENZOR_RETURNS_(int,short,3U)
01702 _ANTISYMTENZOR_RETURNS_(long,short,3U)
01703 _ANTISYMTENZOR_RETURNS_(long,int,3U)
01704 _ANTISYMTENZOR_RETURNS_(float,short,3U)
01705 _ANTISYMTENZOR_RETURNS_(float,int,3U)
01706 _ANTISYMTENZOR_RETURNS_(float,long,3U)
01707 _ANTISYMTENZOR_RETURNS_(double,short,3U)
01708 _ANTISYMTENZOR_RETURNS_(double,int,3U)
01709 _ANTISYMTENZOR_RETURNS_(double,long,3U)
01710 _ANTISYMTENZOR_RETURNS_(double,float,3U)
01711 _ANTISYMTENZOR_RETURNS_(dcomplex,short,3U)
01712 _ANTISYMTENZOR_RETURNS_(dcomplex,int,3U)
01713 _ANTISYMTENZOR_RETURNS_(dcomplex,long,3U)
01714 _ANTISYMTENZOR_RETURNS_(dcomplex,float,3U)
01715 _ANTISYMTENZOR_RETURNS_(dcomplex,double,3U)
01716 
01717 #undef _SYMTENZOR_RETURNS_
01718 
01719 
01720 #endif
01721 
01722 
01724 //
01725 // ASSIGNMENT OPERATORS: min=, max=, &&=, ||=
01726 //
01728 
01729 struct OpMinAssign {
01730 #ifdef IPPL_PURIFY
01731   OpMinAssign() {}
01732   OpMinAssign(const OpMinAssign &) {}
01733   OpMinAssign& operator=(const OpMinAssign &) { return *this; }
01734 #endif
01735   enum { tag = PETE_BinaryUseLeftTag };
01736 };
01737 
01738 struct OpMaxAssign {
01739 #ifdef IPPL_PURIFY
01740   OpMaxAssign() {}
01741   OpMaxAssign(const OpMaxAssign &) {}
01742   OpMaxAssign& operator=(const OpMaxAssign &) { return *this; }
01743 #endif
01744   enum { tag = PETE_BinaryUseLeftTag };
01745 };
01746 
01747 struct OpAndAssign {
01748 #ifdef IPPL_PURIFY
01749   OpAndAssign() {}
01750   OpAndAssign(const OpAndAssign &) {}
01751   OpAndAssign& operator=(const OpAndAssign &) { return *this; }
01752 #endif
01753   enum { tag = PETE_BinaryUseLeftTag };
01754 };
01755 
01756 struct OpOrAssign {
01757 #ifdef IPPL_PURIFY
01758   OpOrAssign() {}
01759   OpOrAssign(const OpOrAssign &) {}
01760   OpOrAssign& operator=(const OpOrAssign &) { return *this; }
01761 #endif
01762   enum { tag = PETE_BinaryUseLeftTag };
01763 };
01764 
01765 
01767 //
01768 // OPERATOR()
01769 //
01771 
01772 #if defined(IPPL_USE_PARTIAL_SPECIALIZATION)
01773 
01774 template<class T, class TP, unsigned Dim>
01775 struct PETEUnaryReturn< Vektor<T, Dim>, OpParens<TP> > {
01776   typedef T type;
01777 };
01778 
01779 template<class T, class TP, unsigned Dim>
01780 struct PETEUnaryReturn< AntiSymTenzor<T, Dim>, OpParens<TP> > {
01781   typedef T type;
01782 };
01783 
01784 template<class T, class TP, unsigned Dim>
01785 struct PETEUnaryReturn< SymTenzor<T, Dim>, OpParens<TP> > {
01786   typedef T type;
01787 };
01788 
01789 template<class T, class TP, unsigned Dim>
01790 struct PETEUnaryReturn< Tenzor<T, Dim>, OpParens<TP> > {
01791   typedef T type;
01792 };
01793 
01794 #else
01795 
01796 // More Yucko non-partial-specialization stuff...
01797 
01798 #define _PETE_DEFINE_PARENS_RETURNS_(T,D)                                   \
01799 template<> struct PETEUnaryReturn<class Vektor<T,D>,OpParens<int> >         \
01800   { typedef T type; };                                                      \
01801 template<> struct                                                           \
01802   PETEUnaryReturn<class Tenzor<T,D>,OpParens<pair<int,int> > >              \
01803   { typedef T type; };                                                      \
01804 template<> struct                                                           \
01805   PETEUnaryReturn<class AntiSymTenzor<T,D>,OpParens<pair<int,int> > >       \
01806   { typedef T type; };                                                      \
01807 template<> struct                                                           \
01808   PETEUnaryReturn<class SymTenzor<T,D>,OpParens<pair<int,int> > >           \
01809   { typedef T type; };
01810 
01811 _PETE_DEFINE_PARENS_RETURNS_(short,1)
01812 _PETE_DEFINE_PARENS_RETURNS_(short,2)
01813 _PETE_DEFINE_PARENS_RETURNS_(short,3)
01814 _PETE_DEFINE_PARENS_RETURNS_(int,1)
01815 _PETE_DEFINE_PARENS_RETURNS_(int,2)
01816 _PETE_DEFINE_PARENS_RETURNS_(int,3)
01817 _PETE_DEFINE_PARENS_RETURNS_(long,1)
01818 _PETE_DEFINE_PARENS_RETURNS_(long,2)
01819 _PETE_DEFINE_PARENS_RETURNS_(long,3)
01820 _PETE_DEFINE_PARENS_RETURNS_(float,1)
01821 _PETE_DEFINE_PARENS_RETURNS_(float,2)
01822 _PETE_DEFINE_PARENS_RETURNS_(float,3)
01823 _PETE_DEFINE_PARENS_RETURNS_(double,1)
01824 _PETE_DEFINE_PARENS_RETURNS_(double,2)
01825 _PETE_DEFINE_PARENS_RETURNS_(double,3)
01826 _PETE_DEFINE_PARENS_RETURNS_(dcomplex,1)
01827 _PETE_DEFINE_PARENS_RETURNS_(dcomplex,2)
01828 _PETE_DEFINE_PARENS_RETURNS_(dcomplex,3)
01829 
01830 #undef _PETE_DEFINE_PARENS_RETURNS_
01831 
01832 #endif
01833 
01834 
01836 //
01837 // END OF FILE
01838 //
01840 
01841 #endif // IPPL_TYPE_COMPUTATIONS_H
01842 
01843 /***************************************************************************
01844  * $RCSfile: IpplTypeComputations.h,v $   $Author: adelmann $
01845  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:28 $
01846  * IPPL_VERSION_ID: $Id: IpplTypeComputations.h,v 1.1.1.1 2003/01/23 07:40:28 adelmann Exp $ 
01847  ***************************************************************************/

Generated on Mon Jan 16 13:23:54 2006 for IPPL by  doxygen 1.4.6