[cig-commits] commit: Initial import from old ArX repo

Mercurial hg at geodynamics.org
Fri Mar 9 13:24:50 PST 2012


changeset:   0:34fc4fd9248b
user:        Walter Landry <boo at dante>
date:        Sun Dec 13 19:57:42 2009 -0800
files:       FTensor.h FTensor_new.h Index.h LICENSE Layout.h Number.h README Tensor0.h Tensor0/dTensor0.h Tensor0/d_boundary_Tensor0.h Tensor0/d_one_sided_Tensor0.h Tensor0/ddTensor0.h Tensor0/dd_boundary_Tensor0.h Tensor0/diffusion_Tensor0.h Tensor0/interpolate_Tensor0.h Tensor1.h Tensor1/Tensor1_Expr.h Tensor1/Tensor1_Expr_equals.h Tensor1/Tensor1_and_Tensor1.h Tensor1/Tensor1_carat_Tensor1.h Tensor1/Tensor1_constructor.h Tensor1/Tensor1_divide_generic.h Tensor1/Tensor1_minus_Tensor1.h Tensor1/Tensor1_minus_generic.h Tensor1/Tensor1_or_Tensor1.h Tensor1/Tensor1_plus_Tensor1.h Tensor1/Tensor1_plus_generic.h Tensor1/Tensor1_pointer.h Tensor1/Tensor1_times_Tensor1.h Tensor1/Tensor1_times_generic.h Tensor1/Tensor1_value.h Tensor1/dTensor1.h Tensor1/d_one_sided_Tensor1.h Tensor1/ddTensor1.h Tensor1/diffusion_Tensor1.h Tensor1/generic_minus_Tensor1.h Tensor1/interpolate_Tensor1.h Tensor1/minus_Tensor1.h Tensor2.h Tensor2/Tensor2_Expr.h Tensor2/Tensor2_Expr_equals.h Tensor2/Tensor2_and_Tensor1.h Tensor2/Tensor2_carat_Tensor2.h Tensor2/Tensor2_constructor.h Tensor2/Tensor2_divide_generic.h Tensor2/Tensor2_minus_Tensor2.h Tensor2/Tensor2_number.h Tensor2/Tensor2_numeral.h Tensor2/Tensor2_or_Tensor2.h Tensor2/Tensor2_plus_Tensor2.h Tensor2/Tensor2_pointer.h Tensor2/Tensor2_times_Tensor1.h Tensor2/Tensor2_times_Tensor2.h Tensor2/Tensor2_times_generic.h Tensor2/Tensor2_transform.h Tensor2/Tensor2_value.h Tensor2/conj_Tensor2.h Tensor2/minus_Tensor2.h Tensor2_symmetric.h Tensor2_symmetric/Tensor2_symmetric_Expr.h Tensor2_symmetric/Tensor2_symmetric_Expr_equals.h Tensor2_symmetric/Tensor2_symmetric_and_Tensor2_symmetric.h Tensor2_symmetric/Tensor2_symmetric_carat_Tensor2.h Tensor2_symmetric/Tensor2_symmetric_constructor.h Tensor2_symmetric/Tensor2_symmetric_divide_generic.h Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2.h Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2_symmetric.h Tensor2_symmetric/Tensor2_symmetric_minus_generic.h Tensor2_symmetric/Tensor2_symmetric_mod_Tensor2_symmetric.h Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2.h Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2_symmetric.h Tensor2_symmetric/Tensor2_symmetric_plus_generic.h Tensor2_symmetric/Tensor2_symmetric_pointer.h Tensor2_symmetric/Tensor2_symmetric_times_Tensor1.h Tensor2_symmetric/Tensor2_symmetric_times_Tensor2.h Tensor2_symmetric/Tensor2_symmetric_times_Tensor2_symmetric.h Tensor2_symmetric/Tensor2_symmetric_times_generic.h Tensor2_symmetric/Tensor2_symmetric_value.h Tensor2_symmetric/dTensor2_symmetric.h Tensor2_symmetric/d_boundary_Tensor2_symmetric.h Tensor2_symmetric/d_one_sided_Tensor2_symmetric.h Tensor2_symmetric/ddTensor2_symmetric.h Tensor2_symmetric/dd_boundary_Tensor2_symmetric.h Tensor2_symmetric/diffusion_Tensor2_symmetric.h Tensor2_symmetric/generic_minus_Tensor2_symmetric.h Tensor2_symmetric/interpolate_Tensor2_symmetric.h Tensor2_symmetric/minus_Tensor2_symmetric.h Tensor3/Tensor3_Expr.h Tensor3/Tensor3_contracted.h Tensor3/Tensor3_minus_Tensor3_dg.h Tensor3/Tensor3_or_Tensor3.h Tensor3/Tensor3_plus_Tensor3.h Tensor3/Tensor3_times_Tensor1.h Tensor3/Tensor3_times_Tensor2.h Tensor3/Tensor3_times_Tensor2_symmetric.h Tensor3/Tensor3_times_Tensor3.h Tensor3/Tensor3_times_Tensor3_dg.h Tensor3/Tensor3_times_generic.h Tensor3_antisymmetric.h Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.h Tensor3_antisymmetric/Tensor3_antisymmetric_Expr_equals.h Tensor3_antisymmetric/Tensor3_antisymmetric_constructor.h Tensor3_antisymmetric/Tensor3_antisymmetric_mod_Tensor1.h Tensor3_antisymmetric/Tensor3_antisymmetric_or_Tensor3_antisymmetric.h Tensor3_antisymmetric/Tensor3_antisymmetric_plus_Tensor3_antisymmetric.h Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.h Tensor3_antisymmetric/Tensor3_antisymmetric_times_Tensor3.h Tensor3_antisymmetric/Tensor3_antisymmetric_times_generic.h Tensor3_antisymmetric/Tensor3_antisymmetric_value.h Tensor3_christof.h Tensor3_christof/Tensor3_christof_constructor.h Tensor3_christof/Tensor3_christof_number.h Tensor3_christof/Tensor3_christof_numeral.h Tensor3_christof/Tensor3_christof_pointer.h Tensor3_christof/Tensor3_christof_value.h Tensor3_dg.h Tensor3_dg/Tensor3_dg_Expr.h Tensor3_dg/Tensor3_dg_Expr_equals.h Tensor3_dg/Tensor3_dg_and_Tensor1.h Tensor3_dg/Tensor3_dg_and_Tensor2_symmetric.h Tensor3_dg/Tensor3_dg_and_Tensor3_dg.h Tensor3_dg/Tensor3_dg_constructor.h Tensor3_dg/Tensor3_dg_divide_generic.h Tensor3_dg/Tensor3_dg_function_operator.h Tensor3_dg/Tensor3_dg_minus_Tensor3_dg.h Tensor3_dg/Tensor3_dg_number.h Tensor3_dg/Tensor3_dg_numeral.h Tensor3_dg/Tensor3_dg_or_Tensor3_dg.h Tensor3_dg/Tensor3_dg_plus_Tensor3_dg.h Tensor3_dg/Tensor3_dg_pointer.h Tensor3_dg/Tensor3_dg_times_Tensor1.h Tensor3_dg/Tensor3_dg_times_Tensor2.h Tensor3_dg/Tensor3_dg_times_Tensor2_symmetric.h Tensor3_dg/Tensor3_dg_times_Tensor3_dg.h Tensor3_dg/Tensor3_dg_times_generic.h Tensor3_dg/Tensor3_dg_value.h Tensor3_dg/minus_Tensor3_dg.h Tensor4/Tensor4_Expr.h Tensor4/Tensor4_minus_Tensor4.h Tensor4/Tensor4_plus_Tensor4.h Tensor4/Tensor4_times_Tensor2.h Tensor4/Tensor4_times_Tensor2_symmetric.h Tensor4_Riemann.h Tensor4_Riemann/Tensor4_Riemann_Expr.h Tensor4_Riemann/Tensor4_Riemann_minus_Tensor4_Riemann.h Tensor4_Riemann/Tensor4_Riemann_plus_Tensor4_Riemann.h Tensor4_Riemann/Tensor4_Riemann_times_Tensor1.h Tensor4_Riemann/Tensor4_Riemann_times_Tensor2_symmetric.h Tensor4_Riemann/Tensor4_Riemann_times_Tensor4.h Tensor4_Riemann/Tensor4_Riemann_times_Tensor4_ddg.h Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_Expr.h Tensor4_ddg/Tensor4_ddg_Expr_equals.h Tensor4_ddg/Tensor4_ddg_and_Tensor2_symmetric.h Tensor4_ddg/Tensor4_ddg_and_Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_carat_Tensor2_symmetric.h Tensor4_ddg/Tensor4_ddg_carat_Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_minus_Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_mod_Tensor2_symmetric.h Tensor4_ddg/Tensor4_ddg_mod_Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_number.h Tensor4_ddg/Tensor4_ddg_numeral.h Tensor4_ddg/Tensor4_ddg_or_Tensor2_symmetric.h Tensor4_ddg/Tensor4_ddg_or_Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_plus_Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_pointer.h Tensor4_ddg/Tensor4_ddg_times_Tensor1.h Tensor4_ddg/Tensor4_ddg_times_Tensor2.h Tensor4_ddg/Tensor4_ddg_times_Tensor2_symmetric.h Tensor4_ddg/Tensor4_ddg_times_Tensor4_ddg.h Tensor4_ddg/Tensor4_ddg_times_generic.h Tensor4_ddg/Tensor4_ddg_value.h Tensor4_ddg/minus_Tensor4_ddg.h derivative_delta.h promote.h tests/README tests/conformance/Makefile tests/conformance/T2/test_T2.C tests/conformance/T2/test_T2I.C tests/conformance/T2/test_T2II.C tests/conformance/T2/test_T2III.C tests/conformance/T2/test_T2IV.C tests/conformance/T2/test_T2IX.C tests/conformance/T2/test_T2V.C tests/conformance/T2/test_T2VI.C tests/conformance/T2/test_T2VII.C tests/conformance/T2/test_T2VIII.C tests/conformance/T2/test_T2X.C tests/conformance/T2/test_T2XI.C tests/conformance/T2/test_T2XII.C tests/conformance/T2/test_T2XIII.C tests/conformance/T2/test_T2XIV.C tests/conformance/T2/test_T2XIX.C tests/conformance/T2/test_T2XV.C tests/conformance/T2/test_T2XVI.C tests/conformance/T2/test_T2XVII.C tests/conformance/T2/test_T2XVIII.C tests/conformance/T2/test_T2XX.C tests/conformance/T2/test_T2XXI.C tests/conformance/T2/test_T2XXII.C tests/conformance/T2/test_T2XXIII.C tests/conformance/T2/test_T2XXIV.C tests/conformance/T2/test_T2XXIX.C tests/conformance/T2/test_T2XXV.C tests/conformance/T2/test_T2XXVI.C tests/conformance/T2/test_T2XXVII.C tests/conformance/T2/test_T2XXVIII.C tests/conformance/T2/test_T2XXX.C tests/conformance/T2/test_T2XXXI.C tests/conformance/T2/test_T2XXXII.C tests/conformance/T2/test_T2XXXIII.C tests/conformance/T2/test_T2XXXIV.C tests/conformance/T2/test_T2XXXV.C tests/conformance/T2/test_T2XXXVI.C tests/conformance/T2/test_T2XXXVII.C tests/conformance/T2/test_T2XXXVIII.C tests/conformance/T2s/test_T2s.C tests/conformance/T2s/test_T2sI.C tests/conformance/T2s/test_T2sII.C tests/conformance/T2s/test_T2sIII.C tests/conformance/T2s/test_T2sIV.C tests/conformance/T2s/test_T2sIX.C tests/conformance/T2s/test_T2sV.C tests/conformance/T2s/test_T2sVI.C tests/conformance/T2s/test_T2sVII.C tests/conformance/T2s/test_T2sVIII.C tests/conformance/T2s/test_T2sX.C tests/conformance/T2s/test_T2sXI.C tests/conformance/T2s/test_T2sXII.C tests/conformance/T2s/test_T2sXIII.C tests/conformance/T2s/test_T2sXIV.C tests/conformance/T2s/test_T2sXIX.C tests/conformance/T2s/test_T2sXL.C tests/conformance/T2s/test_T2sXLI.C tests/conformance/T2s/test_T2sXLII.C tests/conformance/T2s/test_T2sXLIII.C tests/conformance/T2s/test_T2sXLIV.C tests/conformance/T2s/test_T2sXV.C tests/conformance/T2s/test_T2sXVI.C tests/conformance/T2s/test_T2sXVII.C tests/conformance/T2s/test_T2sXVIII.C tests/conformance/T2s/test_T2sXX.C tests/conformance/T2s/test_T2sXXI.C tests/conformance/T2s/test_T2sXXII.C tests/conformance/T2s/test_T2sXXIII.C tests/conformance/T2s/test_T2sXXIV.C tests/conformance/T2s/test_T2sXXIX.C tests/conformance/T2s/test_T2sXXV.C tests/conformance/T2s/test_T2sXXVI.C tests/conformance/T2s/test_T2sXXVII.C tests/conformance/T2s/test_T2sXXVIII.C tests/conformance/T2s/test_T2sXXX.C tests/conformance/T2s/test_T2sXXXI.C tests/conformance/T2s/test_T2sXXXII.C tests/conformance/T2s/test_T2sXXXIII.C tests/conformance/T2s/test_T2sXXXIV.C tests/conformance/T2s/test_T2sXXXIX.C tests/conformance/T2s/test_T2sXXXV.C tests/conformance/T2s/test_T2sXXXVI.C tests/conformance/T2s/test_T2sXXXVII.C tests/conformance/T2s/test_T2sXXXVIII.C tests/conformance/T3/test_T3.C tests/conformance/T3/test_T3II.C tests/conformance/T3as/test_T3as.C tests/conformance/T3as/test_T3asI.C tests/conformance/T3as/test_T3asII.C tests/conformance/T3as/test_T3asIII.C tests/conformance/T3as/test_T3asIV.C tests/conformance/T3as/test_T3asIX.C tests/conformance/T3as/test_T3asV.C tests/conformance/T3as/test_T3asVI.C tests/conformance/T3as/test_T3asVII.C tests/conformance/T3as/test_T3asVIII.C tests/conformance/T3as/test_T3asX.C tests/conformance/T3as/test_T3asXI.C tests/conformance/T3as/test_T3asXII.C tests/conformance/T3as/test_T3asXIII.C tests/conformance/T3as/test_T3asXIV.C tests/conformance/T3dg/test_T3dg.C tests/conformance/T3dg/test_T3dgCII.C tests/conformance/T3dg/test_T3dgCIII.C tests/conformance/T3dg/test_T3dgI.C tests/conformance/T3dg/test_T3dgII.C tests/conformance/T3dg/test_T3dgIII.C tests/conformance/T3dg/test_T3dgIV.C tests/conformance/T3dg/test_T3dgIX.C tests/conformance/T3dg/test_T3dgV.C tests/conformance/T3dg/test_T3dgVI.C tests/conformance/T3dg/test_T3dgVII.C tests/conformance/T3dg/test_T3dgVIII.C tests/conformance/T3dg/test_T3dgX.C tests/conformance/T3dg/test_T3dgXI.C tests/conformance/T3dg/test_T3dgXII.C tests/conformance/T3dg/test_T3dgXIII.C tests/conformance/T3dg/test_T3dgXIV.C tests/conformance/T3dg/test_T3dgXIX.C tests/conformance/T3dg/test_T3dgXV.C tests/conformance/T3dg/test_T3dgXVI.C tests/conformance/T3dg/test_T3dgXVII.C tests/conformance/T3dg/test_T3dgXVIII.C tests/conformance/T3dg/test_T3dgXX.C tests/conformance/T3dg/test_T3dgXXI.C tests/conformance/T3dg/test_T3dgXXII.C tests/conformance/T3dg/test_T3dgXXIII.C tests/conformance/T3dg/test_T3dgXXIV.C tests/conformance/T3dg/test_T3dgXXIX.C tests/conformance/T3dg/test_T3dgXXV.C tests/conformance/T3dg/test_T3dgXXVI.C tests/conformance/T3dg/test_T3dgXXVII.C tests/conformance/T3dg/test_T3dgXXVIII.C tests/conformance/T3dg/test_T3dgXXX.C tests/conformance/T3dg/test_T3dgXXXI.C tests/conformance/T3dg/test_T3dgXXXII.C tests/conformance/T3dg/test_T3dgXXXIII.C tests/conformance/T3dg/test_T3dgXXXIV.C tests/conformance/T3dg/test_T3dgXXXV.C tests/conformance/T4ddg/test_T4ddg.C tests/conformance/T4ddg/test_T4ddgII.C tests/conformance/T4ddg/test_T4ddgIII.C tests/conformance/T4ddg/test_T4ddgIV.C tests/conformance/T4ddg/test_T4ddgV.C tests/conformance/test_T0.C tests/conformance/test_T0.h tests/conformance/test_T1.C tests/conformance/test_T1.h tests/conformance/test_T2.h tests/conformance/test_T2s.h tests/conformance/test_T3.h tests/conformance/test_T3II.h tests/conformance/test_T3as.h tests/conformance/test_T3ch.C tests/conformance/test_T3ch.h tests/conformance/test_T3dg.h tests/conformance/test_T4R.C tests/conformance/test_T4R.h tests/conformance/test_T4ddg.h tests/conformance/test_T4ddgII.h tests/conformance/test_T4ddgIII.h tests/conformance/test_T4ddgIV.h tests/conformance/test_T4ddgV.h tests/conformance/test_for_zero.h tests/conformance/testcases.C tests/conformance/testcases_compiler.C tests/speed/Makefile tests/speed/Number_test.C tests/speed/acoustic.C tests/speed/example.C tests/speed/examplefast.C tests/speed/little.C tests/speed/littlefast.C tests/speed/one_over_1_minus_x.C tests/speed/one_over_1_minus_x.h tests/speed/one_over_1_minus_x1.C tests/speed/one_over_1_minus_x2.C tests/speed/one_over_1_minus_x3.C tests/speed/one_over_1_minus_x4.C tests/speed/one_over_1_minus_x5.C tests/speed/one_over_1_minus_x6.C tests/speed/one_over_1_minus_x7.C tests/speed/one_over_1_minus_x8.C tests/speed/one_over_1_minus_x9.C tests/speed/one_over_1_minus_x_fast.C tests/speed/one_over_1_minus_x_fast.h tests/speed/one_over_1_minus_x_fast1.C tests/speed/one_over_1_minus_x_fast2.C tests/speed/one_over_1_minus_x_fast3.C tests/speed/one_over_1_minus_x_fast4.C tests/speed/one_over_1_minus_x_fast5.C tests/speed/one_over_1_minus_x_fast6.C tests/speed/one_over_1_minus_x_fast7.C tests/speed/one_over_1_minus_x_fast8.C tests/speed/one_over_1_minus_x_fast9.C tests/speed/one_over_script tests/speed/simple.C tests/speed/single.C tests/speed/speed_test.C
description:
Initial import from old ArX repo


diff -r 000000000000 -r 34fc4fd9248b FTensor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FTensor.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,78 @@
+/* Include file for the Fast Tensor classes (FTensor).  Everything is
+   in namespace FTensor. */
+
+#include <cmath>
+#include <complex>
+#ifdef FTENSOR_DEBUG
+#include <iostream>
+#endif
+#include "Layout.h"
+namespace FTensor {
+  template <class T> class Tensor0;
+
+  template <class T, int Dim> class Tensor1;
+  template<class A, class T, int Dim, char i> class Tensor1_Expr;
+
+  template <class T, int Dim1, int Dim2, Layout layout=column_major>
+  class Tensor2;
+  template<class A, class T, int Dim1, int Dim2, char i, char j>
+  class Tensor2_Expr;
+  template<class A, class T, int N>
+  class Tensor2_number_rhs_0;
+  template<class A, class T, int N>
+  class Tensor2_number_rhs_1;
+
+  template <class T, int Dim> class Tensor2_symmetric;
+  template<class A, class T, int Dim, char i, char j>
+  class Tensor2_symmetric_Expr;
+
+  template <class A, class T, int Dim0, int Dim1, int Dim2,
+    char i, char j, char k> class Tensor3_Expr;
+
+  template <class T, int Dim01, int Dim2> class Tensor3_dg;
+  template <class A, class T, int Dim01, int Dim2, char i, char j, char k>
+  class Tensor3_dg_Expr;
+  template<class A, class T, int N> class Tensor3_dg_number_rhs_0;
+  template<class A, class T, int N> class Tensor3_dg_number_rhs_2;
+  template<class A, class T, int N1, int N2> class Tensor3_dg_number_rhs_01;
+  template<class A, class T, int N1, int N2> class Tensor3_dg_number_rhs_12;
+
+  template <class T, int Dim0, int Dim12> class Tensor3_christof;
+  template <class A, class T, int Dim0, int Dim12, char i, char j, char k>
+  class Tensor3_christof_Expr;
+
+  template <class T, int Dim0, int Dim12> class Tensor3_antisymmetric;
+  template <class A, class T, int Dim0, int Dim12, char i, char j, char k>
+  class Tensor3_antisymmetric_Expr;
+
+  template <class A, class T, int Dim0, int Dim1, int Dim2, int Dim3,
+    char i, char j, char k, char l> class Tensor4_Expr;
+
+  template <class T, int Dim> class Tensor4_Riemann;
+  template <class A, class T, int Dim, char i, char j, char k, char l>
+  class Tensor4_Riemann_Expr;
+
+  template <class T, int Dim01, int Dim23> class Tensor4_ddg;
+  template <class A, class T, int Dim01, int Dim23,
+    char i, char j, char k, char l> class Tensor4_ddg_Expr;
+  template<class A, class T, int N0, int N1>
+  class Tensor4_ddg_number_rhs_01;
+  template<class A, class T, int N0>
+  class Tensor4_ddg_number_rhs_0;
+
+#include "Index.h"
+#include "Number.h"
+#include "promote.h"
+#include "Tensor0.h"
+#include "Tensor1.h"
+#include "Tensor2.h"
+#include "Tensor2_symmetric.h"
+#include "Tensor3/Tensor3_Expr.h"
+#include "Tensor3/Tensor3_contracted.h"
+#include "Tensor3_dg.h"
+#include "Tensor3_christof.h"
+#include "Tensor3_antisymmetric.h"
+#include "Tensor4/Tensor4_Expr.h"
+#include "Tensor4_ddg.h"
+#include "Tensor4_Riemann.h"
+}
diff -r 000000000000 -r 34fc4fd9248b FTensor_new.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FTensor_new.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,76 @@
+/* Include file for the Fast Tensor classes (FTensor).  Everything is
+   in namespace FTensor. */
+
+#include <cmath>
+#include <complex>
+#ifdef FTENSOR_DEBUG
+#include <iostream>
+#endif
+namespace FTensor_new {
+  template <class T> class Tensor0;
+
+  template <class T, int Dim> class Tensor1;
+  template<class A, class T, int Dim, char i> class Tensor1_Expr;
+
+  template <class T, int Dim1, int Dim2> class Tensor2;
+  template<class A, class T, int Dim1, int Dim2, char i, char j>
+  class Tensor2_Expr;
+  template<class A, class T, int N>
+  class Tensor2_number_rhs_0;
+  template<class A, class T, int N>
+  class Tensor2_number_rhs_1;
+
+  template <class T, int Dim> class Tensor2_symmetric;
+  template<class A, class T, int Dim, char i, char j>
+  class Tensor2_symmetric_Expr;
+
+  template <class A, class T, int Dim0, int Dim1, int Dim2,
+    char i, char j, char k> class Tensor3_Expr;
+
+  template <class T, int Dim01, int Dim2> class Tensor3_dg;
+  template <class A, class T, int Dim01, int Dim2, char i, char j, char k>
+  class Tensor3_dg_Expr;
+  template<class A, class T, int N> class Tensor3_dg_number_rhs_0;
+  template<class A, class T, int N> class Tensor3_dg_number_rhs_2;
+  template<class A, class T, int N1, int N2> class Tensor3_dg_number_rhs_01;
+  template<class A, class T, int N1, int N2> class Tensor3_dg_number_rhs_12;
+
+  template <class T, int Dim0, int Dim12> class Tensor3_christof;
+  template <class A, class T, int Dim0, int Dim12, char i, char j, char k>
+  class Tensor3_christof_Expr;
+
+  template <class T, int Dim0, int Dim12> class Tensor3_antisymmetric;
+  template <class A, class T, int Dim0, int Dim12, char i, char j, char k>
+  class Tensor3_antisymmetric_Expr;
+
+  template <class A, class T, int Dim0, int Dim1, int Dim2, int Dim3,
+    char i, char j, char k, char l> class Tensor4_Expr;
+
+  template <class T, int Dim> class Tensor4_Riemann;
+  template <class A, class T, int Dim, char i, char j, char k, char l>
+  class Tensor4_Riemann_Expr;
+
+  template <class T, int Dim01, int Dim23> class Tensor4_ddg;
+  template <class A, class T, int Dim01, int Dim23,
+    char i, char j, char k, char l> class Tensor4_ddg_Expr;
+  template<class A, class T, int N0, int N1>
+  class Tensor4_ddg_number_rhs_01;
+  template<class A, class T, int N0>
+  class Tensor4_ddg_number_rhs_0;
+
+#include "Index.h"
+#include "Number.h"
+#include "promote.h"
+#include "Tensor0.h"
+#include "Tensor1.h"
+#include "Tensor2.h"
+#include "Tensor2_symmetric.h"
+#include "Tensor3/Tensor3_Expr.h"
+#include "Tensor3/Tensor3_contracted.h"
+#include "Tensor3_dg.h"
+#include "Tensor3_christof.h"
+#include "Tensor3_antisymmetric.h"
+#include "Tensor4/Tensor4_Expr.h"
+#include "Tensor4_ddg.h"
+#include "Tensor4_Riemann.h"
+}
diff -r 000000000000 -r 34fc4fd9248b Index.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Index.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,24 @@
+/* A simple index class that tells the operators which template to
+   instantiate.  The usual way to do this is to declare an index like
+
+   Index<'i',3> i;
+
+   It is important that each differently named index has a different
+   template parameter. So
+
+   Index<'i',3> i;
+   Index<'j',3> j;          // Good
+
+   is the right way, and
+
+   Index<'i',3> i,j;        // Bad
+
+   is likely to lead to errors, since the program thinks that i and j
+   are identical. */
+
+template<char i, int Dim>
+class Index
+{
+public:
+  Index() {};
+};
diff -r 000000000000 -r 34fc4fd9248b LICENSE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff -r 000000000000 -r 34fc4fd9248b Layout.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Layout.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,9 @@
+/* A simple enum to select what kind of storage order you want.
+   Useful if you're mixing these classes with libraries with something
+   that has row-major (not C/C++ standard) ordering like Fortran or
+   some graphics libraries (Direct-X?). */
+
+enum Layout {
+  column_major,
+  row_major
+};
diff -r 000000000000 -r 34fc4fd9248b Number.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Number.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,16 @@
+/* This index class allows you to explicitly use a part of a tensor.
+   If you want to explicitly list all of the indices, just use
+   int's. The usual way to do this is to declare a Number like
+   
+   Number<0> N; */
+
+template<const int N>
+class Number
+{
+public:
+  Number() {};
+  operator int() const
+  {
+    return N;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,264 @@
+FTensor
+September 5, 2002
+
+FTensor is a set of C++ classes that allow a great deal of
+abstraction when dealing with tensors, yet delivers uncompromising
+efficiency.  It uses template expressions to provide expressiveness
+and speed.
+
+FTensor is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.  A copy of the license should be included
+in the file LICENSE.
+
+FTensor uses template expressions to optimize code.  I owe a huge debt
+to Todd Veldhuizen who originally used template expressions in
+developing the Blitz library (see www.oonumerics.org).  FTensor uses
+many of the ideas from that library.
+
+FTensor's biggest claim to fame is that it handles implicit summation.
+Thus you can write
+
+  A(i,j) = B(i,k)*C(k,j)
+
+instead of having to write
+
+  A = sum(B(i,k)*C(k,j),k)
+
+Also, the result is strongly typed by the indices, so you can't write
+
+  A(i,k) = B(i,k)*C(k,j)
+
+or even
+
+  A = B(i,k)*C(k,j)
+
+It has Tensor0, Tensor1, Tensor2, Tensor2_symmetric, Tensor3_dg
+(symmetric on the first two indices), Tensor3_antisymmetric
+(antisymmetric on the last two indices), Tensor3_christof(symmetric on
+the last two indices), Tensor4_ddg(symmetric on the first two, and
+last two, indices) and Tensor4_Riemann(antisymmetric on the first two,
+and last two, indices, and symmetric under cyclic permutation of the
+last three indices).  I wrote this for a General Relativity code, so
+that is why I implemented this particular choice of tensors.
+
+I'm considering restructuring the code to use policies as described in
+Andrei Alexandrescu's excellent book "Modern C++ Design".  That would
+allow you to add a new symmetry fairly easy.  I've found that I have a
+need for a Hermitian matrix, and I don't look forward to basically
+replicating the Tensor2_symmetric class.
+
+The dimension of the tensors are determined by a template parameter.
+For two, three, or four dimensions, everything should just work.  For
+higher dimensions, the only caveat is that you can't use a simple
+constructor like
+
+  Tensor1<double,5> T1(0,1,2,3,4);
+
+You have to go in to FTensor_new/Tensor1/Tensor1_value.h and add it
+in.  If you want to use it for pointers, you have to add it to
+FTensor_new/Tensor1/Tensor1_pointer.h.  You don't have to do this.
+You could instead just type
+
+  Tensor1<double,5> T1;
+  T1(0)=0;
+  T1(1)=1;
+  T1(2)=2;
+  T1(3)=3;
+  T1(4)=4;
+
+It is more unsafe, but it doesn't require you to mess with the
+internals of the code.  If you want to turn on bounds checking (so
+that, for example, T1(5) will give you a run time error) then compile
+everything with FTENSOR_DEBUG defined.
+
+If you would like higher dimensional constructors, please let me know
+and I'll put them in.
+
+A new feature is the ability to store a Tensor2 in either column-major
+(the default) or row-major format.  It comes in the form of an
+optional fourth template parameter.  So to get column-major format,
+you can rely on on the default
+
+  Tensor2<double,2,3> T2;
+
+or you can declare it explicitly
+
+  Tensor2<double,2,3,column_major> T2;
+
+To get row-major format (for FORTRAN or some graphics libraries),
+declare it as
+
+  Tensor2<double,2,3,row_major> T2;
+
+It can also handle pointers to doubles.  So you could write
+
+  double a0[10000], a1[10000], a2[10000], b0[10000], b1[10000], b2[10000],
+     c0[10000], c1[10000], c2[10000];
+
+  Tensor1<double*,3> A(a0,a1,a2), B(b0,b1,b2), C(c0,c1,c2);
+
+  Index<'i'> i;
+  for(int a=0;a<10000;a++)
+    {
+      A(i)=B(i)+C(i);
+      ++A;
+      ++B;
+      ++C;
+    }
+
+If you are familiar with Blitz, it also uses template expressions to
+optimize code.  However, Blitz optimizes one expression at a time.
+So, for example, if you want to invert a 3x3 matrix, you can write it
+like
+
+  det=a(0,0)*a(1,1)*a(2,2) 
+    + a(1,0)*a(2,1)*a(0,2) 
+    + a(2,0)*a(0,1)*a(1,2)
+    - a(0,0)*a(2,1)*a(1,2)
+    - a(1,0)*a(0,1)*a(2,2)
+    - a(2,0)*a(1,1)*a(0,2);
+  inverse(0,0)= (a(1,1)*a(2,2) - a(1,2)*a(1,2))/det;
+  inverse(0,1)= (a(0,2)*a(1,2) - a(0,1)*a(2,2))/det;
+  inverse(0,2)= (a(0,1)*a(1,2) - a(0,2)*a(1,1))/det;
+  inverse(1,1)= (a(0,0)*a(2,2) - a(0,2)*a(0,2))/det;
+  inverse(1,2)= (a(0,2)*a(0,1) - a(0,0)*a(1,2))/det;
+  inverse(2,2)= (a(1,1)*a(0,0) - a(1,0)*a(1,0))/det;
+
+However, det is just going to be thrown away at the end.  We don't
+need to store it for all (10000 or whatever) points.  We just need to
+compute it for one point, use it in six expressions, and forget it.
+The Blitz method makes you ship the memory of det in and out of the
+cache 6 times.  A better way to do this is to put the whole inversion
+into one loop.  I've seen a factor of 4 improvement doing it this way.
+The disadvantages, which are all-too-real, are that you have to
+manually start the loop, and you have to remember to increment the
+variables.  In the case of the inversion, it ends up looking like
+
+  double det;
+  for(int i=0;i<10000;i++
+   {
+    det=a(0,0)*a(1,1)*a(2,2) 
+      + a(1,0)*a(2,1)*a(0,2) 
+      + a(2,0)*a(0,1)*a(1,2)
+      - a(0,0)*a(2,1)*a(1,2)
+      - a(1,0)*a(0,1)*a(2,2)
+      - a(2,0)*a(1,1)*a(0,2);
+    inverse(0,0)= (a(1,1)*a(2,2) - a(1,2)*a(1,2))/det;
+    inverse(0,1)= (a(0,2)*a(1,2) - a(0,1)*a(2,2))/det;
+    inverse(0,2)= (a(0,1)*a(1,2) - a(0,2)*a(1,1))/det;
+    inverse(1,1)= (a(0,0)*a(2,2) - a(0,2)*a(0,2))/det;
+    inverse(1,2)= (a(0,2)*a(0,1) - a(0,0)*a(1,2))/det;
+    inverse(2,2)= (a(1,1)*a(0,0) - a(1,0)*a(1,0))/det;
+    ++a;
+    ++inverse;
+   }
+
+Forgetting to put in the ++ operators could result in subtle bugs.
+You could also have problems if you put in more than one loop:
+
+  for(int i=0;i<10000;i++)
+   {
+    a(i,j)=...
+    ++a;
+   }
+
+  for(int i=0;i<10000;i++)
+   {
+    a(i,j)+=...
+    ++a;
+   }
+
+This will end up writing off of the end of a.  Furthermore, I use the
+restrict keyword, so you might get some weird problems if you try to
+alias things.  You might want to #define the restrict away.  I found
+that it actually decreased performance for extremely complicated
+expressions.
+
+Basically, you're giving up some expressive power.
+
+It can handle quite complex expressions.  As a real life example
+
+  K_new(i,j)=Lapse*(R(i,j) + Trace_K*K(i,j) - (2*K(i,k)^K_mix(k,j)) 
+                    - 0.5*matter_ADM*g(i,j) - S_ADM(i,j))
+             + Shift_up(k)*dK(i,j,k)
+             + (K(i,k)*dShift_up(k,j) || K(j,k)*dShift_up(k,i))
+             - ddLapse(i,j) + (dLapse(k)*christof(k,i,j));
+
+K_new is symmetric, the ^ operator means contract to make a
+Tensor2_symmetric, and the || means add to make a Tensor2_symmetric
+(it is not a symmetrizer, so it doesn't divide by 2).  I had to use
+these operators (instead of * and +) to keep the compilers from making
+a Tensor2 instead.  You can't assign a Tensor2 to a Tensor2_symmetric,
+so you have to explicitly request the symmetrized result.
+
+KCC was able to optimize the entire expression.  I don't know if any
+other compilers can fully optimize these things well.  gcc doesn't
+(though that isn't surprising).  I couldn't get SGI's CC compiler to
+do it either.  xlC can't optimize it, and I've had problems with
+Internal Compiler Errors and incorrect code.  The Portland Group's
+compiler doesn't optimize it.  For a more complete discussion of
+compilers, please see the paper at
+
+  http://superbeast.ucsd.edu/~landry/FTensor/FTensor.pdf
+
+If your compiler can't optimize the expressions, then you might end up
+with something slower than doing everything by hand, but maybe not.
+For small examples (like the matrix inversion) there is a large
+slowdown (factors of three or more).  However, in my real-life code, I
+saw slow downs of only 10-20% using gcc or xlC compared to KCC.  I
+think I was still dominated by memory bandwith.
+
+Also, not all possible operations are supported.  I can't think of any
+right now, but I know they exist.  It is not hard to add in
+operations, but I don't need it, so I haven't done it.  A somewhat
+more useful extension might be antisymmetric rank 2 tensors.  I have a
+way of doing that, but it isn't particularly nice.  I won't describe
+it here, except to say that it is unsafe.  You can look in
+Tensor3_antisymmetric for how I handled the antisymmetries in that.
+
+There are two versions of the tensor library mentioned in the paper.
+They should both be available through
+
+  http://superbeast.ucsd.edu/~landry/FTensor/
+
+The older version works with older versions (3.0.x and earlier) of
+gcc.
+
+The new version requires a relatively up to date compiler. The details
+of which unix compiler works are in the paper.  KCC is the best, but
+has been discontinued.  The gcc compiler has only recently been able
+to work with the newest version (3.1.x and newer).
+
+If you're running Linux, the Intel Compiler at
+
+  http://developer.intel.com/software/products/compilers/c50/linux/
+
+is free non-commercial use.  For those of you in Windows, I'm almost
+certain that Microsoft's compiler will not work. However, the Windows
+version of the Intel Compiler
+
+  http://developer.intel.com/software/products/compilers/c50/
+
+should work, as well as the Comeau compiler
+
+  http://www.comeaucomputing.com/
+
+I've heard that the Metroworks compiler
+
+  http://www.metroworks.com/products/windows/
+
+also has good template support, so it should compile it.  If you know,
+please send me a note.
+
+The tarball has a directory for tests.  There is a README in there
+that should explain how to use them.
+
+If you have any questions, feedback, bug reports, feature requests,
+etc., feel free to send me an email.
+
+Enjoy,
+Walter Landry
+wlandry at ucsd.edu
+
diff -r 000000000000 -r 34fc4fd9248b Tensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,86 @@
+/* A Tensor0 class that really just ends up being an alias for a
+   pointer to a templated type T. Note that the T * is mutable, so the
+   pointer can change, allowing iterating over a array.  Also note
+   that diffusion and interpolate are included at the end of this
+   file, because it needs the full definition of Tensor0. */
+
+#include "Tensor0/dTensor0.h"
+#include "Tensor0/ddTensor0.h"
+#include "Tensor0/d_boundary_Tensor0.h"
+#include "Tensor0/dd_boundary_Tensor0.h"
+
+template <class T>
+class Tensor0
+{};
+
+template <class T>
+class Tensor0<T*>
+{
+  mutable T * restrict data;
+public:
+  Tensor0(T *d): data(d) {}
+
+  const Tensor0 & operator=(const Tensor0 &a)
+  {
+    *data=*(a.data);
+    return *this;
+  }
+
+  template<class U>
+  const Tensor0<T*> & operator=(const U &d)
+  {
+    *data=d;
+    return *this;
+  }
+  template<class U>
+  const Tensor0<T*> & operator+=(const U &d)
+  {
+    *data+=d;
+    return *this;
+  }
+  template<class U>
+  const Tensor0<T*> & operator-=(const U &d)
+  {
+    *data-=d;
+    return *this;
+  }
+  template<class U>
+  const Tensor0<T*> & operator*=(const U &d)
+  {
+    *data*=d;
+    return *this;
+  }
+  template<class U>
+  const Tensor0<T*> & operator/=(const U &d)
+  {
+    *data/=d;
+    return *this;
+  }
+
+  /* Note that the conversion operator& to T * only works on
+     consts, so it doesn't allow you to change the value of *data.
+     You have to use the = operators to change that.  The idea is that
+     operator& is only used for stencils and such.  */
+
+  const T * operator&() const
+  {
+    return data;
+  }
+  operator T() const
+  {
+    return *data;
+  }
+
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+
+  const Tensor0<T*> & operator++() const
+  {
+    ++data;
+    return *this;
+  }
+};
+
+#include "Tensor0/d_one_sided_Tensor0.h"
+#include "Tensor0/diffusion_Tensor0.h"
+#include "Tensor0/interpolate_Tensor0.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor0/dTensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0/dTensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,29 @@
+/* Takes a derivative of a Tensor0<T*> yielding a Tensor1. */
+
+template<class T, int Dim, char i>
+class dTensor0
+{
+  const Tensor0<T*> &a;
+  const Tensor1<int,Dim> &d_ijk;
+  const Tensor1<double,Dim> &d_xyz;
+public:
+  typename promote<T,double>::V operator()(const int N) const
+  {
+    return (*(&a+d_ijk(N))-*(&a-d_ijk(N)))*d_xyz(N)*0.5;
+  }
+  dTensor0(const Tensor0<T*> &A,
+	   const Tensor1<int,Dim> &D_ijk,
+	   const Tensor1<double,Dim> &D_xyz)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz) {}
+};
+
+template<class T, int Dim, char i>
+inline const Tensor1_Expr<const dTensor0<T,Dim,i>,typename promote<T,double>::V,Dim,i>
+d(const Tensor0<T*> &a, const Index<i,Dim> index, 
+  const Tensor1<int,Dim> &d_ijk,
+  const Tensor1<double,Dim> &d_xyz)
+{
+  typedef const dTensor0<T,Dim,i> Tensor_Expr;
+  return Tensor1_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i>
+    (Tensor_Expr(a,d_ijk,d_xyz));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor0/d_boundary_Tensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0/d_boundary_Tensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,36 @@
+/* Takes a derivative of a Tensor0<T*> yielding a Tensor1.  It checks
+   whether we're at a boundary, and takes a one-sided derivative
+   there. */
+
+template<class T, int Dim, char i>
+class d_boundary_Tensor0
+{
+  const Tensor0<T*> &a;
+  const Tensor1<int,Dim> &d_ijk;
+  const Tensor1<double,Dim> &d_xyz;
+  const Tensor2<bool,Dim,2> &boundary;
+public:
+  typename promote<T,double>::V operator()(const int N) const
+  {
+    return boundary(N,0) ? (*(&a+d_ijk(N))-a)*d_xyz(N) :
+      (boundary(N,1) ? (a-*(&a-d_ijk(N)))*d_xyz(N) :
+       (*(&a+d_ijk(N))-*(&a-d_ijk(N)))*d_xyz(N)*0.5);
+  }
+  d_boundary_Tensor0(const Tensor0<T*> &A,
+		     const Tensor1<int,Dim> &D_ijk,
+		     const Tensor1<double,Dim> &D_xyz,
+		     const Tensor2<bool,Dim,2> &Boundary)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) {}
+};
+
+template<class T, int Dim, char i>
+inline const Tensor1_Expr<const d_boundary_Tensor0<T,Dim,i>,typename promote<T,double>::V,Dim,i>
+d_boundary(const Tensor0<T*> &a, const Index<i,Dim> index, 
+	   const Tensor1<int,Dim> &d_ijk,
+	   const Tensor1<double,Dim> &d_xyz,
+	   const Tensor2<bool,Dim,2> &boundary)
+{
+  typedef const d_boundary_Tensor0<T,Dim,i> Tensor_Expr;
+  return Tensor1_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i>
+    (Tensor_Expr(a,d_ijk,d_xyz,boundary));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor0/d_one_sided_Tensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0/d_one_sided_Tensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,32 @@
+/* Takes a one-sided derivative of a Tensor0 in a particular
+   direction, yielding a typename promote<T,double>::V. */
+
+template<class T>
+inline const typename promote<T,double>::V
+d_one_sided(const Tensor0<T*> &a, const Number<0> n1,
+		 const int &di, const int &dj, const int &dk,
+		 const double &dx, const double &dy,
+		 const double &dz)
+{
+  return (a-*(&a-di))*dx;
+}
+
+template<class T>
+inline const typename promote<T,double>::V
+d_one_sided(const Tensor0<T*> &a, const Number<1> n1,
+		 const int &di, const int &dj, const int &dk,
+		 const double &dx, const double &dy,
+		 const double &dz)
+{
+  return (a-*(&a-dj))*dy;
+}
+
+template<class T>
+inline const typename promote<T,double>::V
+d_one_sided(const Tensor0<T*> &a, const Number<2> n1,
+		 const int &di, const int &dj, const int &dk,
+		 const double &dx, const double &dy,
+		 const double &dz)
+{
+  return (a-*(&a-dk))*dz;
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor0/ddTensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0/ddTensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,35 @@
+/* Takes a second derivative of a Tensor0 yielding a Tensor2_symmetric. */
+
+template<class T, int Dim, char i, char j>
+class ddTensor0
+{
+  const Tensor0<T*> &a;
+  const Tensor1<int,Dim> &d_ijk;
+  const Tensor1<double,Dim> &d_xyz;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2) const
+  {
+    return
+      N1==N2 ? (*(&a+d_ijk(N1))-2*a+*(&a-d_ijk(N1)))
+      *d_xyz(N1)*d_xyz(N1) :
+      (*(&a+d_ijk(N1)+d_ijk(N2)) - *(&a-d_ijk(N1)+d_ijk(N2))
+       - *(&a+d_ijk(N1)-d_ijk(N2)) + *(&a-d_ijk(N1)-d_ijk(N2)))
+      *d_xyz(N1)*d_xyz(N2)*0.25;
+  }
+  ddTensor0(const Tensor0<T*> &A,
+	    const Tensor1<int,Dim> &D_ijk,
+	    const Tensor1<double,Dim> &D_xyz)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz) {}
+};
+
+template<class T, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const ddTensor0<T,Dim,i,j>,
+  typename promote<T,double>::V,Dim,i,j>
+dd(const Tensor0<T*> &a, const Index<i,Dim> index1, const Index<j,Dim> index2,
+   const Tensor1<int,Dim> &d_ijk, const Tensor1<double,Dim> &d_xyz)
+{
+  typedef const ddTensor0<T,Dim,i,j> Tensor_Expr;
+  return Tensor2_symmetric_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i,j>
+    (Tensor_Expr(a,d_ijk,d_xyz));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor0/dd_boundary_Tensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0/dd_boundary_Tensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,79 @@
+/* Takes a second derivative of a Tensor0<T*> yielding a Tensor1.
+   This is primarily useful at boundaries, where you have to take
+   one-sided derivatives. */
+
+template<class T, int Dim, char i, char j>
+class dd_boundary_Tensor0
+{
+  const Tensor0<T*> &a;
+  const Tensor1<int,Dim> &d_ijk;
+  const Tensor1<double,Dim> &d_xyz;
+  const Tensor2<bool,Dim,2> &boundary;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2) const
+  {
+    return N1==N2 ?
+      (boundary(N1,0) ?
+       (*(&a+2*d_ijk(N1))-2**(&a+d_ijk(N1))+a) :
+       (boundary(N1,1) ?
+	(a-2**(&a-d_ijk(N1))+*(&a-2*d_ijk(N1))):
+	(*(&a+d_ijk(N1))-2*a+*(&a-d_ijk(N1)))))
+       *d_xyz(N1)*d_xyz(N1) :
+      (boundary(N1,0) ?
+       (boundary(N2,0) ?
+	((*(&a+d_ijk(N1)+d_ijk(N2)) - *(&a+d_ijk(N2))
+	  - *(&a+d_ijk(N1)) + a)*d_xyz(N1)*d_xyz(N2)) :
+	(boundary(N2,1) ?
+	 ((*(&a+d_ijk(N1)) - a
+	   - *(&a+d_ijk(N1)-d_ijk(N2))
+	   + *(&a-d_ijk(N2)))*d_xyz(N1)*d_xyz(N2)) :
+	 (*(&a+d_ijk(N1)+d_ijk(N2))
+	  - *(&a+d_ijk(N2))
+	  - *(&a+d_ijk(N1)-d_ijk(N2))
+	  + *(&a-d_ijk(N2)))*d_xyz(N1)*d_xyz(N2)*0.5)) :
+       (boundary(N1,1) ?
+	(boundary(N2,0) ?
+	 ((*(&a+d_ijk(N2)) - *(&a-d_ijk(N1)+d_ijk(N2))
+	   - a + *(&a-d_ijk(N1)))*d_xyz(N1)*d_xyz(N2)) :
+	 (boundary(N2,1) ?
+	  ((a - *(&a-d_ijk(N1))
+	    - *(&a-d_ijk(N2))
+	    + *(&a-d_ijk(N1)-d_ijk(N2)))*d_xyz(N1)*d_xyz(N2)) :
+	  (*(&a+d_ijk(N2))
+	   - *(&a-d_ijk(N1)+d_ijk(N2))
+	   - *(&a-d_ijk(N2))
+	   + *(&a-d_ijk(N1)-d_ijk(N2)))*d_xyz(N1)*d_xyz(N2)*0.5)) :
+	(boundary(N2,0) ?
+	 ((*(&a+d_ijk(N1)+d_ijk(N2))
+	   - *(&a-d_ijk(N1)+d_ijk(N2))
+	   - *(&a+d_ijk(N1))
+	   + *(&a-d_ijk(N1)))*d_xyz(N1)*d_xyz(N2)*0.5) :
+	 (boundary(N2,1) ?
+	  ((*(&a+d_ijk(N1))
+	    - *(&a-d_ijk(N1))
+	    - *(&a+d_ijk(N1)-d_ijk(N2))
+	    + *(&a-d_ijk(N1)-d_ijk(N2)))*d_xyz(N1)*d_xyz(N2)*0.5) :
+	  ((*(&a+d_ijk(N1)+d_ijk(N2))
+	    - *(&a-d_ijk(N1)+d_ijk(N2))
+	    - *(&a+d_ijk(N1)-d_ijk(N2))
+	    + *(&a-d_ijk(N1)-d_ijk(N2)))*d_xyz(N1)*d_xyz(N2)*0.25)))));
+  }
+  dd_boundary_Tensor0(const Tensor0<T*> &A,
+		      const Tensor1<int,Dim> &D_ijk,
+		      const Tensor1<double,Dim> &D_xyz,
+		      const Tensor2<bool,Dim,2> &Boundary)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) {}
+};
+
+template<class T, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const dd_boundary_Tensor0<T,Dim,i,j>,
+  typename promote<T,double>::V,Dim,i,j>
+dd_boundary(const Tensor0<T*> &a,
+	    const Index<i,Dim> index3, const Index<j,Dim> index4,
+	    const Tensor1<int,Dim> &d_ijk, const Tensor1<double,Dim> &d_xyz,
+	    const Tensor2<bool,Dim,2> &boundary)
+{
+  typedef const dd_boundary_Tensor0<T,Dim,i,j> Tensor_Expr;
+  return Tensor2_symmetric_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i,j>
+    (Tensor_Expr(a,d_ijk,d_xyz,boundary));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor0/diffusion_Tensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0/diffusion_Tensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,16 @@
+/* Computes 2*del^2 of a Tensor0_ptr but uses diagonal derivatives for
+   half of it. */
+
+template<class T>
+inline const typename promote<T,double>::V
+diffusion(const Tensor0<T*> &a, const int &di, const int &dj,
+	  const int &dk, const double &dx)
+{
+  return 
+    ((*(&a+di) - 2*a + *(&a-di)) + (*(&a+dj) - 2*a + *(&a-dj))
+     + (*(&a+dk) - 2*a + *(&a-dk))
+     + ((*(&a+di+dj) + *(&a+di-dj) + *(&a-di+dj) + *(&a-di-dj) - 4*a)
+	+ (*(&a+di+dk) + *(&a+di-dk) + *(&a-di+dk) + *(&a-di-dk) - 4*a)
+	+ (*(&a+dj+dk) + *(&a+dj-dk) + *(&a-dj+dk) + *(&a-dj-dk) - 4*a))
+     /(std::sqrt(2.0)))*dx*dx;
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor0/interpolate_Tensor0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor0/interpolate_Tensor0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,31 @@
+/* Interpolates to (i0+distance[0], j0+distance[1], k0+distance[2]),
+   yielding a double.  (i0,j0,k0) are 3D array coordinates,
+   conjugate==1-distance, and (di,dj,dk) are the stride of the array
+   coordinates.  It is assumed that the Tensor0_ptr is zero
+   centered. */
+
+template <class T>
+inline const typename promote<T,double>::V
+interpolate(const Tensor0<T*> &a, const int &di, const int &dj,
+	    const int &dk, const int &i0, const int &j0,
+	    const int &k0, const double distance[3],
+	    const double conjugate[3])
+{
+  return 
+    conjugate[0]*conjugate[1]*conjugate[2]
+    * (*(&a + di*i0 + dj*j0 + dk*k0))
+    + distance[0]*conjugate[1]*conjugate[2]
+    * (*(&a + di*(i0+1) + dj*(j0) + dk*(k0)))
+    + conjugate[0]*distance[1]*conjugate[2]
+    * (*(&a + di*(i0) + dj*(j0+1) + dk*(k0)))
+    + distance[0]*distance[1]*conjugate[2]
+    * (*(&a + di*(i0+1) + dj*(j0+1) + dk*(k0)))
+    + conjugate[0]*conjugate[1]*distance[2]
+    * (*(&a + di*(i0) + dj*(j0) + dk*(k0+1)))
+    + distance[0]*conjugate[1]*distance[2]
+    * (*(&a + di*(i0+1) + dj*(j0) + dk*(k0+1)))
+    + conjugate[0]*distance[1]*distance[2]
+    * (*(&a + di*(i0) + dj*(j0+1) + dk*(k0+1)))
+    + distance[0]*distance[1]*distance[2]
+    * (*(&a + di*(i0+1) + dj*(j0+1) + dk*(k0+1)));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,7 @@
+/* Declarations for Tensor1. */
+
+#include "Tensor1/Tensor1_constructor.h"
+#include "Tensor1/Tensor1_value.h"
+#include "Tensor1/Tensor1_pointer.h"
+
+#include "Tensor1/Tensor1_Expr.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,249 @@
+/* Declares a wrapper class for rank 1 Tensor expressions. Note that
+   Tensor1_Expr_equals is included at the end, since it needs the
+   definition of the class in order to compile. */
+
+#include "Tensor1_plus_Tensor1.h"
+#include "Tensor1_minus_Tensor1.h"
+#include "Tensor1_times_Tensor1.h"
+#include "Tensor1_or_Tensor1.h"
+#include "Tensor1_carat_Tensor1.h"
+#include "Tensor1_and_Tensor1.h"
+#include "Tensor1_plus_generic.h"
+#include "Tensor1_minus_generic.h"
+#include "Tensor1_times_generic.h"
+#include "Tensor1_divide_generic.h"
+#include "generic_minus_Tensor1.h"
+#include "minus_Tensor1.h"
+#include "dTensor1.h"
+#include "ddTensor1.h"
+#include "d_one_sided_Tensor1.h"
+#include "diffusion_Tensor1.h"
+#include "interpolate_Tensor1.h"
+
+template<class A, class T, int Dim, char i>
+class Tensor1_Expr
+{
+  A iter;
+public:
+  Tensor1_Expr(A &a): iter(a) {}
+  T operator()(const int N) const
+  {
+    return iter(N);
+  }
+};
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+class Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>
+{
+  Tensor1<A,Tensor_Dim> &iter;
+public:
+  Tensor1_Expr(Tensor1<A,Tensor_Dim> &a): iter(a) {}
+
+  T & operator()(const int N)
+  {
+    return iter(N);
+  }
+  T operator()(const int N) const
+  {
+    return iter(N);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator=(const Tensor1_Expr<B,U,Dim,i> &result);
+
+  const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator=(const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &result);
+
+  template<class B, class U> inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator+=(const Tensor1_Expr<B,U,Dim,i> &result);
+
+  template<class B, class U> inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator-=(const Tensor1_Expr<B,U,Dim,i> &result);
+
+  /* General template assignment operators intended mostly for
+     doubles (type T), but could be applied to anything you want, like
+     complex, etc.  All that is required is that T=B works (or T+=B,
+     etc.)  */
+
+  template<class B> inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator=(const B &d);
+  template<class B> inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator+=(const B &d);
+  template<class B> inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator-=(const B &d);
+  template<class B> inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator*=(const B &d);
+  template<class B> inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+  operator/=(const B &d);
+};
+
+/* Specialized for Tensor2_number_rhs_0 (Tensor2{_symmetric} with the
+   first index explicitly given). */
+
+template<class A, class T, int Dim1, char i, int N>
+class Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>
+{
+  A &iter;
+public:
+  Tensor1_Expr(A &a): iter(a) {}
+  T & operator()(const int N1)
+  {
+    return iter(N,N1);
+  }
+  T operator()(const int N1) const
+  {
+    return iter(N,N1);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+  operator=(const Tensor1_Expr<B,U,Dim1,i> &result);
+
+  const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> &
+  operator=(const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+  operator=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+  operator+=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+  operator-=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+  operator*=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+  operator/=(const B &result);
+};
+
+
+/* Specialized for Tensor2_number_rhs_1 (Tensor2{_symmetric} with the
+   second index explicitly given). */
+
+template<class A, class T, int Dim1, char i, int N>
+class Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>
+{
+  A &iter;
+public:
+  Tensor1_Expr(A &a): iter(a) {}
+  T & operator()(const int N1)
+  {
+    return iter(N1,N);
+  }
+  T operator()(const int N1) const
+  {
+    return iter(N1,N);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+  operator=(const Tensor1_Expr<B,U,Dim1,i> &result);
+
+  const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> &
+  operator=(const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+  operator=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+  operator+=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+  operator-=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+  operator*=(const B &result);
+
+  template<class B> inline
+  const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+  operator/=(const B &result);
+};
+
+/* Specialized for Tensor3_dg_number_rhs_12 (A Tensor3_dg with
+   explicit numbers in the (first or second) and third slots). */
+
+template<class A, class T, int Dim, char i, int N1, int N2>
+class Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i>
+{
+  A &iter;
+public:
+  Tensor1_Expr(A &a):iter(a) {}
+  T & operator()(const int N)
+  {
+    return iter(N,N1,N2);
+  }
+  T operator()(const int N) const
+  {
+    return iter(N,N1,N2);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i> & 
+  operator=(const Tensor1_Expr<B,U,Dim,i> &result);
+
+  const Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i> &
+  operator=(const Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i>
+	    &result);
+};
+
+/* Specialized for Tensor3_dg_number_rhs_01 (A Tensor3_dg with
+   explicit numbers in the first and second slots). */
+
+template<class A, class T, int Dim, char i, int N1, int N2>
+class Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i>
+{
+  A &iter;
+public:
+  Tensor1_Expr(A &a):iter(a) {}
+  T & operator()(const int N)
+  {
+    return iter(N1,N2,N);
+  }
+  T operator()(const int N) const
+  {
+    return iter(N1,N2,N);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i> & 
+  operator=(const Tensor1_Expr<B,U,Dim,i> &result);
+
+  const Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i> &
+  operator=(const Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i>
+	    &result);
+};
+
+#include "Tensor1_Expr_equals.h"
+
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_Expr_equals.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_Expr_equals.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,647 @@
+/* Various assignment operators for generic Tensor1_Expr's as well as
+   specializations for Tensor2_number_rhs's.  I have to explicitly
+   declare the second operator= because otherwise the compiler will
+   generate its own and not use the template code. */
+
+/* =T1_Expr */
+
+template<class A, class B, class U, int Dim, char i, int Current_Dim>
+inline void T1_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim,i> result,
+			 const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)=result(Current_Dim-1);
+  T1_equals_T1(iter,result,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class U, int Dim, char i>
+inline void T1_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim,i> result,
+			 const Number<1> &N)
+{
+  iter(0)=result(0);
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class B, class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator=(const Tensor1_Expr<B,U,Dim,i> &result)
+{
+  T1_equals_T1(iter,result,Number<Dim>());
+  return *this;
+}
+
+/* =T1_Expr(T1) */
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator=(const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &result)
+{
+  return operator=<Tensor1<A,Tensor_Dim>,T>(result);
+}
+
+/* +=T1 */
+
+template<class A, class B, class U, int Dim, char i, int Current_Dim>
+inline void T1_plus_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim,i> result,
+			 const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)+=result(Current_Dim-1);
+  T1_plus_equals_T1(iter,result,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class U, int Dim, char i>
+inline void T1_plus_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim,i> result,
+			 const Number<1> &N)
+{
+  iter(0)+=result(0);
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class B, class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator+=(const Tensor1_Expr<B,U,Dim,i> &result)
+{
+  T1_plus_equals_T1(iter,result,Number<Dim>());
+  return *this;
+}
+
+/* -=T1 */
+
+template<class A, class B, class U, int Dim, char i, int Current_Dim>
+inline void T1_minus_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim,i> result,
+			 const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)-=result(Current_Dim-1);
+  T1_minus_equals_T1(iter,result,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class U, int Dim, char i>
+inline void T1_minus_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim,i> result,
+			 const Number<1> &N)
+{
+  iter(0)-=result(0);
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class B, class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator-=(const Tensor1_Expr<B,U,Dim,i> &result)
+{
+  T1_minus_equals_T1(iter,result,Number<Dim>());
+  return *this;
+}
+
+/* General template assignment operators intended mostly for
+   doubles (type U), but could be applied to anything you want, like
+   complex, etc.  All that is required is that T=U works (or T+=U,
+   etc.)  */
+
+/* =U */
+
+template<class A, class U, int Current_Dim>
+inline void T1_equals_generic(A &iter, const U &u,
+			      const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)=u;
+  T1_equals_generic(iter,u,Number<Current_Dim-1>());
+}
+
+template<class A, class U>
+inline void T1_equals_generic(A &iter, const U &u,
+			      const Number<1> &N)
+{
+  iter(0)=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator=(const U &u)
+{
+  T1_equals_generic(iter,u,Number<Dim>());
+  return *this;
+}
+
+/* +=U */
+
+template<class A, class U, int Current_Dim>
+inline void T1_plus_equals_generic(A &iter, const U &u,
+				   const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)+=u;
+  T1_plus_equals_generic(iter,u,Number<Current_Dim-1>());
+}
+
+template<class A, class U>
+inline void T1_plus_equals_generic(A &iter, const U &u,
+				   const Number<1> &N)
+{
+  iter(0)+=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator+=(const U &u)
+{
+  T1_plus_equals_generic(iter,u,Number<Dim>());
+  return *this;
+}
+
+/* -=U */
+
+template<class A, class U, int Current_Dim>
+inline void T1_minus_equals_generic(A &iter, const U &u,
+				    const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)-=u;
+  T1_minus_equals_generic(iter,u,Number<Current_Dim-1>());
+}
+
+template<class A, class U>
+inline void T1_minus_equals_generic(A &iter, const U &u,
+				    const Number<1> &N)
+{
+  iter(0)-=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator-=(const U &u)
+{
+  T1_minus_equals_generic(iter,u,Number<Dim>());
+  return *this;
+}
+
+/* *=U */
+
+template<class A, class U, int Current_Dim>
+inline void T1_times_equals_generic(A &iter, const U &u,
+				    const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)*=u;
+  T1_times_equals_generic(iter,u,Number<Current_Dim-1>());
+}
+
+template<class A, class U>
+inline void T1_times_equals_generic(A &iter, const U &u,
+				    const Number<1> &N)
+{
+  iter(0)*=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator*=(const U &u)
+{
+  T1_times_equals_generic(iter,u,Number<Dim>());
+  return *this;
+}
+
+/* /=U */
+
+template<class A, class U, int Current_Dim>
+inline void T1_divide_equals_generic(A &iter, const U &u,
+				     const Number<Current_Dim> &N)
+{
+  iter(Current_Dim-1)/=u;
+  T1_divide_equals_generic(iter,u,Number<Current_Dim-1>());
+}
+
+template<class A, class U>
+inline void T1_divide_equals_generic(A &iter, const U &u,
+				     const Number<1> &N)
+{
+  iter(0)/=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i>
+template<class U>
+inline const Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i> &
+Tensor1_Expr<Tensor1<A,Tensor_Dim>,T,Dim,i>::operator/=(const U &u)
+{
+  T1_divide_equals_generic(iter,u,Number<Dim>());
+  return *this;
+}
+
+/* Specializations for Tensor2_number_rhs_0's */
+
+/* =T1 */
+
+template<class A, class B, class U, int Dim1, char i, int N, int Current_Dim>
+inline void T2rhs0_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim1,i> &result,
+			     const Number<N> &N1,
+			     const Number<Current_Dim> &N2)
+{
+  iter(N,Current_Dim-1)=result(Current_Dim-1);
+  T2rhs0_equals_T1(iter,result,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class U, int Dim1, char i, int N>
+inline void T2rhs0_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim1,i> &result,
+			     const Number<N> &N1,
+			     const Number<1> &N2)
+{
+  iter(N,0)=result(0);
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class B, class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>::operator=(const Tensor1_Expr<B,U,Dim1,i> &result)
+{
+  T2rhs0_equals_T1(iter,result,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+template<class A, class T, int Dim1, char i, int N> inline
+const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> &
+Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>::operator=(const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> &result)
+{
+  return operator=<Tensor2_number_rhs_0<A,T,N>,T>(result);
+}
+
+
+/* =U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs0_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(N,Current_Dim-1)=u;
+  T2rhs0_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs0_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(N,0)=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>::operator=(const U &u)
+{
+  T2rhs0_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* +=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs0_plus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(N,Current_Dim-1)+=u;
+  T2rhs0_plus_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs0_plus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(N,0)+=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>::operator+=(const U &u)
+{
+  T2rhs0_plus_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* -=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs0_minus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(N,Current_Dim-1)-=u;
+  T2rhs0_minus_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs0_minus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(N,0)-=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>::operator-=(const U &u)
+{
+  T2rhs0_minus_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* *=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs0_times_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(N,Current_Dim-1)*=u;
+  T2rhs0_times_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs0_times_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(N,0)*=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>::operator*=(const U &u)
+{
+  T2rhs0_times_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* /=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs0_divide_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(N,Current_Dim-1)/=u;
+  T2rhs0_divide_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs0_divide_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(N,0)/=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_0<A,T,N>,T,Dim1,i>::operator/=(const U &u)
+{
+  T2rhs0_divide_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* Specializations for Tensor2_number_rhs_1's */
+
+/* =T1 */
+
+template<class A, class B, class U, int Dim1, char i, int N, int Current_Dim>
+inline void T2rhs1_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim1,i> &result,
+			     const Number<N> &N1,
+			     const Number<Current_Dim> &N2)
+{
+  iter(Current_Dim-1,N)=result(Current_Dim-1);
+  T2rhs1_equals_T1(iter,result,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class U, int Dim1, char i, int N>
+inline void T2rhs1_equals_T1(A &iter, const Tensor1_Expr<B,U,Dim1,i> &result,
+			     const Number<N> &N1,
+			     const Number<1> &N2)
+{
+  iter(0,N)=result(0);
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class B, class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>::operator=(const Tensor1_Expr<B,U,Dim1,i> &result)
+{
+  T2rhs1_equals_T1(iter,result,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+template<class A, class T, int Dim1, char i, int N> inline
+const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> &
+Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>::operator=(const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> &result)
+{
+  return operator=<Tensor2_number_rhs_1<A,T,N>,T>(result);
+}
+
+/* =U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs1_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(Current_Dim-1,N)=u;
+  T2rhs1_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs1_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(0,N)=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>::operator=(const U &u)
+{
+  T2rhs1_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* +=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs1_plus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(Current_Dim-1,N)+=u;
+  T2rhs1_plus_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs1_plus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(0,N)+=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>::operator+=(const U &u)
+{
+  T2rhs1_plus_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* -=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs1_minus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(Current_Dim-1,N)-=u;
+  T2rhs1_minus_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs1_minus_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(0,N)-=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>::operator-=(const U &u)
+{
+  T2rhs1_minus_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* *=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs1_times_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(Current_Dim-1,N)*=u;
+  T2rhs1_times_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs1_times_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(0,N)*=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>::operator*=(const U &u)
+{
+  T2rhs1_times_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+/* /=U */
+
+template<class A, class U, int N, int Current_Dim>
+inline void T2rhs1_divide_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<Current_Dim> &N2)
+{
+  iter(Current_Dim-1,N)/=u;
+  T2rhs1_divide_equals_generic(iter,u,N1,Number<Current_Dim-1>());
+}
+
+template<class A, class U, int N>
+inline void T2rhs1_divide_equals_generic(A &iter, const U &u, const Number<N> &N1,
+				  const Number<1> &N2)
+{
+  iter(0,N)/=u;
+}
+
+template<class A, class T, int Dim1, char i, int N>
+template<class U> inline
+const Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i> & 
+Tensor1_Expr<Tensor2_number_rhs_1<A,T,N>,T,Dim1,i>::operator/=(const U &u)
+{
+  T2rhs1_divide_equals_generic(iter,u,Number<N>(),Number<Dim1>());
+  return *this;
+}
+
+
+/* Specializations for Tensor3_dg_number_rhs_12's */
+
+template<class A, class B, class U, int Dim, char i, int N1, int N2, int Current_Dim>
+inline void T3dgrhs12_equals_T1(A &iter,
+				const Tensor1_Expr<B,U,Dim,i> &result,
+				const Number<N1> &NN1,
+				const Number<N2> &NN2,
+				const Number<Current_Dim> &ND)
+{
+  iter(Current_Dim-1,N1,N2)=result(Current_Dim-1);
+  T3dgrhs12_equals_T1(iter,result,NN1,NN2,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class U, int Dim, char i, int N1, int N2>
+inline void T3dgrhs12_equals_T1(A &iter,
+				const Tensor1_Expr<B,U,Dim,i> &result,
+				const Number<N1> &NN1,
+				const Number<N2> &NN2,
+				const Number<1> &ND)
+{
+  iter(0,N1,N2)=result(0);
+}
+
+template<class A, class T, int Dim, char i, int N1, int N2>
+template<class B, class U> inline
+const Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i> & 
+Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i>
+::operator=(const Tensor1_Expr<B,U,Dim,i> &result)
+{
+  T3dgrhs12_equals_T1(iter,result,Number<N1>(),Number<N2>(),Number<Dim>());
+  return *this;
+}
+
+template<class A, class T, int Dim, char i, int N1, int N2> inline
+const Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i> &
+Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i>
+::operator=(const Tensor1_Expr<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T,Dim,i>
+	    &result)
+{
+  return operator=<Tensor3_dg_number_rhs_12<A,T,N1,N2>,T>(result);
+}
+
+
+/* Specializations for Tensor3_dg_number_rhs_01's */
+
+template<class A, class B, class U, int Dim, char i, int N1, int N2, int Current_Dim>
+inline void T3dgrhs01_equals_T1(A &iter,
+				const Tensor1_Expr<B,U,Dim,i> &result,
+				const Number<N1> &NN1,
+				const Number<N2> &NN2,
+				const Number<Current_Dim> &ND)
+{
+  iter(N1,N2,Current_Dim-1)=result(Current_Dim-1);
+  T3dgrhs01_equals_T1(iter,result,NN1,NN2,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class U, int Dim, char i, int N1, int N2>
+inline void T3dgrhs01_equals_T1(A &iter,
+				const Tensor1_Expr<B,U,Dim,i> &result,
+				const Number<N1> &NN1,
+				const Number<N2> &NN2,
+				const Number<1> &ND)
+{
+  iter(N1,N2,0)=result(0);
+}
+
+template<class A, class T, int Dim, char i, int N1, int N2>
+template<class B, class U> inline
+const Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i> & 
+Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i>
+::operator=(const Tensor1_Expr<B,U,Dim,i> &result)
+{
+  T3dgrhs01_equals_T1(iter,result,Number<N1>(),Number<N2>(),Number<Dim>());
+  return *this;
+}
+
+template<class A, class T, int Dim, char i, int N1, int N2> inline
+const Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i> &
+Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i>
+::operator=(const Tensor1_Expr<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T,Dim,i>
+	    &result)
+{
+  return operator=<Tensor3_dg_number_rhs_01<A,T,N1,N2>,T>(result);
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_and_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_and_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,27 @@
+/* Multiply two Tensor1's together but don't contract, yielding a
+   Tensor1. */
+
+template<class A, class B, class T, class U, int Dim, char i>
+class Tensor1_and_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const Tensor1_Expr<B,U,Dim,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return iterA(N)*iterB(N);
+  }
+
+  Tensor1_and_Tensor1(const Tensor1_Expr<A,T,Dim,i> &a,
+		      const Tensor1_Expr<B,U,Dim,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const Tensor1_and_Tensor1<A,B,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator&(const Tensor1_Expr<A,T,Dim,i> &a, const Tensor1_Expr<B,U,Dim,i> &b)
+{
+  typedef const Tensor1_and_Tensor1<A,B,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_carat_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_carat_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,27 @@
+/* Multiplies two Tensor1's together yielding a Tensor2_symmetric. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor1_carat_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const Tensor1_Expr<B,U,Dim,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1)*iterB(N2);
+  }
+
+  Tensor1_carat_Tensor1(const Tensor1_Expr<A,T,Dim,i> &a,
+			const Tensor1_Expr<B,U,Dim,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const Tensor1_carat_Tensor1<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator^(const Tensor1_Expr<A,T,Dim,i> &a, const Tensor1_Expr<B,U,Dim,j> &b)
+{
+  typedef const Tensor1_carat_Tensor1<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_constructor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_constructor.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,41 @@
+/* A helper class that allows simple initialization of the Tensor1,
+   but only if it has the correct number of elements. */
+
+template<class T, int Tensor_Dim>
+class Tensor1_constructor;
+
+template<class T>
+class Tensor1_constructor<T,2>
+{
+public:
+  Tensor1_constructor(T data[], T d0, T d1)
+  {
+    data[0]=d0;
+    data[1]=d1;
+  }
+};
+
+template<class T>
+class Tensor1_constructor<T,3>
+{
+public:
+  Tensor1_constructor(T data[], T d0, T d1, T d2)
+  {
+    data[0]=d0;
+    data[1]=d1;
+    data[2]=d2;
+  }
+};
+
+template<class T>
+class Tensor1_constructor<T,4>
+{
+public:
+  Tensor1_constructor(T data[], T d0, T d1, T d2, T d3)
+  {
+    data[0]=d0;
+    data[1]=d1;
+    data[2]=d2;
+    data[3]=d3;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_divide_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_divide_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,30 @@
+/* Divides a Tensor1 by a generic, yielding a Tensor1.  Usually used
+   for doubles, but could be used for complex, etc.  All that it
+   requires is that you can add an element of the Tensor1 to it.  */
+
+/* A(i) / d0 -> Tensor1 */
+
+template<class A, class T, class U, int Dim, char i>
+class Tensor1_divide_generic
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return iterA(N)/d;
+  }
+
+  Tensor1_divide_generic(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const Tensor1_divide_generic<A,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator/(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0)
+{
+  typedef const Tensor1_divide_generic<A,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,d0));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_minus_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_minus_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,27 @@
+/* Subtracts a Tensor1 from a Tensor1, yielding a Tensor1. */
+
+template<class A, class B, class T, class U, int Dim, char i>
+class Tensor1_minus_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const Tensor1_Expr<B,U,Dim,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return iterA(N)-iterB(N);
+  }
+
+  Tensor1_minus_Tensor1(const Tensor1_Expr<A,T,Dim,i> &a,
+			const Tensor1_Expr<B,U,Dim,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, char i, int Dim>
+inline const Tensor1_Expr<const Tensor1_minus_Tensor1<A,B,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator-(const Tensor1_Expr<A,T,Dim,i> &a, const Tensor1_Expr<B,U,Dim,i> &b)
+{
+  typedef const Tensor1_minus_Tensor1<A,B,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_minus_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_minus_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,31 @@
+/* Subtracts a Tensor1 from a generic (or vice versa), yielding a
+   Tensor1.  Usually used for doubles, but could be used for complex,
+   etc.  All that it requires is that you can add an element of the
+   Tensor1 to it.  */
+
+/* A(i) - d0 -> Tensor1 */
+
+template<class A, class T, class U, int Dim, char i>
+class Tensor1_minus_generic
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return iterA(N)-d;
+  }
+
+  Tensor1_minus_generic(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const Tensor1_minus_generic<A,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator-(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0)
+{
+  typedef const Tensor1_minus_generic<A,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,d0));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_or_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_or_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,27 @@
+/* Adds two Tensor1's together yielding a Tensor2_symmetric. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor1_or_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const Tensor1_Expr<B,U,Dim,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1)+iterB(N2);
+  }
+
+  Tensor1_or_Tensor1(const Tensor1_Expr<A,T,Dim,i> &a,
+			const Tensor1_Expr<B,U,Dim,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const Tensor1_or_Tensor1<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator||(const Tensor1_Expr<A,T,Dim,i> &a, const Tensor1_Expr<B,U,Dim,j> &b)
+{
+  typedef const Tensor1_or_Tensor1<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_plus_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_plus_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,27 @@
+/* Adds two Tensor1's together, yielding a Tensor1. */
+
+template<class A, class B, class T, class U, int Dim, char i>
+class Tensor1_plus_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const Tensor1_Expr<B,U,Dim,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return iterA(N)+iterB(N);
+  }
+
+  Tensor1_plus_Tensor1(const Tensor1_Expr<A,T,Dim,i> &a,
+		       const Tensor1_Expr<B,U,Dim,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, char i, int Dim>
+inline const Tensor1_Expr<const Tensor1_plus_Tensor1<A,B,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator+(const Tensor1_Expr<A,T,Dim,i> &a, const Tensor1_Expr<B,U,Dim,i> &b)
+{
+  typedef const Tensor1_plus_Tensor1<A,B,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_plus_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_plus_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,41 @@
+/* Adds a Tensor1 to a generic (or vice versa), yielding a Tensor1.
+   Usually used for doubles, but could be used for complex, etc.  All
+   that it requires is that you can add an element of the Tensor1 to
+   it.  */
+
+/* A(i) + d0 -> Tensor1 */
+
+template<class A, class T, class U, int Dim, char i>
+class Tensor1_plus_generic
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return iterA(N)+d;
+  }
+
+  Tensor1_plus_generic(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const Tensor1_plus_generic<A,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator+(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0)
+{
+  typedef const Tensor1_plus_generic<A,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,d0));
+}
+
+/* d0 + A(i) -> Tensor1 */
+
+template<class A, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const Tensor1_plus_generic<A,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator+(const U &d0, const Tensor1_Expr<A,T,Dim,i> &a)
+{
+  typedef const Tensor1_plus_generic<A,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_pointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_pointer.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,97 @@
+/* A version for pointers, useful for previously
+   constructed arrays. */
+
+template <class T, int Tensor_Dim>
+class Tensor1<T*,Tensor_Dim>
+{
+  /* Note that the T *'s are mutable, so the pointer can change,
+     allowing iterating over a array. */
+
+  mutable T * restrict data[Tensor_Dim];
+public:
+  /* Initializations for varying numbers of elements, with each one
+     defined for a particular Tensor_Dim.  To initialize a different
+     dimension, just add the appropriate constructor and call to
+     the Tensor1_constructor constructor. */
+  Tensor1(T *d0, T *d1)
+  {
+    Tensor1_constructor<T* restrict,Tensor_Dim>(data,d0,d1);
+  }
+  Tensor1(T *d0, T *d1, T *d2)
+  {
+    Tensor1_constructor<T* restrict,Tensor_Dim>(data,d0,d1,d2);
+  }
+  Tensor1(T *d0, T *d1, T *d2, T *d3)
+  {
+    Tensor1_constructor<T* restrict,Tensor_Dim>(data,d0,d1,d2,d3);
+  }
+
+  /* There are two operator(int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N>=Tensor_Dim || N<0)
+      {
+	std::cerr << "Bad index in Tensor1<T*," << Tensor_Dim
+		  << ">.operator(" << N << ")" << std::endl;
+	abort();
+      }
+#endif
+    return *data[N];
+  }
+  T operator()(const int N) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N>=Tensor_Dim || N<0)
+      {
+	std::cerr << "Bad index in Tensor1<T*," << Tensor_Dim
+		  << ">.operator(" << N << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return *data[N];
+  }
+  T * ptr(const int N) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N>=Tensor_Dim || N<0)
+      {
+	std::cerr << "Bad index in Tensor1<T*," << Tensor_Dim
+		  << ">.ptr(" << N << ")" << std::endl;
+	abort();
+      }
+#endif
+    return data[N];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  template<char i, int Dim>
+  Tensor1_Expr<Tensor1<T*,Tensor_Dim>,T,Dim,i>
+  operator()(const Index<i,Dim> &index)
+  {
+    return Tensor1_Expr<Tensor1<T*,Tensor_Dim>,T,Dim,i>(*this);
+  }
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor1<T*,Tensor_Dim>,T,Dim,i>
+  operator()(const Index<i,Dim> &index) const
+  {
+    return Tensor1_Expr<const Tensor1<T*,Tensor_Dim>,T,Dim,i>(*this);
+  }
+
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+
+  const Tensor1 & operator++() const
+  {
+    for(int i=0;i<Tensor_Dim;++i)
+      ++data[i];
+    return *this;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_times_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_times_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,55 @@
+/* Multiplies two Tensor1's together yielding a T (int, double, etc.)
+   or a Tensor2. */
+
+/* A(i)*B(i) -> T */
+
+template<class A, class B, class T, class U, int Dim, char i, int Current_Dim>
+inline const typename promote<T,U>::V T1_times_T1(const Tensor1_Expr<A,T,Dim,i> &a,
+				      const Tensor1_Expr<B,U,Dim,i> &b,
+				      const Number<Current_Dim> &N)
+{
+  return a(Current_Dim-1)*b(Current_Dim-1) + 
+    T1_times_T1(a,b,Number<Current_Dim-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i>
+inline const typename promote<T,U>::V T1_times_T1(const Tensor1_Expr<A,T,Dim,i> &a,
+				      const Tensor1_Expr<B,U,Dim,i> &b,
+				      const Number<1> &N)
+{
+  return a(0)*b(0);
+}
+
+template<class A, class B, class T, class U, int Dim, char i>
+inline const typename promote<T,U>::V operator*(const Tensor1_Expr<A,T,Dim,i> &a,
+				 const Tensor1_Expr<B,U,Dim,i> &b)
+{
+  return T1_times_T1(a,b,Number<Dim>());
+}
+
+/* A(i)*B(j) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor1_times_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim0,i> iterA;
+  const Tensor1_Expr<B,U,Dim1,j> iterB;
+public:
+  Tensor1_times_Tensor1(const Tensor1_Expr<A,T,Dim0,i> &a,
+			const Tensor1_Expr<B,U,Dim1,j> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1)*iterB(N2);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor2_Expr<const Tensor1_times_Tensor1<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor1_Expr<A,T,Dim0,i> &a, const Tensor1_Expr<B,U,Dim1,j> &b)
+{
+  typedef const Tensor1_times_Tensor1<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_times_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_times_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,41 @@
+/* Multipliess a Tensor1 by a generic (or vice versa), yielding a Tensor1.
+   Usually used for doubles, but could be used for complex, etc.  All
+   that it requires is that you can add an element of the Tensor1 to
+   it.  */
+
+/* A(i) * d0 -> Tensor1 */
+
+template<class A, class T, class U, int Dim, char i>
+class Tensor1_times_generic
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return iterA(N)*d;
+  }
+
+  Tensor1_times_generic(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const Tensor1_times_generic<A,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0)
+{
+  typedef const Tensor1_times_generic<A,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,d0));
+}
+
+/* d0 * A(i) -> Tensor1 */
+
+template<class A, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const Tensor1_times_generic<A,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const U &d0, const Tensor1_Expr<A,T,Dim,i> &a)
+{
+  typedef const Tensor1_times_generic<A,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/Tensor1_value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/Tensor1_value.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,73 @@
+/* The general version, not for pointers. */
+
+template <class T, int Tensor_Dim>
+class Tensor1
+{
+  T data[Tensor_Dim];
+public:
+  /* Initializations for varying numbers of elements, with each one
+     defined for a particular Tensor_Dim.  To initialize a different
+     dimension, just add the appropriate constructor and call to
+     the Tensor1_constructor constructor. */
+  Tensor1(T d0, T d1)
+  {
+    Tensor1_constructor<T,Tensor_Dim>(data,d0,d1);
+  }
+  Tensor1(T d0, T d1, T d2)
+  {
+    Tensor1_constructor<T,Tensor_Dim>(data,d0,d1,d2);
+  }
+  Tensor1(T d0, T d1, T d2, T d3)
+  {
+    Tensor1_constructor<T,Tensor_Dim>(data,d0,d1,d2,d3);
+  }
+
+  Tensor1() {}
+
+  /* There are two operator(int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N>=Tensor_Dim || N<0)
+      {
+	std::cerr << "Bad index in Tensor1<T," << Tensor_Dim
+		  << ">.operator(" << N << ")" << std::endl;
+	abort();
+      }
+#endif
+    return data[N];
+  }
+  T operator()(const int N) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N>=Tensor_Dim || N<0)
+      {
+	std::cerr << "Bad index in Tensor1<T," << Tensor_Dim
+		  << ">.operator(" << N << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return data[N];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  template<char i, int Dim>
+  Tensor1_Expr<Tensor1<T,Tensor_Dim>,T,Dim,i>
+  operator()(const Index<i,Dim> &index)
+  {
+    return Tensor1_Expr<Tensor1<T,Tensor_Dim>,T,Dim,i>(*this);
+  }
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor1<T,Tensor_Dim>,T,Dim,i>
+  operator()(const Index<i,Dim> &index) const
+  {
+    return Tensor1_Expr<const Tensor1<T,Tensor_Dim>,T,Dim,i>(*this);
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor1/dTensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/dTensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,63 @@
+/* Takes a derivative of a Tensor1, yielding a Tensor2. */
+
+//  template<class T, int Dim, char i, char j>
+//  class dTensor1
+//  {
+//    const Tensor1<T*,Dim> &a;
+//    const int di,dj,dk;
+//    const double dx,dy,dz;
+//  public:
+//    typename promote<T,double>::V operator()(const int N1, const int N2) const
+//    {
+//      return N2==0 ? (*(a.ptr(N1)+di)-*(a.ptr(N1)-di))*dx*0.5
+//        : (N2==1 ? (*(a.ptr(N1)+dj)-*(a.ptr(N1)-dj))*dy*0.5
+//  	 : (*(a.ptr(N1)+dk)-*(a.ptr(N1)-dk))*dz*0.5);
+//    }
+//    dTensor1(const Tensor1<T*,Dim> &A,
+//  	   const int Di, const int Dj, const int Dk,
+//  	   const double Dx, const double Dy, const double Dz):
+//      a(A), di(Di), dj(Dj), dk(Dk), dx(Dx), dy(Dy), dz(Dz) {}
+//  };
+
+//  template<class T, int Dim, char i, char j>
+//  inline const Tensor2_Expr<const dTensor1<T,Dim,i,j>,
+//    typename promote<T,double>::V,Dim,3,i,j>
+//  d(const Tensor1<T*,Dim> &a, const Index<i,Dim> index1, const Index<j,3> index2,
+//    const int &di, const int &dj, const int &dk,
+//    const double &dx, const double &dy, const double &dz)
+//  {
+//    typedef const dTensor1<T,Dim,i,j> TensorExpr;
+//    return Tensor2_Expr<TensorExpr,typename promote<T,double>::V,Dim,3,i,j>
+//      (TensorExpr(a,di,dj,dk,dx,dy,dz));
+//  }
+
+
+template<class T, int Dim0, int Dim1, char i, char j>
+class dTensor1
+{
+  const Tensor1<T*,Dim0> &a;
+  const Tensor1<int,Dim1> &d_ijk;
+  const Tensor1<double,Dim1> &d_xyz;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2) const
+  {
+    return (*(a.ptr(N1)+d_ijk(N2))-*(a.ptr(N1)-d_ijk(N2)))*d_xyz(N2)*0.5;
+  }
+  dTensor1(const Tensor1<T*,Dim0> &A,
+	   const Tensor1<int,Dim1> &D_ijk,
+	   const Tensor1<double,Dim1> &D_xyz)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz) {}
+};
+
+template<class T, int Dim0, int Dim1, char i, char j>
+inline const Tensor2_Expr<const dTensor1<T,Dim0,Dim1,i,j>,
+  typename promote<T,double>::V,Dim0,Dim1,i,j>
+d(const Tensor1<T*,Dim0> &a, const Index<i,Dim0> index1,
+  const Index<j,Dim1> index2,
+  const Tensor1<int,Dim1> &d_ijk,
+  const Tensor1<double,Dim1> &d_xyz)
+{
+  typedef const dTensor1<T,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,double>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,d_ijk,d_xyz));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/d_one_sided_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/d_one_sided_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* Takes a one-sided derivative of a Tensor1 in a particular
+   direction, yieldind a Tensor1. */
+
+template<class T, int Dim, char i, int axis>
+class d_one_sided_Tensor1
+{
+  const Tensor1<T*,Dim> &a;
+  const int di,dj,dk;
+  const double dx,dy,dz;
+public:
+  typename promote<T,double>::V operator()(const int N1) const
+  {
+    return axis==0 ? (a(N1)-*(a.ptr(N1)-di))*dx
+      : (axis==1 ? (a(N1)-*(a.ptr(N1)-dj))*dy
+	 : (a(N1)-*(a.ptr(N1)-dk))*dz);
+  }
+  d_one_sided_Tensor1(const Tensor1<T*,Dim> &A,
+		      const int Di, const int Dj, const int Dk,
+		      const double Dx, const double Dy, const double Dz):
+    a(A), di(Di), dj(Dj), dk(Dk), dx(Dx), dy(Dy), dz(Dz) {}
+};
+
+template<class T, int Dim, char i, int axis>
+inline const Tensor1_Expr<const d_one_sided_Tensor1<T,Dim,i,axis>,
+  typename promote<T,double>::V,Dim,i>
+d_one_sided(const Tensor1<T*,Dim> &a, const Number<axis> n1,
+	    const Index<i,Dim> index1,
+	    const int &di, const int &dj, const int &dk,
+	    const double &dx, const double &dy, const double &dz)
+{
+  typedef const d_one_sided_Tensor1<T,Dim,i,axis> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,double>::V,Dim,i>
+    (TensorExpr(a,di,dj,dk,dx,dy,dz));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/ddTensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/ddTensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,46 @@
+/* Takes a second derivative of a Tensor1, yielding a Tensor3_dg, but
+   with it's indices switched around so that it has the symmetries of
+   a Tensor3_christof. */
+
+template<class T, int Dim0, int Dim12, char i, char j, char k>
+class ddTensor1
+{
+  const Tensor1<T*,Dim0> &a;
+  const Tensor1<int,Dim12> &d_ijk;
+  const Tensor1<double,Dim12> &d_xyz;
+public:
+
+  /* Note the indices switch here. */
+
+  typename promote<T,double>::V operator()(const int N2, const int N3,
+				  const int N1) const
+  {
+    return
+      N2==N3 ? (*(a.ptr(N1)+d_ijk(N2))-2*a(N1)+*(a.ptr(N1)-d_ijk(N2)))
+      *d_xyz(N2)*d_xyz(N2) :
+      (*(a.ptr(N1)+d_ijk(N2)+d_ijk(N3))
+       - *(a.ptr(N1)-d_ijk(N2)+d_ijk(N3))
+       - *(a.ptr(N1)+d_ijk(N2)-d_ijk(N3))
+       + *(a.ptr(N1)-d_ijk(N2)-d_ijk(N3)))*d_xyz(N2)*d_xyz(N3)*0.25;
+  }
+  ddTensor1(const Tensor1<T*,Dim0> &A,
+	    const Tensor1<int,Dim12> &D_ijk,
+	    const Tensor1<double,Dim12> &D_xyz)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz) {}
+};
+
+/* Note that the indices are mixed up here to convert between being
+   symmetric on the last two indices to the first two indices. */
+
+
+template<class T, int Dim0, int Dim12, char i, char j, char k>
+inline const Tensor3_dg_Expr<const ddTensor1<T,Dim0,Dim12,i,j,k>,
+  typename promote<T,double>::V,Dim0,Dim12,i,j,k>
+dd(const Tensor1<T*,Dim0> &a, const Index<k,Dim0> index0,
+   const Index<i,Dim12> index1, const Index<j,Dim12> index2,
+   const Tensor1<int,Dim12> &d_ijk, const Tensor1<double,Dim12> &d_xyz)
+{
+  typedef const ddTensor1<T,Dim0,Dim12,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,double>::V,Dim0,Dim12,i,j,k>
+    (TensorExpr(a,d_ijk,d_xyz));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/diffusion_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/diffusion_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+/* Computes 2*del^2 of a Tensor1_ptr but uses diagonal derivatives for
+   half of it.  Yields a Tensor1. */
+
+template<class T, int Dim, char i>
+class diffusion_Tensor1
+{
+  const Tensor1<T*,Dim> &a;
+  const int di,dj,dk;
+  const double dx;
+public:
+  typename promote<T,double>::V operator()(const int N1) const
+  {
+    return
+      ((*(a.ptr(N1)+di) - 2*a(N1) + *(a.ptr(N1)-di))
+       + (*(a.ptr(N1)+dj) - 2*a(N1) + *(a.ptr(N1)-dj))
+       + (*(a.ptr(N1)+dk) - 2*a(N1) + *(a.ptr(N1)-dk))
+       + ((*(a.ptr(N1)+di+dj) + *(a.ptr(N1)+di-dj)
+	   + *(a.ptr(N1)-di+dj) + *(a.ptr(N1)-di-dj)
+	   - 4*a(N1))
+	  + (*(a.ptr(N1)+di+dk) + *(a.ptr(N1)+di-dk)
+	     + *(a.ptr(N1)-di+dk) + *(a.ptr(N1)-di-dk)
+	     - 4*a(N1))
+	  + (*(a.ptr(N1)+dj+dk) + *(a.ptr(N1)+dj-dk)
+	     + *(a.ptr(N1)-dj+dk) + *(a.ptr(N1)-dj-dk)
+	     - 4*a(N1)))/(std::sqrt(2.0)))*dx*dx;
+  }
+  diffusion_Tensor1(const Tensor1<T*,Dim> &A, const int Di,
+		    const int Dj, const int Dk, const double Dx):
+    a(A), di(Di), dj(Dj), dk(Dk), dx(Dx) {}
+};
+
+template<class T, int Dim, char i>
+inline const Tensor1_Expr<const diffusion_Tensor1<T,Dim,i>,
+  typename promote<T,double>::V,Dim,i>
+diffusion(const Tensor1<T*,Dim> &a, const Index<i,Dim> index1,
+	  const int &di, const int &dj, const int &dk,
+	  const double &dx)
+{
+  typedef const diffusion_Tensor1<T,Dim,i> Tensor_Expr;
+  return Tensor1_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i>
+    (Tensor_Expr(a,di,dj,dk,dx));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/generic_minus_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/generic_minus_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,26 @@
+/* Subtracts a Tensor1 from a generic, yielding a Tensor1. */
+
+template<class A, class T, class U, int Dim, char i>
+class generic_minus_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N) const
+  {
+    return d-iterA(N);
+  }
+
+  generic_minus_Tensor1(const Tensor1_Expr<A,T,Dim,i> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i>
+inline const Tensor1_Expr<const generic_minus_Tensor1<A,T,U,Dim,i>,
+  typename promote<T,U>::V,Dim,i>
+operator-(const U &d0, const Tensor1_Expr<A,T,Dim,i> &a)
+{
+  typedef const generic_minus_Tensor1<A,T,U,Dim,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,d0));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor1/interpolate_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/interpolate_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,53 @@
+/* Interpolates to (i0+distance[0], j0+distance[1], k0+distance[2])
+   yielding a Tensor1.  (i0,j0,k0) are 3D array coordinates,
+   conjugate==1-distance, and (di,dj,dk) are the stride of the array
+   coordinates.  It is assumed that the Tensor1<T*,Dim> is zero
+   centered. */
+
+template<class T, int Dim, char i>
+class interpolate_Tensor1
+{
+  const Tensor1<T*,Dim> &a;
+  const int di,dj,dk,i0,j0,k0;
+  const double *distance, *conjugate;
+public:
+  typename promote<T,double>::V operator()(const int N1) const
+  {
+  return 
+    conjugate[0]*conjugate[1]*conjugate[2]
+    * (*(a.ptr(N1) + di*i0 + dj*j0 + dk*k0))
+    + distance[0]*conjugate[1]*conjugate[2]
+    * (*(a.ptr(N1) + di*(i0+1) + dj*(j0) + dk*(k0)))
+    + conjugate[0]*distance[1]*conjugate[2]
+    * (*(a.ptr(N1) + di*(i0) + dj*(j0+1) + dk*(k0)))
+    + distance[0]*distance[1]*conjugate[2]
+    * (*(a.ptr(N1) + di*(i0+1) + dj*(j0+1) + dk*(k0)))
+    + conjugate[0]*conjugate[1]*distance[2]
+    * (*(a.ptr(N1) + di*(i0) + dj*(j0) + dk*(k0+1)))
+    + distance[0]*conjugate[1]*distance[2]
+    * (*(a.ptr(N1) + di*(i0+1) + dj*(j0) + dk*(k0+1)))
+    + conjugate[0]*distance[1]*distance[2]
+    * (*(a.ptr(N1) + di*(i0) + dj*(j0+1) + dk*(k0+1)))
+    + distance[0]*distance[1]*distance[2]
+    * (*(a.ptr(N1) + di*(i0+1) + dj*(j0+1) + dk*(k0+1)));
+  }
+  interpolate_Tensor1(const Tensor1<T*,Dim> &A, const int Di,
+		      const int Dj, const int Dk, const int I0,
+		      const int J0, const int K0, const double Distance[3],
+		      const double Conjugate[3]):
+    a(A), di(Di), dj(Dj), dk(Dk), i0(I0), j0(J0), k0(K0),
+    distance(Distance), conjugate(Conjugate) {}
+};
+
+template<class T, int Dim, char i>
+inline const Tensor1_Expr<const interpolate_Tensor1<T,Dim,i>,
+  typename promote<T,double>::V,Dim,i>
+interpolate(const Tensor1<T*,Dim> &a, const Index<i,Dim> index1,
+	    const int &di, const int &dj, const int &dk,
+	    const int &i0, const int &j0, const int &k0,
+	    const double distance[3], const double conjugate[3])
+{
+  typedef const interpolate_Tensor1<T,Dim,i> Tensor_Expr;
+  return Tensor1_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i>
+    (Tensor_Expr(a,di,dj,dk,i0,j0,k0,distance,conjugate));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor1/minus_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor1/minus_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,22 @@
+/* Declares a wrapper class for the unary minus (-) operator. */
+
+template<class A, class T, int Dim, char i>
+class minus_Tensor1
+{
+  const Tensor1_Expr<A,T,Dim,i> iterA;
+public:
+  T operator()(const int N) const
+  {
+    return -iterA(N);
+  }
+
+  minus_Tensor1(const Tensor1_Expr<A,T,Dim,i> &a): iterA(a) {}
+};
+
+template<class A, class T, int Dim, char i>
+inline const Tensor1_Expr<const minus_Tensor1<A,T,Dim,i>,T,Dim,i>
+operator-(const Tensor1_Expr<A,T,Dim,i> &a)
+{
+    typedef const minus_Tensor1<A,T,Dim,i> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(a));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,10 @@
+/* Declarations for Tensor2. */
+
+#include "Tensor2/Tensor2_number.h"
+#include "Tensor2/Tensor2_numeral.h"
+
+#include "Tensor2/Tensor2_constructor.h"
+#include "Tensor2/Tensor2_value.h"
+#include "Tensor2/Tensor2_pointer.h"
+
+#include "Tensor2/Tensor2_Expr.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,134 @@
+/* Declares a wrapper class for rank 2 Tensor expressions.  I
+   specialize it for when I wrap a simple Tensor2 or Tensor2_ptr so
+   that it has a reference to the Tensor2(_ptr) and not a copy.
+   Otherwise assignment wouldn't work. */
+
+#include "Tensor2_plus_Tensor2.h"
+#include "Tensor2_minus_Tensor2.h"
+#include "Tensor2_or_Tensor2.h"
+#include "Tensor2_times_Tensor2.h"
+#include "Tensor2_carat_Tensor2.h"
+#include "Tensor2_times_Tensor1.h"
+#include "Tensor2_and_Tensor1.h"
+#include "Tensor2_times_generic.h"
+#include "Tensor2_divide_generic.h"
+#include "Tensor2_transform.h"
+#include "minus_Tensor2.h"
+#include "conj_Tensor2.h"
+
+template<class A, class T, int Dim0, int Dim1, char i, char j>
+class Tensor2_Expr
+{
+  A iter;
+public:
+  Tensor2_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2) const
+  {
+    return iter(N1,N2);
+  }
+};
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+class Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>
+{
+  Tensor2<A,Dim0,Dim1,layout> &iter;
+public:
+  Tensor2_Expr(Tensor2<A,Dim0,Dim1,layout> &a): iter(a) {}
+  T & operator()(const int N1, const int N2)
+  {
+    return iter(N1,N2);
+  }
+  T operator()(const int N1, const int N2) const
+  {
+    return iter(N1,N2);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result);
+  
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator=(const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &result);
+  
+  template<class B, class U>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator+=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result);
+
+  template<class B, class U>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator-=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result);
+
+  /* This is for when the indices are switched (i,j) -> (j,i). */
+
+  template<class B, class U>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator=(const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result);
+
+  template<class B, class U>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator+=(const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result);
+
+  template<class B, class U>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator-=(const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result);
+
+  /* This is for int's, double's, etc. */
+
+  template <class B>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator=(const B &d);
+
+  template <class B>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator+=(const B &d);
+
+  template <class B>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator-=(const B &d);
+
+  template <class B>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator*=(const B &d);
+
+  template <class B>
+  const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+  operator/=(const B &d);
+};
+
+/* Specialized for Tensor3_dg_number_rhs_0 (Tensor3_dg with the
+   first or second index explicitly given). */
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, int N>
+class Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j>
+{
+  A &iter;
+public:
+  Tensor2_Expr(A &a): iter(a) {}
+  T & operator()(const int N1, const int N2)
+  {
+    return iter(N,N1,N2);
+  }
+  T operator()(const int N1, const int N2) const
+  {
+    return iter(N,N1,N2);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j> &
+  operator=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result);
+
+  const Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j> &
+  operator=(const Tensor2_Expr<Tensor3_dg_number_rhs_0
+	    <A,T,N>,T,Dim0,Dim1,i,j> &result);
+
+};
+
+#include "Tensor2_Expr_equals.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_Expr_equals.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_Expr_equals.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,516 @@
+/* Various assignment operators. */
+
+/* T2=T2 */
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void T2_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<Current_Dim0> &N0,
+			 const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)=result(Current_Dim0-1,Current_Dim1-1);
+  T2_equals_T2(iter,result,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim1>
+inline void T2_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0,
+			 const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)=result(0,Current_Dim1-1);
+  T2_equals_T2(iter,result,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j>
+inline void T2_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0,
+			 const Number<1> &N1)
+{
+  iter(0,0)=result(0,0);
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class B, class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result)
+{
+  T2_equals_T2(iter,result,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2=T2_Expr(T2) */
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+inline const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator=(const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &result)
+{
+  return operator=<Tensor2<A,Dim0,Dim1,layout>,T>(result);
+}
+
+/* T2+=T2 */
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void T2_plus_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<Current_Dim0> &N0,
+			 const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)+=result(Current_Dim0-1,Current_Dim1-1);
+  T2_plus_equals_T2(iter,result,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim1>
+inline void T2_plus_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0,
+			 const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)+=result(0,Current_Dim1-1);
+  T2_plus_equals_T2(iter,result,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j>
+inline void T2_plus_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0,
+			 const Number<1> &N1)
+{
+  iter(0,0)+=result(0,0);
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class B, class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator+=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result)
+{
+  T2_plus_equals_T2(iter,result,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2-=T2 */
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void T2_minus_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<Current_Dim0> &N0,
+			 const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)-=result(Current_Dim0-1,Current_Dim1-1);
+  T2_minus_equals_T2(iter,result,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim1>
+inline void T2_minus_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0,
+			 const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)-=result(0,Current_Dim1-1);
+  T2_minus_equals_T2(iter,result,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j>
+inline void T2_minus_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0,
+			 const Number<1> &N1)
+{
+  iter(0,0)-=result(0,0);
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class B, class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator-=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result)
+{
+  T2_minus_equals_T2(iter,result,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* This is for when the indices are switched (i,j) -> (j,i). */
+
+/* T2(i,j)=T2(j,i) */
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void T2_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<Current_Dim0> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)=result(Current_Dim1-1,Current_Dim0-1);
+  T2_equals_switched_T2(iter,result,Number<Current_Dim0-1>(),
+			Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim1>
+inline void T2_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)=result(Current_Dim1-1,0);
+  T2_equals_switched_T2(iter,result,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j>
+inline void T2_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)=result(0,0);
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class B, class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator=(const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result)
+{
+  T2_equals_switched_T2(iter,result,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2(i,j)+=T2(j,i) */
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void T2_plus_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<Current_Dim0> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)+=result(Current_Dim1-1,Current_Dim0-1);
+  T2_plus_equals_switched_T2(iter,result,Number<Current_Dim0-1>(),
+			Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim1>
+inline void T2_plus_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)+=result(Current_Dim1-1,0);
+  T2_plus_equals_switched_T2(iter,result,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j>
+inline void T2_plus_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)+=result(0,0);
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class B, class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator+=(const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result)
+{
+  T2_plus_equals_switched_T2(iter,result,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2(i,j)-=T2(j,i) */
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void T2_minus_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<Current_Dim0> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)-=result(Current_Dim1-1,Current_Dim0-1);
+  T2_minus_equals_switched_T2(iter,result,Number<Current_Dim0-1>(),
+			Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j,
+  int Current_Dim1>
+inline void T2_minus_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)-=result(Current_Dim1-1,0);
+  T2_minus_equals_switched_T2(iter,result,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j>
+inline void T2_minus_equals_switched_T2
+(A &iter, const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result,
+ const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)-=result(0,0);
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class B, class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator-=(const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &result)
+{
+  T2_minus_equals_switched_T2(iter,result,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* For int's, double's, etc. */
+
+/* T2=U */
+
+template<class A, class U, int Dim0, int Dim1,
+  int Current_Dim0, int Current_Dim1, Layout layout>
+inline void T2_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<Current_Dim0> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)=u;
+  T2_equals_generic(iter,u,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, int Current_Dim1, Layout layout>
+inline void T2_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)=u;
+  T2_equals_generic(iter,u,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, Layout layout>
+inline void T2_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)=u;
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator=(const U &u)
+{
+  T2_equals_generic(iter,u,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2+=U */
+
+template<class A, class U, int Dim0, int Dim1,
+  int Current_Dim0, int Current_Dim1, Layout layout>
+inline void T2_plus_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+				   const Number<Current_Dim0> &N0,
+				   const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)+=u;
+  T2_plus_equals_generic(iter,u,Number<Current_Dim0-1>(),
+			 Number<Current_Dim1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, int Current_Dim1, Layout layout>
+inline void T2_plus_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+				   const Number<1> &N0,
+				   const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)+=u;
+  T2_plus_equals_generic(iter,u,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, Layout layout>
+inline void T2_plus_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+				   const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)+=u;
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator+=(const U &u)
+{
+  T2_plus_equals_generic(iter,u,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2-=U */
+
+template<class A, class U, int Dim0, int Dim1,
+  int Current_Dim0, int Current_Dim1, Layout layout>
+inline void T2_minus_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<Current_Dim0> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)-=u;
+  T2_minus_equals_generic(iter,u,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, int Current_Dim1, Layout layout>
+inline void T2_minus_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)-=u;
+  T2_minus_equals_generic(iter,u,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, Layout layout>
+inline void T2_minus_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)-=u;
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator-=(const U &u)
+{
+  T2_minus_equals_generic(iter,u,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2*=U */
+
+template<class A, class U, int Dim0, int Dim1,
+  int Current_Dim0, int Current_Dim1, Layout layout>
+inline void T2_times_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<Current_Dim0> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)*=u;
+  T2_times_equals_generic(iter,u,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, int Current_Dim1, Layout layout>
+inline void T2_times_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)*=u;
+  T2_times_equals_generic(iter,u,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, Layout layout>
+inline void T2_times_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)*=u;
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator*=(const U &u)
+{
+  T2_times_equals_generic(iter,u,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+/* T2/=U */
+
+template<class A, class U, int Dim0, int Dim1,
+  int Current_Dim0, int Current_Dim1, Layout layout>
+inline void T2_divide_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<Current_Dim0> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)/=u;
+  T2_divide_equals_generic(iter,u,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, int Current_Dim1, Layout layout>
+inline void T2_divide_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0,
+			      const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)/=u;
+  T2_divide_equals_generic(iter,u,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class U, int Dim0, int Dim1, Layout layout>
+inline void T2_divide_equals_generic(Tensor2<A,Dim0,Dim1,layout> &iter, const U &u,
+			      const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)/=u;
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, Layout layout>
+template<class U> inline
+const Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor2<A,Dim0,Dim1,layout>,T,Dim0,Dim1,i,j>::
+operator/=(const U &u)
+{
+  T2_divide_equals_generic(iter,u,Number<Dim0>(),Number<Dim1>());
+  return *this;
+}
+
+
+/* Various assignment operators for Tensor3_dg_number_rhs_0.  I have
+   to explicitly declare the second operator= because otherwise the
+   compiler will generate its own and not use the template code. */
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j, int N,
+  int Current_Dim0, int Current_Dim1> inline
+void T3dgrhs0_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<Current_Dim0> &N0,
+			 const Number<Current_Dim1> &N1, const Number<N> &NN)
+{
+  iter(N,Current_Dim0-1,Current_Dim1-1)=result(Current_Dim0-1,Current_Dim1-1);
+  T3dgrhs0_equals_T2(iter,result,Number<Current_Dim0-1>(),
+		      Number<Current_Dim1>(),Number<N>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j, int N,
+  int Current_Dim1> inline
+void T3dgrhs0_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0, const Number<Current_Dim1> &N1,
+			 const Number<N> &NN)
+{
+  iter(N,0,Current_Dim1-1)=result(0,Current_Dim1-1);
+  T3dgrhs0_equals_T2(iter,result,Number<Dim0>(),
+		      Number<Current_Dim1-1>(),Number<N>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim1, char i, char j, int N>
+inline
+void T3dgrhs0_equals_T2(A &iter,
+			 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result,
+			 const Number<1> &N0, const Number<1> &N1,
+			 const Number<N> &NN)
+{
+  iter(N,0,0)=result(0,0);
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, int N>
+template<class B, class U> inline
+const Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j>
+::operator=(const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &result)
+{
+  T3dgrhs0_equals_T2(iter,result,Number<Dim0>(),Number<Dim1>(),Number<N>());
+  return *this;
+}
+
+template<class A, class T, int Dim0, int Dim1, char i, char j, int N> inline
+const Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j> &
+Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j>
+::operator=(const Tensor2_Expr<Tensor3_dg_number_rhs_0<A,T,N>,T,Dim0,Dim1,i,j>
+	    &result)
+{
+  return operator=<Tensor3_dg_number_rhs_0<A,T,N>,T>(result);
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_and_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_and_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,89 @@
+/* Multiply a Tensor1 and a Tensor2 together but don't contract, yielding a
+   Tensor2. */
+
+/* A(i,j) & B(i) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor2_and_Tensor1_0
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor1_Expr<B,U,Dim0,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)*iterB(N1);
+  }
+
+  Tensor2_and_Tensor1_0(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			const Tensor1_Expr<B,U,Dim0,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor2_Expr<const Tensor2_and_Tensor1_0<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator&(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor1_Expr<B,U,Dim0,i> &b)
+{
+  typedef const Tensor2_and_Tensor1_0<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(i) & A(i,j) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor2_Expr<const Tensor2_and_Tensor1_0
+<A,B,T,U,Dim0,Dim1,i,j>,typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator&(const Tensor1_Expr<B,U,Dim0,i> &b,
+	  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a)
+{
+  typedef const Tensor2_and_Tensor1_0<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j) & B(j) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1,
+  char i, char j>
+class Tensor2_and_Tensor1_1
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor1_Expr<B,U,Dim1,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)*iterB(N2);
+  }
+
+  Tensor2_and_Tensor1_1(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			const Tensor1_Expr<B,U,Dim1,j> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1,
+  char i, char j>
+inline const Tensor2_Expr<const Tensor2_and_Tensor1_1
+<A,B,T,U,Dim0,Dim1,i,j>,typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator&(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor1_Expr<B,U,Dim1,j> &b)
+{
+  typedef const Tensor2_and_Tensor1_1<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(j) & A(i,j) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1,
+  char i, char j>
+inline const Tensor2_Expr<const Tensor2_and_Tensor1_1<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator&(const Tensor1_Expr<B,U,Dim1,j> &b,
+	  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a)
+{
+  typedef const Tensor2_and_Tensor1_1<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_carat_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_carat_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,211 @@
+/* Creates a Tensor2_symmetric expression by contracting two Tensor2's
+   together. There are different versions, depending on where the
+   contracting indices are located (i.e. whether it is A(i,j)^B(j,k)
+   or A(i,j)^B(k,j)).  The classes are numbered to differentiate
+   between these.  Thus, A(i,j)^B(j,k) has 10 appended to the name
+   because I count from 0. */
+
+/* A(i,j)^B(j,k) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_carat_Tensor2_10
+{
+  const Tensor2_Expr<A,T,Dim,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim1,Dim,j,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(0,N2);
+  }
+public:
+  Tensor2_carat_Tensor2_10(const Tensor2_Expr<A,T,Dim,Dim1,i,j> &a,
+			   const Tensor2_Expr<B,U,Dim1,Dim,j,k> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_carat_Tensor2_10<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<A,T,Dim,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim1,Dim,j,k> &b)
+{
+  typedef const Tensor2_carat_Tensor2_10<A,B,T,U,Dim,Dim1,i,j,k> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j)^B(k,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_carat_Tensor2_11
+{
+  const Tensor2_Expr<A,T,Dim,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim1,k,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(N2,0);
+  }
+public:
+  Tensor2_carat_Tensor2_11(const Tensor2_Expr<A,T,Dim,Dim1,i,j> &a,
+			   const Tensor2_Expr<B,U,Dim,Dim1,k,j> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_carat_Tensor2_11<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<A,T,Dim,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim1,k,j> &b)
+{
+  typedef const Tensor2_carat_Tensor2_11<A,B,T,U,Dim,Dim1,i,j,k> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(j,i)^B(j,k) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_carat_Tensor2_00
+{
+  const Tensor2_Expr<A,T,Dim1,Dim,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim1,Dim,j,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(0,N2);
+  }
+public:
+  Tensor2_carat_Tensor2_00(const Tensor2_Expr<A,T,Dim1,Dim,j,i> &a,
+			   const Tensor2_Expr<B,U,Dim1,Dim,j,k> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_carat_Tensor2_00<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<A,T,Dim1,Dim,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim1,Dim,j,k> &b)
+{
+  typedef const Tensor2_carat_Tensor2_00<A,B,T,U,Dim,Dim1,i,j,k> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(j,i)^B(k,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_carat_Tensor2_01
+{
+  const Tensor2_Expr<A,T,Dim1,Dim,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim1,k,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(N2,0);
+  }
+public:
+  Tensor2_carat_Tensor2_01(const Tensor2_Expr<A,T,Dim1,Dim,j,i> &a,
+			   const Tensor2_Expr<B,U,Dim,Dim1,k,j> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_carat_Tensor2_01<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<A,T,Dim1,Dim,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim1,k,j> &b)
+{
+  typedef const Tensor2_carat_Tensor2_01<A,B,T,U,Dim,Dim1,i,j,k> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* I don't think that this product actually gives a Tensor4_ddg. */
+
+//  /* A(i,j)^B(k,l) -> Tensor4_ddg(i,k,j,l) */
+
+//  template<class A, class B, class T, class U, int Dim, int Dim1,
+//    char i, char j, char k>
+//  class Tensor2_carat_Tensor2_0213
+//  {
+//    const Tensor2_Expr<A,T,Dim01,Dim23,i,j> iterA;
+//    const Tensor2_Expr<B,U,Dim01,Dim23,k,l> iterB;
+//  public:
+//    Tensor2_carat_Tensor2_0213(const Tensor2_Expr<A,T,Dim01,Dim23,i,j> &a,
+//  			     const Tensor2_Expr<B,U,Dim01,Dim23,k,l> &b):
+//      iterA(a), iterB(b) {}
+//    typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+//  			     const int N4) const
+//    {
+//      return iterA(N1,N3)*iterB(N2,N4);
+//    }
+//  };
+
+//  template<class A, class B, class T, class U, int Dim01, int Dim23,
+//    char i, char j, char k, char l>
+//  inline const Tensor4_ddg_Expr<const Tensor2_carat_Tensor2_0213<A,B,T,U,Dim01,Dim23,i,j,k,l>,typename promote<T,U>::V,Dim01,Dim23,i,k,j,l>
+//  operator^(const Tensor2_Expr<A,T,Dim01,Dim23,i,j> &a,
+//  	  const Tensor2_Expr<B,U,Dim01,Dim23,k,l> &b)
+//  {
+//    typedef const Tensor2_carat_Tensor2_0213<A,B,T,U,Dim01,Dim23,i,j,k,l>
+//      TensorExpr;
+//    return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,k,j,l>
+//      (TensorExpr(a,b));
+//  }
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_constructor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_constructor.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,160 @@
+/* A helper class that allows simple initialization of the Tensor2,
+   but only if it has the correct number of elements.  There are
+   specializations for column-major and row-major orderings. */
+
+template<class T, int Tensor_Dim0, int Tensor_Dim1, Layout layout>
+class Tensor2_constructor;
+
+/* Column major versions */
+
+template<class T>
+class Tensor2_constructor<T,2,2,column_major>
+{
+public:
+  Tensor2_constructor(T data[2][2],T d00,T d01,T d10,T d11)
+  {
+    data[0][0]=d00;
+    data[0][1]=d01;
+    data[1][0]=d10;
+    data[1][1]=d11;
+  }
+};
+
+template<class T>
+class Tensor2_constructor<T,3,2,column_major>
+{
+public:
+  Tensor2_constructor(T data[3][2],T d00, T d01, T d10, T d11,
+		      T d20, T d21)
+  {
+    data[0][0]=d00;
+    data[0][1]=d01;
+    data[1][0]=d10;
+    data[1][1]=d11;
+    data[2][0]=d20;
+    data[2][1]=d21;
+  }
+};
+
+template<class T>
+class Tensor2_constructor<T,3,3,column_major>
+{
+public:
+  Tensor2_constructor(T data[3][3],T d00, T d01, T d02, T d10, T d11, T d12,
+		      T d20, T d21, T d22)
+  {
+    data[0][0]=d00;
+    data[0][1]=d01;
+    data[0][2]=d02;
+    data[1][0]=d10;
+    data[1][1]=d11;
+    data[1][2]=d12;
+    data[2][0]=d20;
+    data[2][1]=d21;
+    data[2][2]=d22;
+  }
+};
+
+template<class T>
+class Tensor2_constructor<T,4,4,column_major>
+{
+public:
+  Tensor2_constructor(T data[4][4], T d00, T d01, T d02, T d03, T d10, T d11,
+		      T d12, T d13, T d20, T d21, T d22, T d23, T d30, T d31,
+		      T d32, T d33)
+  {
+    data[0][0]=d00;
+    data[0][1]=d01;
+    data[0][2]=d02;
+    data[0][3]=d03;
+    data[1][0]=d10;
+    data[1][1]=d11;
+    data[1][2]=d12;
+    data[1][3]=d13;
+    data[2][0]=d20;
+    data[2][1]=d21;
+    data[2][2]=d22;
+    data[2][3]=d23;
+    data[3][0]=d30;
+    data[3][1]=d31;
+    data[3][2]=d32;
+    data[3][3]=d33;
+  }
+};
+
+/* Row major versions */
+
+template<class T>
+class Tensor2_constructor<T,2,2,row_major>
+{
+public:
+  Tensor2_constructor(T data[2][2],T d00,T d01,T d10,T d11)
+  {
+    data[0][0]=d00;
+    data[1][0]=d01;
+    data[0][1]=d10;
+    data[1][1]=d11;
+  }
+};
+
+template<class T>
+class Tensor2_constructor<T,3,2,row_major>
+{
+public:
+  Tensor2_constructor(T data[2][3],T d00, T d01, T d10, T d11,
+		      T d20, T d21)
+  {
+    data[0][0]=d00;
+    data[1][0]=d01;
+    data[0][1]=d10;
+    data[1][1]=d11;
+    data[0][2]=d20;
+    data[1][2]=d21;
+  }
+};
+
+template<class T>
+class Tensor2_constructor<T,3,3,row_major>
+{
+public:
+  Tensor2_constructor(T data[3][3],T d00, T d01, T d02, T d10, T d11, T d12,
+		      T d20, T d21, T d22)
+  {
+    data[0][0]=d00;
+    data[1][0]=d01;
+    data[2][0]=d02;
+    data[0][1]=d10;
+    data[1][1]=d11;
+    data[2][1]=d12;
+    data[0][2]=d20;
+    data[1][2]=d21;
+    data[2][2]=d22;
+  }
+};
+
+template<class T>
+class Tensor2_constructor<T,4,4,row_major>
+{
+public:
+  Tensor2_constructor(T data[4][4], T d00, T d01, T d02, T d03, T d10, T d11,
+		      T d12, T d13, T d20, T d21, T d22, T d23, T d30, T d31,
+		      T d32, T d33)
+  {
+    data[0][0]=d00;
+    data[1][0]=d01;
+    data[2][0]=d02;
+    data[3][0]=d03;
+    data[0][1]=d10;
+    data[1][1]=d11;
+    data[2][1]=d12;
+    data[3][1]=d13;
+    data[0][2]=d20;
+    data[1][2]=d21;
+    data[2][2]=d22;
+    data[3][2]=d23;
+    data[0][3]=d30;
+    data[1][3]=d31;
+    data[2][3]=d32;
+    data[3][3]=d33;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_divide_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_divide_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,28 @@
+/* Divides a Tensor2 by a generic, yielding a Tensor2. */
+
+template<class A, class T, class U, int Dim0, int Dim1, char i, char j>
+class Tensor2_divide_generic
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)/d;
+  }
+
+  Tensor2_divide_generic(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			 const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim0, int Dim1, char i, char j>
+inline const Tensor2_Expr<const Tensor2_divide_generic<A,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator/(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a, const U &d0)
+{
+  typedef const Tensor2_divide_generic<A,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,d0));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_minus_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_minus_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,60 @@
+/* Subtracts a Tensor2 from a Tensor2, yielding a Tensor2. */
+
+/* A(i,j)-B(i,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor2_minus_Tensor2_01
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim0,Dim1,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)-iterB(N1,N2);
+  }
+
+  Tensor2_minus_Tensor2_01(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			   const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor2_Expr<const Tensor2_minus_Tensor2_01<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator-(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b)
+{
+  typedef const Tensor2_minus_Tensor2_01<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j)-B(j,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor2_minus_Tensor2_10
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim0,Dim1,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)-iterB(N2,N1);
+  }
+
+  Tensor2_minus_Tensor2_10(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			  const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1,
+  char i, char j>
+inline const Tensor2_Expr<const Tensor2_minus_Tensor2_10<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator-(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &b)
+{
+  typedef const Tensor2_minus_Tensor2_10<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_number.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_number.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* This is for expressions where a number is used for one slot, and
+   an index for another, yielding a Tensor1_Expr. */
+
+template<class A, class T, int N>
+class Tensor2_number_1
+{
+  A iterA;
+public:
+  T operator()(const int N1) const
+  {
+    return iterA(N1,N);
+  }
+  Tensor2_number_1(A &a): iterA(a) {}
+};
+
+template<class A, class T, int N>
+class Tensor2_number_0
+{
+  A iterA;
+public:
+  T operator()(const int N1) const
+  {
+    return iterA(N,N1);
+  }
+  Tensor2_number_0(A &a): iterA(a) {}
+};
+
+template<class A, class T, int N>
+class Tensor2_number_rhs_0
+{};
+
+template<class A, class T, int N>
+class Tensor2_number_rhs_1
+{};
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_numeral.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_numeral.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,28 @@
+/* This is for expressions where a number is used for one slot, and
+   an index for another, yielding a Tensor1_Expr. */
+
+template<class A, class T>
+class Tensor2_numeral_1
+{
+  A iterA;
+  const int N;
+public:
+  T operator()(const int N1) const
+  {
+    return iterA(N1,N);
+  }
+  Tensor2_numeral_1(A &a, const int NN): iterA(a), N(NN) {}
+};
+
+template<class A, class T>
+class Tensor2_numeral_0
+{
+  A iterA;
+  const int N;
+public:
+  T operator()(const int N1) const
+  {
+    return iterA(N,N1);
+  }
+  Tensor2_numeral_0(A &a, const int NN): iterA(a), N(NN) {}
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_or_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_or_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,61 @@
+/* Creates a Tensor2_symmetric expression by adding two Tensor2's
+   together. */
+
+/* This version is for expressions like A(i,j)||B(i,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_or_Tensor2
+{
+  const Tensor2_Expr<A,T,Dim,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N1,N2);
+  }
+
+  Tensor2_or_Tensor2(const Tensor2_Expr<A,T,Dim,Dim,i,j> &a,
+		     const Tensor2_Expr<B,U,Dim,Dim,i,j> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const Tensor2_or_Tensor2<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator||(const Tensor2_Expr<A,T,Dim,Dim,i,j> &a,
+	   const Tensor2_Expr<B,U,Dim,Dim,i,j> &b)
+{
+  typedef const Tensor2_or_Tensor2<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
+/* This version is for when the indices are switched as in
+   A(i,j)||B(j,i) (probably the most common case). */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_or_Tensor2_switched
+{
+  const Tensor2_Expr<A,T,Dim,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N2,N1);
+  }
+
+  Tensor2_or_Tensor2_switched(const Tensor2_Expr<A,T,Dim,Dim,i,j> &a,
+			      const Tensor2_Expr<B,U,Dim,Dim,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_or_Tensor2_switched<A,B,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator||(const Tensor2_Expr<A,T,Dim,Dim,i,j> &a,
+	   const Tensor2_Expr<B,U,Dim,Dim,j,i> &b)
+{
+  typedef const Tensor2_or_Tensor2_switched<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_plus_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_plus_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,60 @@
+/* Adds a Tensor2 to a Tensor2, yielding a Tensor2. */
+
+/* A(i,j)+B(i,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor2_plus_Tensor2_01
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim0,Dim1,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N1,N2);
+  }
+
+  Tensor2_plus_Tensor2_01(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			  const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor2_Expr<const Tensor2_plus_Tensor2_01<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator+(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b)
+{
+  typedef const Tensor2_plus_Tensor2_01<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j)+B(j,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor2_plus_Tensor2_10
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim0,Dim1,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N2,N1);
+  }
+
+  Tensor2_plus_Tensor2_10(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			  const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1,
+  char i, char j>
+inline const Tensor2_Expr<const Tensor2_plus_Tensor2_10<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator+(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &b)
+{
+  typedef const Tensor2_plus_Tensor2_10<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_pointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_pointer.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,189 @@
+/* A version for pointers. */
+
+template <class T, int Tensor_Dim0, int Tensor_Dim1,
+	  Layout layout>
+class Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>
+{
+  mutable T * restrict data[(layout==column_major) ? Tensor_Dim0 : Tensor_Dim1]
+  [(layout==column_major) ? Tensor_Dim1 : Tensor_Dim0];
+public:
+  /* Initializations for varying numbers of elements, with each one
+     defined for a particular Tensor_Dim.  To initialize a different
+     dimension, just add the appropriate constructor and call to
+     the Tensor2_constructor constructor. */
+  Tensor2(T* d00, T* d01,T* d10, T* d11)
+  {
+    Tensor2_constructor<T* restrict,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d10,d11);
+  }
+  Tensor2(T* d00, T* d01, T* d10, T* d11, T* d20, T* d21)
+  {
+    Tensor2_constructor<T* restrict,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d10,d11,d20,d21);
+  }
+  Tensor2(T* d00, T* d01, T* d02, T* d10, T* d11, T* d12, T* d20, T* d21, T* d22)
+  {
+    Tensor2_constructor<T* restrict,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d02,d10,d11,d12,d20,d21,d22);
+  }
+  Tensor2(T* d00, T* d01, T* d02, T* d03, T* d10, T* d11, T* d12, T* d13,
+	  T* d20, T* d21, T* d22, T* d23, T* d30, T* d31, T* d32, T* d33)
+  {
+    Tensor2_constructor<T* restrict,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d02,d03,d10,d11,d12,d13,d20,d21,d22,d23,d30,d31,d32,d33);
+  }
+  Tensor2() {}
+
+  /* There are two operator(int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0 || N2>=Tensor_Dim1 || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim1
+		  << ">.operator(" << N1 << "," << N2 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return ((layout==column_major) ? *data[N1][N2] : *data[N2][N1]);
+  }
+
+  T operator()(const int N1, const int N2) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0 || N2>=Tensor_Dim1 || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim1
+		  << ">.operator(" << N1 << "," << N2 << ") const"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return ((layout==column_major) ? *data[N1][N2] : *data[N2][N1]);
+  }
+
+  T* ptr(const int N1, const int N2) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0 || N2>=Tensor_Dim1 || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim1
+		  << ">.ptr(" << N1 << "," << N2 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return ((layout==column_major) ? data[N1][N2] : data[N2][N1]);
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2)
+  {
+    return Tensor2_Expr<Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,T,Dim0,Dim1,i,j>
+      (*this);
+  }
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<const Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2) const
+  {
+    return Tensor2_Expr<const Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,
+      T,Dim0,Dim1,i,j>(*this);
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     an index for another, yielding a Tensor1_Expr.  The non-const
+     versions don't actually create a Tensor2_number_rhs_[01] object.
+     They create a Tensor1_Expr directly, which provides the
+     appropriate indexing operators.  The const versions do create a
+     Tensor2_number_[01]. */
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<Tensor2_number_rhs_1<Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> n1)
+  {
+    typedef Tensor2_number_rhs_1<Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,
+      T,N> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<Tensor2_number_rhs_0<Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Number<N> n1, const Index<i,Dim> index1)
+  {
+    typedef Tensor2_number_rhs_0<Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<const Tensor2_number_1<const Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> n1) const
+  {
+    typedef const Tensor2_number_1<const Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<const Tensor2_number_0<const Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Number<N> n1, const Index<i,Dim> index1) const
+  {
+    typedef const Tensor2_number_0<const Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+  
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+
+  const Tensor2<T*,Tensor_Dim0,Tensor_Dim1,layout> & operator++() const
+  {
+    for(int i=0;i<Tensor_Dim0;++i)
+      for(int j=0;j<Tensor_Dim1;++j)
+	((layout==column_major) ? ++data[i][j] : ++data[j][i]);
+    return *this;
+  }
+
+  /* These two operator()'s return the Tensor2 with internal
+     contractions, yielding a T.  I have to specify one for both
+     const and non-const because otherwise they compiler will use the
+     operator() which gives a Tensor2_Expr<>. */
+
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2)
+  {
+    return internal_contract(Number<Dim>());
+  }
+
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2) const
+  {
+    return internal_contract(Number<Dim>());
+  }
+private:
+  template<int N>
+  T internal_contract(Number<N>)
+  {
+    return *data[N-1][N-1] + internal_contract(Number<N-1>());
+  }
+
+  T internal_contract(Number<1>)
+  {
+    return *data[0][0];
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_times_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_times_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,147 @@
+/* This file has all of the declarations for expressions like
+   Tensor2*Tensor1 and Tensor1*Tensor2, yielding a Tensor1 or
+   Tensor3. */
+
+/* A(i,j)*B(j) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor2_times_Tensor1_1
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor1_Expr<B,U,Dim1,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(Current_Dim-1)
+      + eval(N1,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(0);
+  }
+public:
+  Tensor2_times_Tensor1_1(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			  const Tensor1_Expr<B,U,Dim1,j> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor1_Expr<const Tensor2_times_Tensor1_1<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor1_Expr<B,U,Dim1,j> &b)
+{
+  typedef const Tensor2_times_Tensor1_1<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* A(j,i)*B(j) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+class Tensor2_times_Tensor1_0
+{
+  const Tensor2_Expr<A,T,Dim1,Dim0,j,i> iterA;
+  const Tensor1_Expr<B,U,Dim1,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(Current_Dim-1)
+      + eval(N1,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(0);
+  }
+public:
+  Tensor2_times_Tensor1_0(const Tensor2_Expr<A,T,Dim1,Dim0,j,i> &a,
+			  const Tensor1_Expr<B,U,Dim1,j> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor1_Expr<const Tensor2_times_Tensor1_0<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor2_Expr<A,T,Dim1,Dim0,j,i> &a,
+	  const Tensor1_Expr<B,U,Dim1,j> &b)
+{
+  typedef const Tensor2_times_Tensor1_0<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* B(j)*A(i,j) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor1_Expr<const Tensor2_times_Tensor1_1<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor1_Expr<B,U,Dim1,j> &b,
+	  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a)
+{
+  typedef const Tensor2_times_Tensor1_1<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* B(j)*A(j,i) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const Tensor1_Expr<const Tensor2_times_Tensor1_0<A,B,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor1_Expr<B,U,Dim1,j> &b,
+	  const Tensor2_Expr<A,T,Dim1,Dim0,j,i> &a)
+{
+  typedef const Tensor2_times_Tensor1_0<A,B,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* A(i,j)*B(k) -> Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor2_times_Tensor1
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor1_Expr<B,U,Dim2,k> iterB;
+public:
+  Tensor2_times_Tensor1(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			const Tensor1_Expr<B,U,Dim2,k> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2)*iterB(N3);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr<const Tensor2_times_Tensor1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor1_Expr<B,U,Dim2,k> &b)
+{
+  typedef const Tensor2_times_Tensor1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k> TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(k)*A(i,j) -> Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr<const Tensor2_times_Tensor1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator*(const Tensor1_Expr<B,U,Dim2,k> &b,
+	  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a)
+{
+  typedef const Tensor2_times_Tensor1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k> TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_times_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_times_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,299 @@
+/* This file has all of the declarations for Tensor2*Tensor2.  This
+   includes the double contraction A(i,j)*B(i,j) (yielding a
+   typename promote<T,U>) as well as the more complicated single contraction
+   A(i,j)*B(j,k) (yielding a Tensor2 expression) and no contraction
+   (yielding a Tensor4). */
+
+/* Double contraction. */
+
+/* A(i,j)*B(i,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,
+  char j, int Current_Dim0, int Current_Dim1>
+inline const typename promote<T,U>::V T2_times_T2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+				   const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b,
+				   const Number<Current_Dim0> &N0,
+				   const Number<Current_Dim1> &N1)
+{
+  return a(Current_Dim0-1,Current_Dim1-1)*b(Current_Dim0-1,Current_Dim1-1)
+    + T2_times_T2(a,b,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,
+  char j, int Current_Dim1>
+inline const typename promote<T,U>::V T2_times_T2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+				   const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b,
+				   const Number<1> &N0,
+				   const Number<Current_Dim1> &N1)
+{
+  return a(0,Current_Dim1-1)*b(0,Current_Dim1-1)
+    + T2_times_T2(a,b,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,
+  char j>
+inline const typename promote<T,U>::V T2_times_T2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+				   const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b,
+				   const Number<1> &N0, const Number<1> &N1)
+{
+  return a(0,0)*b(0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const typename promote<T,U>::V operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+				 const Tensor2_Expr<B,U,Dim0,Dim1,i,j> &b)
+{
+  return T2_times_T2(a,b,Number<Dim0>(),Number<Dim1>());
+}
+
+/* A(i,j)*B(j,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,
+  char j, int Current_Dim0, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2_times_switched_T2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+		     const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &b,
+		     const Number<Current_Dim0> &N0,
+		     const Number<Current_Dim1> &N1)
+{
+  return a(Current_Dim0-1,Current_Dim1-1)*b(Current_Dim1-1,Current_Dim0-1)
+    + T2_times_switched_T2(a,b,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,
+  char j, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2_times_switched_T2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+		     const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &b,
+		     const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  return a(0,Current_Dim1-1)*b(Current_Dim1-1,0)
+    + T2_times_switched_T2(a,b,Number<Dim0>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,
+  char j>
+inline const typename promote<T,U>::V
+T2_times_switched_T2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+		     const Tensor2_Expr<B,U,Dim0,Dim1,j,i> &b,
+		     const Number<1> &N0, const Number<1> &N1)
+{
+  return a(0,0)*b(0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, char i,char j>
+inline const typename promote<T,U>::V operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+				 const Tensor2_Expr<B,U,Dim1,Dim0,j,i> &b)
+{
+  return T2_times_switched_T2(a,b,Number<Dim0>(),Number<Dim1>());
+}
+
+/* Single contraction.  The wrapper class has a different name for
+   each possible placing of the indices (e.g. A(i,j)*B(j,k) has the
+   number 10 because the contraction indices are on the second and
+   first slots (counting from 0). */
+
+/* A(i,j)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor2_times_Tensor2_10
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim1,Dim2,j,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(0,N2);
+  }
+public:
+  Tensor2_times_Tensor2_10(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			   const Tensor2_Expr<B,U,Dim1,Dim2,j,k> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_times_Tensor2_10
+<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,typename promote<T,U>::V,Dim0,Dim2,i,k>
+operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim1,Dim2,j,k> &b)
+{
+  typedef const Tensor2_times_Tensor2_10<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim2,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor2_times_Tensor2_11
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim1,k,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(N2,0);
+  }
+public:
+  Tensor2_times_Tensor2_11(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			   const Tensor2_Expr<B,U,Dim2,Dim1,k,j> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_times_Tensor2_11
+<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,typename promote<T,U>::V,Dim0,Dim2,i,k>
+operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim1,k,j> &b)
+{
+  typedef const Tensor2_times_Tensor2_11<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim2,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(j,i)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor2_times_Tensor2_00
+{
+  const Tensor2_Expr<A,T,Dim1,Dim0,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim1,Dim2,j,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(0,N2);
+  }
+public:
+  Tensor2_times_Tensor2_00(const Tensor2_Expr<A,T,Dim1,Dim0,j,i> &a,
+			   const Tensor2_Expr<B,U,Dim1,Dim2,j,k> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_times_Tensor2_00
+<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,typename promote<T,U>::V,Dim0,Dim2,i,k>
+operator*(const Tensor2_Expr<A,T,Dim1,Dim0,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim1,Dim2,j,k> &b)
+{
+  typedef const Tensor2_times_Tensor2_00<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim2,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(j,i)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor2_times_Tensor2_01
+{
+  const Tensor2_Expr<A,T,Dim1,Dim0,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim1,k,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(N2,0);
+  }
+public:
+  Tensor2_times_Tensor2_01(const Tensor2_Expr<A,T,Dim1,Dim0,j,i> &a,
+			   const Tensor2_Expr<B,U,Dim2,Dim1,k,j> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_times_Tensor2_01
+<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,typename promote<T,U>::V,Dim0,Dim2,i,k>
+operator*(const Tensor2_Expr<A,T,Dim1,Dim0,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim1,k,j> &b)
+{
+  typedef const Tensor2_times_Tensor2_01<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim2,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j)*B(k,l) -> Tensor4 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor2_times_Tensor2
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> iterB;
+public:
+  Tensor2_times_Tensor2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+			const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2)*iterB(N3,N4);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor4_Expr
+<const Tensor2_times_Tensor2<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b)
+{
+  typedef const Tensor2_times_Tensor2<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_times_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_times_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+/* Multiplies a Tensor2 with a generic, yielding a Tensor2. */
+
+template<class A, class T, class U, int Dim0, int Dim1, char i, char j>
+class Tensor2_times_generic
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)*d;
+  }
+
+  Tensor2_times_generic(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim0, int Dim1, char i, char j>
+inline const Tensor2_Expr<const Tensor2_times_generic<A,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a, const U &d0)
+{
+  typedef const Tensor2_times_generic<A,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,d0));
+}
+
+template<class A, class T, class U, int Dim0, int Dim1, char i, char j>
+inline const Tensor2_Expr<const Tensor2_times_generic<A,T,U,Dim0,Dim1,i,j>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const U &d0, const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a)
+{
+  typedef const Tensor2_times_generic<A,T,U,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,d0));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_transform.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_transform.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,25 @@
+/* Applies an arbitrary function to the Tensor2_Expr. */
+
+template<class A, class B, class T, int Dim0, int Dim1, char i, char j>
+class transform_Tensor2
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+  B function;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return function(iterA(N1,N2));
+  }
+
+  transform_Tensor2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a, B func):
+    iterA(a), function(func) {}
+};
+
+template<class A, class B, class T, int Dim0, int Dim1, char i, char j>
+inline const Tensor2_Expr<const transform_Tensor2<A,B,T,Dim0,Dim1,i,j>,T,Dim0,Dim1,i,j>
+transform(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a, B function)
+{
+  typedef const transform_Tensor2<A,B,T,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(TensorExpr(a,function));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2/Tensor2_value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/Tensor2_value.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,188 @@
+/* A general version, not for pointers. */
+
+template <class T, int Tensor_Dim0, int Tensor_Dim1,
+	  Layout layout>
+class Tensor2
+{
+  T data[(layout==column_major) ? Tensor_Dim0 : Tensor_Dim1]
+  [(layout==column_major) ? Tensor_Dim1 : Tensor_Dim0];
+public:
+  /* Initializations for varying numbers of elements, with each one
+     defined for a particular Tensor_Dim.  To initialize a different
+     dimension, just add the appropriate constructor and call to
+     the Tensor2_constructor constructor. */
+  Tensor2(T d00, T d01,T d10, T d11)
+  {
+    Tensor2_constructor<T,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d10,d11);
+  }
+  Tensor2(T d00, T d01, T d02, T d10, T d11, T d12, T d20, T d21, T d22)
+  {
+    Tensor2_constructor<T,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d02,d10,d11,d12,d20,d21,d22);
+  }
+  Tensor2(T d00, T d01, T d10, T d11, T d20, T d21)
+  {
+    Tensor2_constructor<T,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d10,d11,d20,d21);
+  }
+  Tensor2(T d00, T d01, T d02, T d03, T d10, T d11, T d12, T d13,
+	  T d20, T d21, T d22, T d23, T d30, T d31, T d32, T d33)
+  {
+    Tensor2_constructor<T,Tensor_Dim0,Tensor_Dim1,layout>
+      (data,d00,d01,d02,d03,d10,d11,d12,d13,d20,d21,d22,d23,d30,d31,d32,d33);
+  }
+  Tensor2() {}
+
+  /* There are two operator(int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0 || N2>=Tensor_Dim1 || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2<T,"
+		  << Tensor_Dim0 << "," << Tensor_Dim1
+		  << ">.operator(" << N1 << "," << N2 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return ((layout==column_major) ? data[N1][N2] : data[N2][N1]);
+  }
+
+  T operator()(const int N1, const int N2) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0 || N2>=Tensor_Dim1 || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2<T,"
+		  << Tensor_Dim0 << "," << Tensor_Dim1
+		  << ">.operator(" << N1 << "," << N2 << ") const"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return ((layout==column_major) ? data[N1][N2] : data[N2][N1]);
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2)
+  {
+    return Tensor2_Expr<Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T,Dim0,Dim1,i,j>
+      (*this);
+  }
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2) const
+  {
+    return Tensor2_Expr<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,
+      T,Dim0,Dim1,i,j>(*this);
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     an index for another, yielding a Tensor1_Expr.  The non-const
+     versions don't actually create a Tensor2_number_rhs_[01] object.
+     They create a Tensor1_Expr directly, which provides the
+     appropriate indexing operators.  The const versions do create a
+     Tensor2_number_[01]. */
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<Tensor2_number_rhs_1<Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> n1)
+  {
+    typedef Tensor2_number_rhs_1<Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,
+      T,N> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<Tensor2_number_rhs_0<Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Number<N> n1, const Index<i,Dim> index1)
+  {
+    typedef Tensor2_number_rhs_0<Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<const Tensor2_number_1<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> n1) const
+  {
+    typedef const Tensor2_number_1<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  template<char i, int Dim, int N>
+  Tensor1_Expr<const Tensor2_number_0<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,
+    T,N>,T,Dim,i>
+  operator()(const Number<N> n1, const Index<i,Dim> index1) const
+  {
+    typedef const Tensor2_number_0<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* This is for expressions where an actual number (not a Number<>)
+     is used for one slot, and an index for another, yielding a
+     Tensor1_Expr. */
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor2_numeral_1<const Tensor2
+  <T,Tensor_Dim0,Tensor_Dim1>,T>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const int N) const
+  {
+    typedef const Tensor2_numeral_1<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
+  }
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor2_numeral_0<const Tensor2
+  <T,Tensor_Dim0,Tensor_Dim1>,T>,T,Dim,i>
+  operator()(const int N, const Index<i,Dim> index1) const
+  {
+    typedef const Tensor2_numeral_0<const Tensor2<T,Tensor_Dim0,Tensor_Dim1,layout>,T>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
+  }
+
+  /* These two operator()'s return the Tensor2 with internal
+     contractions, yielding a T.  I have to specify one for both
+     const and non-const because otherwise they compiler will use the
+     operator() which gives a Tensor2_Expr<>. */
+
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2)
+  {
+    return internal_contract(Number<Dim>());
+  }
+
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2) const
+  {
+    return internal_contract(Number<Dim>());
+  }
+private:
+  template<int N>
+  T internal_contract(Number<N>)
+  {
+    return data[N-1][N-1] + internal_contract(Number<N-1>());
+  }
+
+  T internal_contract(Number<1>)
+  {
+    return data[0][0];
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor2/conj_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/conj_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,23 @@
+/* complex conjugate operator. */
+
+template<class A, class T, int Dim0, int Dim1, char i, char j>
+class conj_Tensor2
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return conj(iterA(N1,N2));
+  }
+
+  conj_Tensor2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a): iterA(a) {}
+};
+
+template<class A, class T, int Dim0, int Dim1, char i, char j>
+inline const Tensor2_Expr<const conj_Tensor2<A,T,Dim0,Dim1,i,j>,T,Dim0,Dim1,i,j>
+conj(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a)
+{
+  typedef const conj_Tensor2<A,T,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(TensorExpr(a));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2/minus_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2/minus_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,23 @@
+/* Unary minus operator. */
+
+template<class A, class T, int Dim0, int Dim1, char i, char j>
+class minus_Tensor2
+{
+  const Tensor2_Expr<A,T,Dim0,Dim1,i,j> iterA;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return -iterA(N1,N2);
+  }
+
+  minus_Tensor2(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a): iterA(a) {}
+};
+
+template<class A, class T, int Dim0, int Dim1, char i, char j>
+inline const Tensor2_Expr<const minus_Tensor2<A,T,Dim0,Dim1,i,j>,T,Dim0,Dim1,i,j>
+operator-(const Tensor2_Expr<A,T,Dim0,Dim1,i,j> &a)
+{
+  typedef const minus_Tensor2<A,T,Dim0,Dim1,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(TensorExpr(a));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,9 @@
+/* Declarations for a Tensor2_symmetric.  This only has a single
+   dimension parameter, since the dimensions of the two indices must
+   be the same for it to be symmetric. */
+
+#include "Tensor2_symmetric/Tensor2_symmetric_constructor.h"
+#include "Tensor2_symmetric/Tensor2_symmetric_value.h"
+#include "Tensor2_symmetric/Tensor2_symmetric_pointer.h"
+
+#include "Tensor2_symmetric/Tensor2_symmetric_Expr.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,175 @@
+/* Declares a wrapper class for symmetric rank 2 Tensor expressions.
+   It is specialized for Tensor3_number_rhs_2.  Note that
+   Tensor2_symmetric_Expr_equals.h is included at the end, because it
+   needs the definition of Tensor2_symmetric_Expr. */
+
+#include "Tensor2_symmetric_plus_Tensor2_symmetric.h"
+#include "Tensor2_symmetric_minus_Tensor2_symmetric.h"
+#include "Tensor2_symmetric_plus_Tensor2.h"
+#include "Tensor2_symmetric_minus_Tensor2.h"
+#include "Tensor2_symmetric_times_Tensor2_symmetric.h"
+#include "Tensor2_symmetric_and_Tensor2_symmetric.h"
+#include "Tensor2_symmetric_mod_Tensor2_symmetric.h"
+#include "Tensor2_symmetric_times_Tensor2.h"
+#include "Tensor2_symmetric_carat_Tensor2.h"
+#include "Tensor2_symmetric_times_Tensor1.h"
+#include "Tensor2_symmetric_plus_generic.h"
+#include "Tensor2_symmetric_minus_generic.h"
+#include "generic_minus_Tensor2_symmetric.h"
+#include "Tensor2_symmetric_times_generic.h"
+#include "Tensor2_symmetric_divide_generic.h"
+#include "minus_Tensor2_symmetric.h"
+#include "dTensor2_symmetric.h"
+#include "ddTensor2_symmetric.h"
+#include "d_one_sided_Tensor2_symmetric.h"
+#include "d_boundary_Tensor2_symmetric.h"
+#include "dd_boundary_Tensor2_symmetric.h"
+#include "diffusion_Tensor2_symmetric.h"
+#include "interpolate_Tensor2_symmetric.h"
+
+
+template<class A, class T, int Dim, char i, char j>
+class Tensor2_symmetric_Expr
+{
+  A iter;
+public:
+  Tensor2_symmetric_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2) const
+  {
+    return iter(N1,N2);
+  }
+};
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+class Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>
+{
+  Tensor2_symmetric<A,Tensor_Dim> &iter;
+public:
+  Tensor2_symmetric_Expr(Tensor2_symmetric<A,Tensor_Dim> &a): iter(a) {}
+  T & operator()(const int N1, const int N2)
+  {
+    return iter(N1,N2);
+  }
+  T operator()(const int N1, const int N2) const
+  {
+    return iter(N1,N2);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result);
+
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator=(const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &result);
+
+  template<class B, class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator+=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result);
+
+  template<class B, class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator-=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result);
+  
+  template<class B, class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator&=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result);
+
+  /* This is for when the indices are switched (i,j) -> (j,i). */
+
+  template<class B, class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator=(const Tensor2_symmetric_Expr<B,U,Dim,j,i> &result);
+
+  template<class B, class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator+=(const Tensor2_symmetric_Expr<B,U,Dim,j,i> &result);
+
+  template<class B, class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+  operator-=(const Tensor2_symmetric_Expr<B,U,Dim,j,i> &result);
+
+  /* Operations with just generics. */
+
+  template<class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & operator=(const U &d);
+  template<class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & operator+=(const U &d);
+  template<class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & operator-=(const U &d);
+  template<class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & operator*=(const U &d);
+  template<class U> inline
+  const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & operator/=(const U &d);
+};
+
+/* Specialized for Tensor3_dg_number_rhs_2 (Tensor3_dg with the
+   second index explicitly given). */
+
+template<class A, class T, int Dim, char i, char j, int N>
+class Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,T,Dim,i,j>
+{
+  A &iter;
+public:
+  Tensor2_symmetric_Expr(A &a): iter(a) {}
+  T & operator()(const int N1, const int N2)
+  {
+    return iter(N1,N2,N);
+  }
+  T operator()(const int N1, const int N2) const
+  {
+    return iter(N1,N2,N);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,
+    T,Dim,i,j> &
+  operator=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result);
+
+  const Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,
+    T,Dim,i,j> &
+  operator=(const Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,
+	    T,Dim,i,j> &result);
+};
+
+/* Specialized for Tensor4_ddg_number_rhs_01 (Tensor4_ddg with the
+   first and second index explicitly given). */
+
+template<class A, class T, int Dim, char i, char j, int N0, int N1>
+class Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,T,Dim,i,j>
+{
+  A &iter;
+public:
+  Tensor2_symmetric_Expr(A &a): iter(a) {}
+  T & operator()(const int N2, const int N3)
+  {
+    return iter(N0,N1,N2,N3);
+  }
+  T operator()(const int N2, const int N3) const
+  {
+    return iter(N0,N1,N2,N3);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,
+    T,Dim,i,j> &
+  operator=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result);
+
+  const Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,
+    T,Dim,i,j> &
+  operator=(const Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,
+	    T,Dim,i,j> &result);
+};
+
+#include "Tensor2_symmetric_Expr_equals.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_Expr_equals.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_Expr_equals.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,533 @@
+/* Various assignment operators.  I have to explicitly declare the
+   second operator= because otherwise the compiler will generate its
+   own and not use the template code. */
+
+/* T2s=T2s */
+
+template<class A, class B, class U, int Dim, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void T2s_equals_T2s(A &iter,
+			   const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+			   const Number<Current_Dim0> &N0,
+			   const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)=result(Current_Dim0-1,Current_Dim1-1);
+  T2s_equals_T2s(iter,result,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j, int Current_Dim1>
+inline void T2s_equals_T2s
+(A &iter, const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+ const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)=result(0,Current_Dim1-1);
+  T2s_equals_T2s(iter,result,Number<Current_Dim1-1>(),
+		 Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j>
+inline void T2s_equals_T2s(A &iter,
+			   const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+			   const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)=result(0,0);
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result)
+{
+  T2s_equals_T2s(iter,result,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* T2s=T2s_Expr(T2s) */
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator=(const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &result)
+{
+  return operator=<Tensor2_symmetric<A,Tensor_Dim>,T>(result);
+}
+
+/* T2s+=T2s */
+
+template<class A, class B, class U, int Dim, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void
+T2s_plus_equals_T2s(A &iter, const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		    const Number<Current_Dim0> &N0,
+		    const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)+=result(Current_Dim0-1,Current_Dim1-1);
+  T2s_plus_equals_T2s(iter,result,Number<Current_Dim0-1>(),
+		      Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j, int Current_Dim1>
+inline void
+T2s_plus_equals_T2s(A &iter, const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		    const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)+=result(0,Current_Dim1-1);
+  T2s_plus_equals_T2s(iter,result,Number<Current_Dim1-1>(),
+		 Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j>
+inline void
+T2s_plus_equals_T2s(A &iter, const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		    const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)+=result(0,0);
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator+=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result)
+{
+  T2s_plus_equals_T2s(iter,result,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* T2s-=T2s */
+
+template<class A, class B, class U, int Dim, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void
+T2s_minus_equals_T2s(A &iter,
+		     const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		     const Number<Current_Dim0> &N0,
+		     const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)-=result(Current_Dim0-1,Current_Dim1-1);
+  T2s_minus_equals_T2s(iter,result,Number<Current_Dim0-1>(),
+		       Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j, int Current_Dim1>
+inline void
+T2s_minus_equals_T2s(A &iter,
+		     const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		     const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)-=result(0,Current_Dim1-1);
+  T2s_minus_equals_T2s(iter,result,Number<Current_Dim1-1>(),
+		 Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j>
+inline void
+T2s_minus_equals_T2s(A &iter,
+		     const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		     const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)-=result(0,0);
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator-=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result)
+{
+  T2s_minus_equals_T2s(iter,result,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* T2s&=T2s */
+
+template<class A, class B, class U, int Dim, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline void
+T2s_and_equals_T2s(A &iter, const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		    const Number<Current_Dim0> &N0,
+		    const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)*=result(Current_Dim0-1,Current_Dim1-1);
+  T2s_and_equals_T2s(iter,result,Number<Current_Dim0-1>(),
+		      Number<Current_Dim1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j, int Current_Dim1>
+inline void
+T2s_and_equals_T2s(A &iter, const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		    const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)*=result(0,Current_Dim1-1);
+  T2s_and_equals_T2s(iter,result,Number<Current_Dim1-1>(),
+		 Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class U, int Dim, char i, char j>
+inline void
+T2s_and_equals_T2s(A &iter, const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result,
+		    const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)*=result(0,0);
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator&=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result)
+{
+  T2s_and_equals_T2s(iter,result,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* This is for when the indices are switched (i,j) -> (j,i). */
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator=(const Tensor2_symmetric_Expr<B,U,Dim,j,i> &result)
+{
+  T2s_equals_T2s(iter,result,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator+=(const Tensor2_symmetric_Expr<B,U,Dim,j,i> &result)
+{
+  T2s_plus_equals_T2s(iter,result,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> & 
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator-=(const Tensor2_symmetric_Expr<B,U,Dim,j,i> &result)
+{
+  T2s_minus_equals_T2s(iter,result,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* Operations with just generics. */
+
+/* T2s=U */
+
+template<class A, class U, int Current_Dim0, int Current_Dim1>
+inline void T2s_equals_generic(A &iter, const U &u,
+			   const Number<Current_Dim0> &N0,
+			   const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)=u;
+  T2s_equals_generic(iter,u,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class U, int Current_Dim1>
+inline void T2s_equals_generic(A &iter, const U &u,
+			   const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)=u;
+  T2s_equals_generic(iter,u,Number<Current_Dim1-1>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class U>
+inline void T2s_equals_generic(A &iter, const U &u,
+			       const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator=(const U &u)
+{
+  T2s_equals_generic(iter,u,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* T2s+=U */
+
+template<class A, class U, int Current_Dim0, int Current_Dim1>
+inline void T2s_plus_equals_generic(A &iter, const U &u,
+			   const Number<Current_Dim0> &N0,
+			   const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)+=u;
+  T2s_plus_equals_generic(iter,u,Number<Current_Dim0-1>(),
+			  Number<Current_Dim1>());
+}
+
+template<class A, class U, int Current_Dim1>
+inline void T2s_plus_equals_generic(A &iter, const U &u,
+			   const Number<1> &N0, const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)+=u;
+  T2s_plus_equals_generic(iter,u,Number<Current_Dim1-1>(),
+			  Number<Current_Dim1-1>());
+}
+
+template<class A, class U>
+inline void T2s_plus_equals_generic(A &iter, const U &u,
+				    const Number<1> &N0, const Number<1> &N1)
+{
+  iter(0,0)+=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator+=(const U &u)
+{
+  T2s_plus_equals_generic(iter,u,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* T2s-=U */
+
+template<class A, class U, int Current_Dim0, int Current_Dim1>
+inline void T2s_minus_equals_generic(A &iter,
+				     const U &u,
+				     const Number<Current_Dim0> &N0,
+				     const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)-=u;
+  T2s_minus_equals_generic(iter,u,Number<Current_Dim0-1>(),
+			   Number<Current_Dim1>());
+}
+
+template<class A, class U, int Current_Dim1>
+inline void T2s_minus_equals_generic(A &iter,
+				     const U &u, const Number<1> &N0,
+				     const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)-=u;
+  T2s_minus_equals_generic(iter,u,Number<Current_Dim1-1>(),
+			   Number<Current_Dim1-1>());
+}
+
+template<class A, class U>
+inline void T2s_minus_equals_generic(A &iter,
+				     const U &u, const Number<1> &N0,
+				     const Number<1> &N1)
+{
+  iter(0,0)-=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator-=(const U &u)
+{
+  T2s_minus_equals_generic(iter,u,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* T2s*=U */
+
+template<class A, class U, int Current_Dim0, int Current_Dim1>
+inline void T2s_times_equals_generic(A &iter,
+				     const U &u,
+				     const Number<Current_Dim0> &N0,
+				     const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)*=u;
+  T2s_times_equals_generic(iter,u,Number<Current_Dim0-1>(),
+			   Number<Current_Dim1>());
+}
+
+template<class A, class U, int Current_Dim1>
+inline void T2s_times_equals_generic(A &iter,
+				     const U &u, const Number<1> &N0,
+				     const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)*=u;
+  T2s_times_equals_generic(iter,u,Number<Current_Dim1-1>(),
+			   Number<Current_Dim1-1>());
+}
+
+template<class A, class U>
+inline void T2s_times_equals_generic(A &iter,
+				     const U &u, const Number<1> &N0,
+				     const Number<1> &N1)
+{
+  iter(0,0)*=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator*=(const U &u)
+{
+  T2s_times_equals_generic(iter,u,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* T2s/=U */
+
+template<class A, class U, int Current_Dim0, int Current_Dim1>
+inline void T2s_divide_equals_generic(A &iter,
+				      const U &u,
+				      const Number<Current_Dim0> &N0,
+				      const Number<Current_Dim1> &N1)
+{
+  iter(Current_Dim0-1,Current_Dim1-1)/=u;
+  T2s_divide_equals_generic(iter,u,Number<Current_Dim0-1>(),
+			    Number<Current_Dim1>());
+}
+
+template<class A, class U, int Current_Dim1>
+inline void T2s_divide_equals_generic(A &iter,
+				      const U &u, const Number<1> &N0,
+				      const Number<Current_Dim1> &N1)
+{
+  iter(0,Current_Dim1-1)/=u;
+  T2s_divide_equals_generic(iter,u,Number<Current_Dim1-1>(),
+			    Number<Current_Dim1-1>());
+}
+
+template<class A, class U>
+inline void T2s_divide_equals_generic(A &iter,
+				      const U &u, const Number<1> &N0,
+				      const Number<1> &N1)
+{
+  iter(0,0)/=u;
+}
+
+template<class A, class T, int Tensor_Dim, int Dim, char i, char j>
+template<class U> inline
+const Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor2_symmetric<A,Tensor_Dim>,T,Dim,i,j>::
+operator/=(const U &u)
+{
+  T2s_divide_equals_generic(iter,u,Number<Dim>(),Number<Dim>());
+  return *this;
+}
+
+/* Various assignment operators for Tensor3_dg_number_rhs_2.  I have
+   to explicitly declare the second operator= because otherwise the
+   compiler will generate its own and not use the template code. */
+
+template<class A, class B, class U, int Dim01, char i, char j, int N,
+  int Current_Dim0, int Current_Dim1> inline
+void T3dgrhs2_equals_T2s(A &iter,
+			 const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &result,
+			 const Number<Current_Dim0> &N0,
+			 const Number<Current_Dim1> &N1, const Number<N> &NN)
+{
+  iter(Current_Dim0-1,Current_Dim1-1,N)=result(Current_Dim0-1,Current_Dim1-1);
+  T3dgrhs2_equals_T2s(iter,result,Number<Current_Dim0-1>(),
+		      Number<Current_Dim1>(),Number<N>());
+}
+
+template<class A, class B, class U, int Dim01, char i, char j, int N,
+  int Current_Dim1> inline
+void T3dgrhs2_equals_T2s(A &iter,
+			 const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &result,
+			 const Number<1> &N0, const Number<Current_Dim1> &N1,
+			 const Number<N> &NN)
+{
+  iter(0,Current_Dim1-1,N)=result(0,Current_Dim1-1);
+  T3dgrhs2_equals_T2s(iter,result,Number<Current_Dim1-1>(),
+		      Number<Current_Dim1-1>(),Number<N>());
+}
+
+template<class A, class B, class U, int Dim01, char i, char j, int N>
+inline
+void T3dgrhs2_equals_T2s(A &iter,
+			 const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &result,
+			 const Number<1> &N0, const Number<1> &N1,
+			 const Number<N> &NN)
+{
+  iter(0,0,N)=result(0,0);
+}
+
+template<class A, class T, int Dim, char i, char j, int N>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,
+  T,Dim,i,j>::operator=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result)
+{
+  T3dgrhs2_equals_T2s(iter,result,Number<Dim>(),Number<Dim>(),Number<N>());
+  return *this;
+}
+
+template<class A, class T, int Dim, char i, char j, int N> inline
+const Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<A,T,N>,T,Dim,i,j>
+::operator=(const Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2
+	    <A,T,N>,T,Dim,i,j> &result)
+{
+  return operator=<Tensor3_dg_number_rhs_2<A,T,N>,T>(result);
+}
+
+
+/* Various assignment operators for Tensor4_ddg_number_rhs_01.  I have
+   to explicitly declare the second operator= because otherwise the
+   compiler will generate its own and not use the template code. */
+
+template<class A, class B, class U, int Dim01, char i, char j, int N0, int N1,
+  int Current_Dim0, int Current_Dim1> inline
+void T4ddgrhs01_equals_T2s(A &iter,
+			   const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &result,
+			   const Number<Current_Dim0> &N2,
+			   const Number<Current_Dim1> &N3,
+			   const Number<N0> &NN0,  const Number<N1> &NN1)
+{
+  iter(N0,N1,Current_Dim0-1,Current_Dim1-1)=
+    result(Current_Dim0-1,Current_Dim1-1);
+  T4ddgrhs01_equals_T2s(iter,result,Number<Current_Dim0-1>(),
+		      Number<Current_Dim1>(),Number<N0>(),Number<N1>());
+}
+
+template<class A, class B, class U, int Dim01, char i, char j, int N0, int N1,
+  int Current_Dim1> inline
+void T4ddgrhs01_equals_T2s(A &iter,
+			 const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &result,
+			 const Number<1> &N2, const Number<Current_Dim1> &N3,
+			   const Number<N0> &NN0, const Number<N1> &NN1)
+{
+  iter(N0,N1,0,Current_Dim1-1)=result(0,Current_Dim1-1);
+  T4ddgrhs01_equals_T2s(iter,result,Number<Current_Dim1-1>(),
+			Number<Current_Dim1-1>(),Number<N0>(),Number<N1>());
+}
+
+template<class A, class B, class U, int Dim01, char i, char j, int N0, int N1>
+inline
+void T4ddgrhs01_equals_T2s(A &iter,
+			 const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &result,
+			 const Number<1> &N2, const Number<1> &N3,
+			   const Number<N0> &NN0, const Number<N1> &NN1)
+{
+  iter(N0,N1,0,0)=result(0,0);
+}
+
+template<class A, class T, int Dim, char i, char j, int N0, int N1>
+template<class B, class U> inline
+const Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,
+  T,Dim,i,j>::operator=(const Tensor2_symmetric_Expr<B,U,Dim,i,j> &result)
+{
+  T4ddgrhs01_equals_T2s(iter,result,Number<Dim>(),Number<Dim>(),
+			Number<N0>(),Number<N1>());
+  return *this;
+}
+
+template<class A, class T, int Dim, char i, char j, int N0, int N1> inline
+const Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,T,Dim,i,j> &
+Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,T,Dim,i,j>
+::operator=(const Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01
+	    <A,T,N0,N1>,T,Dim,i,j> &result)
+{
+  return operator=<Tensor4_ddg_number_rhs_01<A,T,N0,N1>,T>(result);
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_and_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_and_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,64 @@
+/* Multiply a Tensor2_symmetric and a Tensor2_symmetric together but
+   don't contract, yielding a Tensor2_symmetric. */
+
+/* A(i,j) & B(i,j) -> Tensor2_symmetric */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_and_Tensor2_symmetric_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)*iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_and_Tensor2_symmetric_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_and_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator&(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b)
+{
+  typedef const Tensor2_symmetric_and_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j) & B(j,i) -> Tensor2_symmetric */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_and_Tensor2_symmetric_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)*iterB(N2,N1);
+  }
+
+  Tensor2_symmetric_and_Tensor2_symmetric_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const Tensor2_symmetric_and_Tensor2_symmetric_10
+<A,B,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator&(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b)
+{
+  typedef const Tensor2_symmetric_and_Tensor2_symmetric_10<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_carat_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_carat_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,263 @@
+/* Creates a Tensor2_symmetric expression by contracting a
+   Tensor2_symmetric and a Tensor2 together. There are different
+   versions, depending on where the contracting indices are located
+   (i.e. whether it is A(i,j)^B(j,k) or A(i,j)^B(k,j)).  The classes
+   are numbered to differentiate between these.  Thus, A(i,j)^B(j,k)
+   has 10 appended to the name because I count from 0. */
+
+/* A(i,j)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor2_symmetric_carat_Tensor2_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,j,k> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(0,N2);
+  }
+public:
+  Tensor2_symmetric_carat_Tensor2_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_10<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,j,k> &b)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_10<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(j,k)*A(i,j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_10<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<B,U,Dim,Dim,j,k> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_10<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+
+
+
+
+
+
+/* A(i,j)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor2_symmetric_carat_Tensor2_11
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,k,j> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(N2,0);
+  }
+public:
+  Tensor2_symmetric_carat_Tensor2_11
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,k,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_11<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,k,j> &b)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_11<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(k,j)*A(i,j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_11<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<B,U,Dim,Dim,k,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_11<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+
+
+
+
+
+
+/* A(j,i)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor2_symmetric_carat_Tensor2_00
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,j,k> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(0,N2);
+  }
+public:
+  Tensor2_symmetric_carat_Tensor2_00
+  (const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_00<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,j,k> &b)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_00<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,i) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_00<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<B,U,Dim,Dim,j,k> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_00<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+
+
+
+
+
+/* A(j,i)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor2_symmetric_carat_Tensor2_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,k,j> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(N2,0);
+  }
+public:
+  Tensor2_symmetric_carat_Tensor2_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,k,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_01<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,k,j> &b)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_01<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(k,j)*A(j,i) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_carat_Tensor2_01<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_Expr<B,U,Dim,Dim,k,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a)
+{
+  typedef const Tensor2_symmetric_carat_Tensor2_01<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_constructor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_constructor.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,53 @@
+/* A helper class that allows simple initialization of the Tensor2_symmetric,
+   but only if it has the correct number of elements. */
+
+template<class T, int Tensor_Dim>
+class Tensor2_symmetric_constructor;
+
+template<class T>
+class Tensor2_symmetric_constructor<T,2>
+{
+public:
+  Tensor2_symmetric_constructor(T data[(2*3)/2], T d00, T d01, T d11)
+  {
+    data[0]=d00;
+    data[1]=d01;
+    data[2]=d11;
+  }
+};
+
+template<class T>
+class Tensor2_symmetric_constructor<T,3>
+{
+public:
+  Tensor2_symmetric_constructor(T data[(3*4)/2], T d00, T d01, T d02,
+				T d11, T d12, T d22)
+  {
+    data[0]=d00;
+    data[1]=d01;
+    data[2]=d02;
+    data[3]=d11;
+    data[4]=d12;
+    data[5]=d22;
+  }
+};
+
+template<class T>
+class Tensor2_symmetric_constructor<T,4>
+{
+public:
+  Tensor2_symmetric_constructor(T data[(4*5)/2], T d00, T d01, T d02, T d03,
+				T d11, T d12, T d13, T d22, T d23, T d33)
+  {
+    data[0]=d00;
+    data[1]=d01;
+    data[2]=d02;
+    data[3]=d03;
+    data[4]=d11;
+    data[5]=d12;
+    data[6]=d13;
+    data[7]=d22;
+    data[8]=d23;
+    data[9]=d33;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_divide_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_divide_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,28 @@
+/* Divides a Tensor2_symmetric by a generic, yielding a
+   Tensor2_symmetric. */
+
+template<class A, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_divide_generic
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)/d;
+  }
+
+  Tensor2_symmetric_divide_generic
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_divide_generic<A,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator/(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a, const U &d0)
+{
+  typedef const Tensor2_symmetric_divide_generic<A,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,115 @@
+/* Subtracts a Tensor2 from a Tensor2_symmetric (or vice versa),
+   yielding a Tensor2. */
+
+/* A(i,j)-B(i,j), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_minus_Tensor2_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)-iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_minus_Tensor2_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_symmetric_minus_Tensor2_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator-(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,i,j> &b)
+{
+  typedef const Tensor2_symmetric_minus_Tensor2_01<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
+
+/* B(i,j)-A(i,j), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_minus_Tensor2_symmetric_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterB(N1,N2)-iterA(N1,N2);
+  }
+
+  Tensor2_minus_Tensor2_symmetric_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_minus_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator-(const Tensor2_Expr<B,U,Dim,Dim,i,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+	  
+{
+  typedef const Tensor2_minus_Tensor2_symmetric_01<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
+
+/* A(i,j)-B(j,i), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_minus_Tensor2_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)-iterB(N2,N1);
+  }
+
+  Tensor2_symmetric_minus_Tensor2_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,j,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_symmetric_minus_Tensor2_10<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator-(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,j,i> &b)
+{
+  typedef const Tensor2_symmetric_minus_Tensor2_10<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
+
+/* B(j,i)-A(i,j), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_minus_Tensor2_symmetric_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterB(N2,N1)-iterA(N1,N2);
+  }
+
+  Tensor2_minus_Tensor2_symmetric_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,j,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_minus_Tensor2_symmetric_10<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator-(const Tensor2_Expr<B,U,Dim,Dim,j,i> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_minus_Tensor2_symmetric_10<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_minus_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,65 @@
+/* Subtracts a Tensor2_symmetric from a Tensor2_symmetric, yielding a
+   Tensor2_symmetric. */
+
+/* A(i,j) - B(i,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_minus_Tensor2_symmetric_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)-iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_minus_Tensor2_symmetric_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_minus_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator-(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b)
+{
+  typedef const Tensor2_symmetric_minus_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j) - B(j,i) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_minus_Tensor2_symmetric_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)-iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_minus_Tensor2_symmetric_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_minus_Tensor2_symmetric_10<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator-(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b)
+{
+  typedef const Tensor2_symmetric_minus_Tensor2_symmetric_10<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_minus_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_minus_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,27 @@
+/* Subtracts a generic from a Tensor2_symmetric, yielding a
+   Tensor2_symmetric. */
+
+template<class A, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_minus_generic
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)-d;
+  }
+
+  Tensor2_symmetric_minus_generic(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+				  const U &d0): iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_minus_generic<A,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator-(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a, const U &d0)
+{
+  typedef const Tensor2_symmetric_minus_generic<A,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_mod_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_mod_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,64 @@
+/* Divides a Tensor2_symmetric by a Tensor2_symmetric together but
+   don't contract, yielding a Tensor2_symmetric. */
+
+/* A(i,j) % B(i,j) -> Tensor2_symmetric */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_mod_Tensor2_symmetric_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)/iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_mod_Tensor2_symmetric_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_mod_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator%(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b)
+{
+  typedef const Tensor2_symmetric_mod_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j) % B(j,i) -> Tensor2_symmetric */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_mod_Tensor2_symmetric_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)/iterB(N2,N1);
+  }
+
+  Tensor2_symmetric_mod_Tensor2_symmetric_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const Tensor2_symmetric_mod_Tensor2_symmetric_10
+<A,B,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator%(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b)
+{
+  typedef const Tensor2_symmetric_mod_Tensor2_symmetric_10<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,82 @@
+/* Adds a Tensor2_symmetric to a Tensor2, yielding a Tensor2. */
+
+/* A(i,j)+B(i,j), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_plus_Tensor2_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_plus_Tensor2_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_symmetric_plus_Tensor2_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator+(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,i,j> &b)
+{
+  typedef const Tensor2_symmetric_plus_Tensor2_01<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
+
+/* B(i,j)+A(i,j), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_symmetric_plus_Tensor2_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator+(const Tensor2_Expr<B,U,Dim,Dim,i,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_plus_Tensor2_01<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
+
+/* A(i,j)+B(j,i), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_plus_Tensor2_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N2,N1);
+  }
+
+  Tensor2_symmetric_plus_Tensor2_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim,j,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_symmetric_plus_Tensor2_10<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator+(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim,j,i> &b)
+{
+  typedef const Tensor2_symmetric_plus_Tensor2_10<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
+
+/* B(j,i)+A(i,j), A is symmetric, B is not. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_Expr<const Tensor2_symmetric_plus_Tensor2_10<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,Dim,i,j>
+operator+(const Tensor2_Expr<B,U,Dim,Dim,j,i> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_plus_Tensor2_10<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j>(TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_plus_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,64 @@
+/* Adds a Tensor2_symmetric to a Tensor2_symmetric, yielding a
+   Tensor2_symmetric. */
+
+/* A(i,j) + B(i,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_plus_Tensor2_symmetric_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,i,j> iterB;
+public:
+  typename promote<T,U>::V  operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_plus_Tensor2_symmetric_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_plus_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator+(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b)
+{
+  typedef const Tensor2_symmetric_plus_Tensor2_symmetric_01<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j) + B(j,i) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_plus_Tensor2_symmetric_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+iterB(N1,N2);
+  }
+
+  Tensor2_symmetric_plus_Tensor2_symmetric_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_plus_Tensor2_symmetric_10<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i,j>
+operator+(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b)
+{
+  typedef const Tensor2_symmetric_plus_Tensor2_symmetric_10<A,B,T,U,Dim,i,j>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_plus_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_plus_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+/* Adds a Tensor2_symmetric to a generic, yielding a
+   Tensor2_symmetric. */
+
+template<class A, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_plus_generic
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)+d;
+  }
+
+  Tensor2_symmetric_plus_generic(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+				  const U &d0): iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_plus_generic<A,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator+(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a, const U &d0)
+{
+  typedef const Tensor2_symmetric_plus_generic<A,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,d0));
+}
+
+template<class A, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_plus_generic<A,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator+(const U &d0, const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_plus_generic<A,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_pointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_pointer.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,226 @@
+/* A version for pointers. */
+
+template <class T, int Tensor_Dim>
+class Tensor2_symmetric<T*,Tensor_Dim>
+{
+  mutable T* restrict data[(Tensor_Dim*(Tensor_Dim+1))/2];
+public:
+  Tensor2_symmetric() {}
+
+  /* Tensor_Dim=2 */
+  Tensor2_symmetric(T* d00, T* d01, T* d11)
+  {
+    Tensor2_symmetric_constructor<T* restrict,Tensor_Dim>(data,d00,d01,d11);
+  }
+
+  /* Tensor_Dim=3 */
+  Tensor2_symmetric(T* d00, T* d01, T* d02, T* d11, T* d12, T* d22)
+  {
+    Tensor2_symmetric_constructor<T* restrict,Tensor_Dim>(data,d00,d01,d02,d11,d12,d22);
+  }
+
+  /* Tensor_Dim=4 */
+  Tensor2_symmetric(T* d00, T* d01, T* d02, T* d03, T* d11, T* d12, T* d13,
+		    T* d22, T* d23, T* d33)
+  {
+    Tensor2_symmetric_constructor<T* restrict,Tensor_Dim>
+      (data,d00,d01,d02,d03,d11,d12,d13,d22,d23,d33);
+  }
+
+  /* There are two operator(int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim || N1<0 || N2>=Tensor_Dim || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2_symmetric<T*," << Tensor_Dim
+		  << ">.operator(" << N1 << "," << N2 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? *data[N1+(N2*(2*Tensor_Dim-N2-1))/2]
+      : *data[N2+(N1*(2*Tensor_Dim-N1-1))/2];
+  }
+
+  T operator()(const int N1, const int N2) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim || N1<0 || N2>=Tensor_Dim || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2_symmetric<T*," << Tensor_Dim
+		  << ">.operator(" << N1 << "," << N2 << ") const"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? *data[N1+(N2*(2*Tensor_Dim-N2-1))/2]
+      : *data[N2+(N1*(2*Tensor_Dim-N1-1))/2];
+  }
+
+  T* ptr(const int N1, const int N2) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim || N1<0 || N2>=Tensor_Dim || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2_symmetric<T*," << Tensor_Dim
+		  << ">.ptr(" << N1 << "," << N2 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? data[N1+(N2*(2*Tensor_Dim-N2-1))/2]
+      : data[N2+(N1*(2*Tensor_Dim-N1-1))/2];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  /* This returns a Tensor2_Expr, since the indices are not really
+     symmetric anymore since they cover different dimensions. */
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<Tensor2_symmetric<T*,Tensor_Dim>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2)
+  {
+    return Tensor2_Expr<Tensor2_symmetric<T*,Tensor_Dim>,T,Dim0,Dim1,i,j>
+      (*this);
+  }
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<const Tensor2_symmetric<T*,Tensor_Dim>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2) const
+  {
+    return Tensor2_Expr<const Tensor2_symmetric<T*,Tensor_Dim>,T,Dim0,Dim1,i,j>
+      (*this);
+  }
+
+  /* This returns a Tensor2_symmetric_Expr, since the indices are still
+     symmetric on the lower dimensions. */
+
+  template<char i, char j, int Dim>
+  Tensor2_symmetric_Expr<Tensor2_symmetric<T*,Tensor_Dim>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2)
+  {
+    return Tensor2_symmetric_Expr<Tensor2_symmetric<T*,Tensor_Dim>,T,Dim,i,j>
+      (*this);
+  }
+
+  template<char i, char j, int Dim>
+  Tensor2_symmetric_Expr<const Tensor2_symmetric<T*,Tensor_Dim>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2) const
+  {
+    return Tensor2_symmetric_Expr<const Tensor2_symmetric<T*,Tensor_Dim>,
+      T,Dim,i,j>(*this);
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     an index for another, yielding a Tensor1_Expr.  The non-const
+     versions don't actually create a Tensor2_number_rhs_[01] object.
+     They create a Tensor1_Expr directly, which provides the
+     appropriate indexing operators.  The const versions do create a
+     Tensor2_number_[01]. */
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<Tensor2_number_rhs_1<Tensor2_symmetric<T*,Tensor_Dim>,T,N>,
+    T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> &n1)
+  {
+    typedef Tensor2_number_rhs_1<Tensor2_symmetric<T*,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<const Tensor2_number_1<const Tensor2_symmetric<T*,Tensor_Dim>,
+    T,N>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> &n1) const
+  {
+    typedef const Tensor2_number_1<const Tensor2_symmetric<T*,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<Tensor2_number_rhs_0<Tensor2_symmetric<T*,Tensor_Dim>,T,N>,
+    T,Dim,i>
+  operator()(const Number<N> &n1, const Index<i,Dim> index1)
+  {
+    typedef Tensor2_number_rhs_0<Tensor2_symmetric<T*,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<const Tensor2_number_0<const Tensor2_symmetric<T*,Tensor_Dim>,
+    T,N>,T,Dim,i>
+  operator()(const Number<N> &n1, const Index<i,Dim> index1) const
+  {
+    typedef const Tensor2_number_0<const Tensor2_symmetric<T*,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Specializations for using actual numbers instead of Number<> */
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor2_numeral_1<const Tensor2_symmetric<T*,Tensor_Dim>,
+    T>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const int N) const
+  {
+    typedef const Tensor2_numeral_1<const Tensor2_symmetric<T*,Tensor_Dim>,T>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
+  }
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor2_numeral_0<const Tensor2_symmetric<T*,Tensor_Dim>,
+    T>,T,Dim,i>
+  operator()(const int N, const Index<i,Dim> index1) const
+  {
+    typedef const Tensor2_numeral_0<const Tensor2_symmetric<T*,Tensor_Dim>,T>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
+  }
+  
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+
+  const Tensor2_symmetric<T*,Tensor_Dim> & operator++() const
+  {
+    for(int i=0;i<(Tensor_Dim*(Tensor_Dim+1))/2;++i)
+      ++data[i];
+    return *this;
+  }
+
+  /* These two operator()'s return the Tensor2 with internal
+     contractions, yielding a T.  I have to specify one for both
+     const and non-const because otherwise the compiler will use the
+     operator() which gives a Tensor2_Expr<>. */
+  
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2)
+  {
+    return internal_contract(Number<Dim>());
+  }
+
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2) const
+  {
+    return internal_contract(Number<Dim>());
+  }
+private:
+  template<int N>
+  T internal_contract(Number<N>)
+  {
+    return *data[N-1+((N-1)*(2*Tensor_Dim-N))/2]
+      + internal_contract(Number<N-1>());
+  }
+
+  T internal_contract(Number<1>)
+  {
+    return *data[0];
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_times_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_times_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,151 @@
+/* This file has all of the declarations for expressions like
+   Tensor2_symmetric*Tensor1 and Tensor1*Tensor2_symmetric, yielding a
+   Tensor1 or Tensor3_dg. */
+
+/* A(i,j)*B(j) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+class Tensor2_symmetric_times_Tensor1_1
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor1_Expr<B,U,Dim,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(Current_Dim-1)
+      + eval(N1,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(0);
+  }
+public:
+  Tensor2_symmetric_times_Tensor1_1
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor1_Expr<B,U,Dim,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+inline const Tensor1_Expr<const Tensor2_symmetric_times_Tensor1_1<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor1_Expr<B,U,Dim,j> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor1_1<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* A(j,i)*B(j) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+class Tensor2_symmetric_times_Tensor1_0
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,j,i> iterA;
+  const Tensor1_Expr<B,U,Dim,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(Current_Dim-1)
+      + eval(N1,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(0);
+  }
+public:
+  Tensor2_symmetric_times_Tensor1_0
+  (const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+   const Tensor1_Expr<B,U,Dim,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+inline const Tensor1_Expr<const Tensor2_symmetric_times_Tensor1_0<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+	  const Tensor1_Expr<B,U,Dim,j> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor1_0<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* B(j)*A(i,j) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+inline const Tensor1_Expr<const Tensor2_symmetric_times_Tensor1_1<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor1_Expr<B,U,Dim,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_times_Tensor1_1<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* B(j)*A(j,i) -> Tensor1 */
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+inline const Tensor1_Expr<const Tensor2_symmetric_times_Tensor1_0<A,B,T,U,Dim,i,j>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor1_Expr<B,U,Dim,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a)
+{
+  typedef const Tensor2_symmetric_times_Tensor1_0<A,B,T,U,Dim,i,j> TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* A(i,j)*B(k) -> Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k>
+class Tensor2_symmetric_times_Tensor1
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor1_Expr<B,U,Dim2,k> iterB;
+public:
+  Tensor2_symmetric_times_Tensor1(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+			const Tensor1_Expr<B,U,Dim2,k> &b):
+    iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2)*iterB(N3);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr
+<const Tensor2_symmetric_times_Tensor1<A,B,T,U,Dim,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim2,i,j,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor1_Expr<B,U,Dim2,k> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor1<A,B,T,U,Dim,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(k)*A(i,j) -> Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr
+<const Tensor2_symmetric_times_Tensor1<A,B,T,U,Dim,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim2,i,j,k>
+operator*(const Tensor1_Expr<B,U,Dim2,k> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_times_Tensor1<A,B,T,U,Dim,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_times_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,380 @@
+/* This file has all of the declarations for
+   Tensor2_symmetric*Tensor2.  This includes the double
+   contraction A(i,j)*B(i,j) (yielding a double) as well as the more
+   complicated single contraction A(i,j)*B(j,k) (yielding a Tensor2
+   expression). */
+
+/* Double contraction. */
+
+/* A(i,j)*B(i,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_T2_01(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+		const Tensor2_Expr<B,U,Dim,Dim,i,j> &b,
+		const Number<Current_Dim0> &N0,
+		const Number<Current_Dim1> &N1)
+{
+  return a(Current_Dim0-1,Current_Dim1-1)*b(Current_Dim0-1,Current_Dim1-1)
+    + T2s_times_T2_01(a,b,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_T2_01(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+		const Tensor2_Expr<B,U,Dim,Dim,i,j> &b,
+		const Number<1> &N0,
+		const Number<Current_Dim1> &N1)
+{
+  return a(0,Current_Dim1-1)*b(0,Current_Dim1-1)
+    + T2s_times_T2_01(a,b,Number<Dim>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V
+T2s_times_T2_01(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+		const Tensor2_Expr<B,U,Dim,Dim,i,j> &b,
+		const Number<1> &N0,
+		const Number<1> &N1)
+{
+  return a(0,0)*b(0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+				 const Tensor2_Expr<B,U,Dim,Dim,i,j> &b)
+{
+  return T2s_times_T2_01(a,b,Number<Dim>(),Number<Dim>());
+}
+
+/* B(i,j)*A(i,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V operator*(const Tensor2_Expr<B,U,Dim,Dim,i,j> &b,
+				 const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+				 
+{
+  return T2s_times_T2_01(a,b,Number<Dim>(),Number<Dim>());
+}
+
+/* Double contraction with switched indices.  The perspicacious reader
+   will note that it just replicated code for the aligned indices case
+   above, but with B(i,j) -> B(j,i).  This is ok, since A is
+   symmetric. */
+
+/* A(i,j)*B(j,i) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  int Current_Dim0, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_T2_01(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+		const Tensor2_Expr<B,U,Dim,Dim,j,i> &b,
+		const Number<Current_Dim0> &N0,
+		const Number<Current_Dim1> &N1)
+{
+  return a(Current_Dim0-1,Current_Dim1-1)*b(Current_Dim0-1,Current_Dim1-1)
+    + T2s_times_T2_01(a,b,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_T2_01(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+		const Tensor2_Expr<B,U,Dim,Dim,j,i> &b,
+		const Number<1> &N0,
+		const Number<Current_Dim1> &N1)
+{
+  return a(0,Current_Dim1-1)*b(0,Current_Dim1-1)
+    + T2s_times_T2_01(a,b,Number<Dim>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V
+T2s_times_T2_01(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+		const Tensor2_Expr<B,U,Dim,Dim,j,i> &b,
+		const Number<1> &N0,
+		const Number<1> &N1)
+{
+  return a(0,0)*b(0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+				 const Tensor2_Expr<B,U,Dim,Dim,j,i> &b)
+{
+  return T2s_times_T2_01(a,b,Number<Dim>(),Number<Dim>());
+}
+
+/* B(j,i)*A(i,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V operator*(const Tensor2_Expr<B,U,Dim,Dim,j,i> &b,
+				 const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+				 
+{
+  return T2s_times_T2_01(a,b,Number<Dim>(),Number<Dim>());
+}
+
+/* Single contraction.  The wrapper class has a different name for
+   each possible placing of the indices (e.g. A(i,j)*B(j,k) has the
+   number 10 because the contraction indices are on the second and
+   first slots (counting from 0). */
+
+/* A(i,j)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim1,j,k> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(0,N2);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim,Dim1,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_10<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim1,j,k> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_10<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(j,k)*A(i,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_10<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_Expr<B,U,Dim,Dim1,j,k> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_10<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
+
+
+
+
+
+
+
+/* A(i,j)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_11
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim1,Dim,k,j> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(N2,0);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_11
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_Expr<B,U,Dim1,Dim,k,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_11<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim1,Dim,k,j> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_11<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(k,j)*A(i,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_11<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_Expr<B,U,Dim1,Dim,k,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_11<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
+
+
+
+
+
+
+
+/* A(j,i)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_00
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim,Dim1,j,k> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(0,N2);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_00
+  (const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+   const Tensor2_Expr<B,U,Dim,Dim1,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_00<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim,Dim1,j,k> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_00<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,i) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_00<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_Expr<B,U,Dim,Dim1,j,k> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_00<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
+
+
+
+
+
+
+/* A(j,i)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,j,i> iterA;
+  const Tensor2_Expr<B,U,Dim1,Dim,k,j> iterB;
+  
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(N2,0);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+   const Tensor2_Expr<B,U,Dim1,Dim,k,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_01<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+	  const Tensor2_Expr<B,U,Dim1,Dim,k,j> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_01<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(k,j)*A(j,i) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor2_symmetric_times_Tensor2_01<A,B,T,U,Dim,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim1,i,k>
+operator*(const Tensor2_Expr<B,U,Dim1,Dim,k,j> &b,
+	  const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_01<A,B,T,U,Dim,Dim1,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim1,i,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_times_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_times_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,296 @@
+/* This file has all of the declarations for
+   Tensor2_symmetric*Tensor2_symmetric.  This includes the double
+   contraction A(i,j)*B(i,j) (yielding a typename promote<T,U>::V) as well as the more
+   complicated single contraction A(i,j)*B(j,k) (yielding a Tensor2
+   expression), and no contractions A(i,j)*B(k,l) -> Tensor4_ddg */
+
+/* Double contraction. */
+
+/* A(i,j)*B(i,j) */
+
+
+template<class A, class B, class T, class U, int Dim, char i,
+  char j, int Current_Dim0, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_T2s(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	      const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b,
+	      const Number<Current_Dim0> &N0,
+	      const Number<Current_Dim1> &N1)
+{
+  return a(Current_Dim0-1,Current_Dim1-1)*b(Current_Dim0-1,Current_Dim1-1)
+    + T2s_times_T2s(a,b,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i,
+  char j, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_T2s(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	      const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b,
+	      const Number<1> &N0,
+	      const Number<Current_Dim1> &N1)
+{
+  return a(0,Current_Dim1-1)*b(0,Current_Dim1-1)
+    + T2s_times_T2s(a,b,Number<Dim>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V 
+T2s_times_T2s(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	      const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b,
+	      const Number<1> &N0, const Number<1> &N1)
+{
+  return a(0,0)*b(0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+inline const typename promote<T,U>::V operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+				 const Tensor2_symmetric_Expr<B,U,Dim,i,j> &b)
+{
+  return T2s_times_T2s(a,b,Number<Dim>(),Number<Dim>());
+}
+
+/* A(i,j)*B(j,i) */
+
+template<class A, class B, class T, class U, int Dim, char i,
+  char j, int Current_Dim0, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_switched_T2s(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	      const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b,
+	      const Number<Current_Dim0> &N0,
+	      const Number<Current_Dim1> &N1)
+{
+  return a(Current_Dim0-1,Current_Dim1-1)*b(Current_Dim1-1,Current_Dim0-1)
+    + T2s_times_switched_T2s(a,b,Number<Current_Dim0-1>(),
+			     Number<Current_Dim1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i,
+  char j, int Current_Dim1>
+inline const typename promote<T,U>::V
+T2s_times_switched_T2s(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	      const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b,
+	      const Number<1> &N0,
+	      const Number<Current_Dim1> &N1)
+{
+  return a(0,Current_Dim1-1)*b(Current_Dim1-1,0)
+    + T2s_times_switched_T2s(a,b,Number<Dim>(),Number<Current_Dim1-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j>
+inline const typename promote<T,U>::V 
+T2s_times_switched_T2s(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	      const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b,
+	      const Number<1> &N0, const Number<1> &N1)
+{
+  return a(0,0)*b(0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, char i,char j>
+inline const typename promote<T,U>::V
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,i> &b)
+{
+  return T2s_times_switched_T2s(a,b,Number<Dim>(),Number<Dim>());
+}
+
+/* Single contraction.  The wrapper class has a different name for
+   each possible placing of the indices (e.g. A(i,j)*B(j,k) has the
+   number 10 because the contraction indices are on the second and
+   first slots (counting from 0). */
+
+/* A(i,j)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_symmetric_10
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(0,N2);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_symmetric_10
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_symmetric_times_Tensor2_symmetric_10
+<A,B,T,U,Dim,i,j,k>,typename promote<T,U>::V,Dim,Dim,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_symmetric_10<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_symmetric_11
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,k,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,Current_Dim-1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(N1,0)*iterB(N2,0);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_symmetric_11
+  (const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,k,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_symmetric_times_Tensor2_symmetric_11
+<A,B,T,U,Dim,i,j,k>,typename promote<T,U>::V,Dim,Dim,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,k,j> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_symmetric_11<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(j,i)*B(j,k) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_symmetric_00
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,j,i> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(Current_Dim-1,N2)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(0,N2);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_symmetric_00
+  (const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_symmetric_times_Tensor2_symmetric_00
+<A,B,T,U,Dim,i,j,k>,typename promote<T,U>::V,Dim,Dim,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_symmetric_00<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(j,i)*B(k,j) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor2_symmetric_times_Tensor2_symmetric_01
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,j,i> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,k,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(Current_Dim-1,N1)*iterB(N2,Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const Number<1> &N) const
+  {
+    return iterA(0,N1)*iterB(N2,0);
+  }
+public:
+  Tensor2_symmetric_times_Tensor2_symmetric_01
+  (const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,k,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor2_Expr<const Tensor2_symmetric_times_Tensor2_symmetric_01
+<A,B,T,U,Dim,i,j,k>,typename promote<T,U>::V,Dim,Dim,i,k>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,j,i> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,k,j> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_symmetric_01<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j)*B(k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, 
+  char i, char j, char k, char l>
+class Tensor2_symmetric_times_Tensor2_symmetric
+{
+  const Tensor2_symmetric_Expr<A,T,Dim0,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim1,k,l> iterB;
+public:
+  Tensor2_symmetric_times_Tensor2_symmetric
+  (const Tensor2_symmetric_Expr<A,T,Dim0,i,j> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim1,k,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2)*iterB(N3,N4);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, 
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor2_symmetric_times_Tensor2_symmetric<A,B,T,U,Dim0,Dim1,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j,k,l>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim0,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim1,k,l> &b)
+{
+  typedef const Tensor2_symmetric_times_Tensor2_symmetric
+    <A,B,T,U,Dim0,Dim1,i,j,k,l> TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_times_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_times_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+/* Multiplies a Tensor2_symmetric with a generic, yielding a
+   Tensor2_symmetric. */
+
+template<class A, class T, class U, int Dim, char i, char j>
+class Tensor2_symmetric_times_generic
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2)*d;
+  }
+
+  Tensor2_symmetric_times_generic(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+				  const U &d0): iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_times_generic<A,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator*(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a, const U &d0)
+{
+  typedef const Tensor2_symmetric_times_generic<A,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,d0));
+}
+
+template<class A, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const Tensor2_symmetric_times_generic<A,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator*(const U &d0, const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const Tensor2_symmetric_times_generic<A,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/Tensor2_symmetric_value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/Tensor2_symmetric_value.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,202 @@
+/* A general version, not for pointers. */
+
+template <class T, int Tensor_Dim>
+class Tensor2_symmetric
+{
+  T data[(Tensor_Dim*(Tensor_Dim+1))/2];
+public:
+  Tensor2_symmetric() {}
+
+  /* Tensor_Dim=2 */
+  Tensor2_symmetric(T d00, T d01, T d11)
+  {
+    Tensor2_symmetric_constructor<T,Tensor_Dim>(data,d00,d01,d11);
+  }
+
+  /* Tensor_Dim=3 */
+  Tensor2_symmetric(T d00, T d01, T d02, T d11, T d12, T d22)
+  {
+    Tensor2_symmetric_constructor<T,Tensor_Dim>(data,d00,d01,d02,d11,d12,d22);
+  }
+
+  /* Tensor_Dim=4 */
+  Tensor2_symmetric(T d00, T d01, T d02, T d03, T d11, T d12, T d13, T d22,
+		    T d23, T d33)
+  {
+    Tensor2_symmetric_constructor<T,Tensor_Dim>
+      (data,d00,d01,d02,d03,d11,d12,d13,d22,d23,d33);
+  }
+
+  /* There are two operator(int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim || N1<0 || N2>=Tensor_Dim || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2_symmetric<T," << Tensor_Dim
+		  << ">.operator(" << N1 << "," << N2 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? data[N1+(N2*(2*Tensor_Dim-N2-1))/2]
+      : data[N2+(N1*(2*Tensor_Dim-N1-1))/2];
+  }
+
+  T operator()(const int N1, const int N2) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim || N1<0 || N2>=Tensor_Dim || N2<0)
+      {
+	std::cerr << "Bad index in Tensor2_symmetric<T," << Tensor_Dim
+		  << ">.operator(" << N1 << "," << N2 << ") const"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? data[N1+(N2*(2*Tensor_Dim-N2-1))/2]
+      : data[N2+(N1*(2*Tensor_Dim-N1-1))/2];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  /* This returns a Tensor2_Expr, since the indices are not really
+     symmetric anymore since they cover different dimensions. */
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<Tensor2_symmetric<T,Tensor_Dim>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2)
+  {
+    return Tensor2_Expr<Tensor2_symmetric<T,Tensor_Dim>,T,Dim0,Dim1,i,j>
+      (*this);
+  }
+
+  template<char i, char j, int Dim0, int Dim1>
+  Tensor2_Expr<const Tensor2_symmetric<T,Tensor_Dim>,T,Dim0,Dim1,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim1> index2) const
+  {
+    return Tensor2_Expr<const Tensor2_symmetric<T,Tensor_Dim>,T,Dim0,Dim1,i,j>
+      (*this);
+  }
+
+  /* This returns a Tensor2_symmetric_Expr, since the indices are still
+     symmetric on the lower dimensions. */
+
+  template<char i, char j, int Dim>
+  Tensor2_symmetric_Expr<Tensor2_symmetric<T,Tensor_Dim>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2)
+  {
+    return Tensor2_symmetric_Expr<Tensor2_symmetric<T,Tensor_Dim>,T,Dim,i,j>
+      (*this);
+  }
+
+  template<char i, char j, int Dim>
+  Tensor2_symmetric_Expr<const Tensor2_symmetric<T,Tensor_Dim>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2) const
+  {
+    return Tensor2_symmetric_Expr<const Tensor2_symmetric<T,Tensor_Dim>,
+      T,Dim,i,j>(*this);
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     an index for another, yielding a Tensor1_Expr.  The non-const
+     versions don't actually create a Tensor2_number_rhs_[01] object.
+     They create a Tensor1_Expr directly, which provides the
+     appropriate indexing operators.  The const versions do create a
+     Tensor2_number_[01]. */
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<Tensor2_number_rhs_1<Tensor2_symmetric<T,Tensor_Dim>,T,N>,
+    T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> &n1)
+  {
+    typedef Tensor2_number_rhs_1<Tensor2_symmetric<T,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<const Tensor2_number_1<const Tensor2_symmetric<T,Tensor_Dim>,
+    T,N>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Number<N> &n1) const
+  {
+    typedef const Tensor2_number_1<const Tensor2_symmetric<T,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<Tensor2_number_rhs_0<Tensor2_symmetric<T,Tensor_Dim>,T,N>,
+    T,Dim,i>
+  operator()(const Number<N> &n1, const Index<i,Dim> index1)
+  {
+    typedef Tensor2_number_rhs_0<Tensor2_symmetric<T,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N, int Dim>
+  Tensor1_Expr<const Tensor2_number_0<const Tensor2_symmetric<T,Tensor_Dim>,
+    T,N>,T,Dim,i>
+  operator()(const Number<N> &n1, const Index<i,Dim> index1) const
+  {
+    typedef const Tensor2_number_0<const Tensor2_symmetric<T,Tensor_Dim>,T,N>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Specializations for using actual numbers instead of Number<> */
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor2_numeral_1<const Tensor2_symmetric<T,Tensor_Dim>,
+    T>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const int N) const
+  {
+    typedef const Tensor2_numeral_1<const Tensor2_symmetric<T,Tensor_Dim>,T>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
+  }
+
+  template<char i, int Dim>
+  Tensor1_Expr<const Tensor2_numeral_0<const Tensor2_symmetric<T,Tensor_Dim>,
+    T>,T,Dim,i>
+  operator()(const int N, const Index<i,Dim> index1) const
+  {
+    typedef const Tensor2_numeral_0<const Tensor2_symmetric<T,Tensor_Dim>,T>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N));
+  }
+  
+  /* These two operator()'s return the Tensor2 with internal
+     contractions, yielding a T.  I have to specify one for both
+     const and non-const because otherwise the compiler will use the
+     operator() which gives a Tensor2_Expr<>. */
+  
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2)
+  {
+    return internal_contract(Number<Dim>());
+  }
+
+  template<char i, int Dim>
+  T operator()(const Index<i,Dim> index1, const Index<i,Dim> index2) const
+  {
+    return internal_contract(Number<Dim>());
+  }
+private:
+  template<int N>
+  T internal_contract(const Number<N> &n)
+  {
+    return data[N-1+((N-1)*(2*Tensor_Dim-N))/2]
+      + internal_contract(Number<N-1>());
+  }
+
+  T internal_contract(const Number<1> &n)
+  {
+    return data[0];
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/dTensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/dTensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,32 @@
+/* Takes a derivative of a Tensor2_symmetric, yielding a Tensor3_dg. */
+
+template<class T, int Dim01, int Dim2, char i, char j, char k>
+class dTensor2_symmetric
+{
+  const Tensor2_symmetric<T*,Dim01> &a;
+  const Tensor1<int,Dim2> &d_ijk;
+  const Tensor1<double,Dim2> &d_xyz;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2,
+				  const int N3) const
+  {
+    return (*(a.ptr(N1,N2)+d_ijk(N3))-*(a.ptr(N1,N2)-d_ijk(N3)))*d_xyz(N3)*0.5;
+  }
+  dTensor2_symmetric(const Tensor2_symmetric<T*,Dim01> &A,
+		     const Tensor1<int,Dim2> &D_ijk,
+		     const Tensor1<double,Dim2> &D_xyz)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz) {}
+};
+
+template<class T, int Dim01, int Dim2, char i, char j, char k>
+inline const Tensor3_dg_Expr<const dTensor2_symmetric<T,Dim01,Dim2,i,j,k>,
+  typename promote<T,double>::V,Dim01,Dim2,i,j,k>
+d(const Tensor2_symmetric<T*,Dim01> &a, const Index<i,Dim01> index1,
+  const Index<j,Dim01> index2, const Index<k,Dim2> index3,
+  const Tensor1<int,Dim2> &d_ijk,
+  const Tensor1<double,Dim2> &d_xyz)
+{
+  typedef const dTensor2_symmetric<T,Dim01,Dim2,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,double>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,d_ijk,d_xyz));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/d_boundary_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/d_boundary_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+/* Takes a derivative of a Tensor2_symmetric, yielding a Tensor3_dg.
+   This is mostly useful near boundaries where you might have to take
+   one-sided derivatives. */
+
+template<class T, int Dim01, int Dim2, char i, char j, char k>
+class d_boundary_Tensor2_symmetric
+{
+  const Tensor2_symmetric<T*,Dim01> &a;
+  const Tensor1<int,Dim2> &d_ijk;
+  const Tensor1<double,Dim2> &d_xyz;
+  const Tensor2<bool,Dim2,2> &boundary;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2,
+				  const int N3) const
+  {
+    return boundary(N3,0) ? 
+      (*(a.ptr(N1,N2)+d_ijk(N3))-a(N1,N2))*d_xyz(N3) :
+      (boundary(N3,1) ? 
+       (a(N1,N2)-*(a.ptr(N1,N2)-d_ijk(N3)))*d_xyz(N3) :
+       (*(a.ptr(N1,N2)+d_ijk(N3))-*(a.ptr(N1,N2)-d_ijk(N3)))*d_xyz(N3)*0.5);
+  }
+  d_boundary_Tensor2_symmetric(const Tensor2_symmetric<T*,Dim01> &A,
+			       const Tensor1<int,Dim2> &D_ijk,
+			       const Tensor1<double,Dim2> &D_xyz,
+			       const Tensor2<bool,Dim2,2> &Boundary)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) {}
+};
+
+template<class T, int Dim01, int Dim2, char i, char j, char k>
+inline const Tensor3_dg_Expr
+<const d_boundary_Tensor2_symmetric<T,Dim01,Dim2,i,j,k>,
+  typename promote<T,double>::V,Dim01,Dim2,i,j,k>
+d_boundary(const Tensor2_symmetric<T*,Dim01> &a, const Index<i,Dim01> index1,
+	   const Index<j,Dim01> index2, const Index<k,Dim2> index3,
+	   const Tensor1<int,Dim2> &d_ijk,
+	   const Tensor1<double,Dim2> &d_xyz,
+	   const Tensor2<bool,Dim2,2> &boundary)
+{
+  typedef const d_boundary_Tensor2_symmetric<T,Dim01,Dim2,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,double>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,d_ijk,d_xyz,boundary));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/d_one_sided_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/d_one_sided_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+/* Takes a one-sided derivative of a Tensor2_symmetric in a particular
+   direction, yielding a Tensor2_symmetric. */
+
+template<class T, int Dim, char i, char j, int axis>
+class d_one_sided_Tensor2_symmetric
+{
+  const Tensor2_symmetric<T*,Dim> &a;
+  const int di,dj,dk;
+  const double dx,dy,dz;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2) const
+  {
+    return axis==0 ? (a(N1,N2)-*(a.ptr(N1,N2)-di))*dx
+      : (axis==1 ? (a(N1,N2)-*(a.ptr(N1,N2)-dj))*dy
+	 : (a(N1,N2)-*(a.ptr(N1,N2)-dk))*dz);
+  }
+  d_one_sided_Tensor2_symmetric(const Tensor2_symmetric<T*,Dim> &A,
+				const int Di, const int Dj, const int Dk,
+				const double Dx, const double Dy,
+				const double Dz):
+    a(A), di(Di), dj(Dj), dk(Dk), dx(Dx), dy(Dy), dz(Dz) {}
+};
+
+template<class T, int Dim, char i, char j, int axis>
+inline const Tensor2_symmetric_Expr
+<const d_one_sided_Tensor2_symmetric<T,Dim,i,j,axis>,
+  typename promote<T,double>::V,Dim,i,j>
+d_one_sided(const Tensor2_symmetric<T*,Dim> &a, const Number<axis> n1,
+	    const Index<i,Dim> index1,
+	    const Index<j,Dim> index2,
+	    const int &di, const int &dj, const int &dk,
+	    const double &dx, const double &dy, const double &dz)
+{
+  typedef const d_one_sided_Tensor2_symmetric<T,Dim,i,j,axis> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,double>::V,Dim,i,j>
+    (TensorExpr(a,di,dj,dk,dx,dy,dz));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/ddTensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/ddTensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,39 @@
+/* Takes a second derivative of a Tensor2_symmetric, yielding a
+   Tensor4_ddg. */
+
+template<class T, int Dim01, int Dim23, char i, char j, char k, char l>
+class ddTensor2_symmetric
+{
+  const Tensor2_symmetric<T*,Dim01> &a;
+  const Tensor1<int,Dim23> &d_ijk;
+  const Tensor1<double,Dim23> &d_xyz;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2, const int N3,
+				  const int N4) const
+  {
+    return
+      N3==N4 ? (*(a.ptr(N1,N2)+d_ijk(N3))-2*a(N1,N2)+*(a.ptr(N1,N2)-d_ijk(N3)))
+      *d_xyz(N3)*d_xyz(N3) :
+      (*(a.ptr(N1,N2)+d_ijk(N3)+d_ijk(N4))
+       - *(a.ptr(N1,N2)-d_ijk(N3)+d_ijk(N4))
+       - *(a.ptr(N1,N2)+d_ijk(N3)-d_ijk(N4))
+       + *(a.ptr(N1,N2)-d_ijk(N3)-d_ijk(N4)))*d_xyz(N3)*d_xyz(N4)*0.25;
+  }
+  ddTensor2_symmetric(const Tensor2_symmetric<T*,Dim01> &A,
+		      const Tensor1<int,Dim23> &D_ijk,
+		      const Tensor1<double,Dim23> &D_xyz)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz) {}
+};
+
+template<class T, int Dim01, int Dim23, char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr<const ddTensor2_symmetric<T,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,double>::V,Dim01,Dim23,i,j,k,l>
+dd(const Tensor2_symmetric<T*,Dim01> &a,
+   const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+   const Index<k,Dim23> index3, const Index<l,Dim23> index4,
+   const Tensor1<int,Dim23> &d_ijk, const Tensor1<double,Dim23> &d_xyz)
+{
+  typedef const ddTensor2_symmetric<T,Dim01,Dim23,i,j,k,l> Tensor_Expr;
+  return Tensor4_ddg_Expr<Tensor_Expr,typename promote<T,double>::V,Dim01,Dim23,i,j,k,l>
+    (Tensor_Expr(a,d_ijk,d_xyz));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/dd_boundary_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/dd_boundary_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,81 @@
+/* Takes a second derivative of a Tensor2_symmetric, yielding a
+   Tensor4_ddg.  This is mostly useful near boundaries where you might
+   have to take one-sided derivatives. */
+
+template<class T, int Dim01, int Dim23, char i, char j, char k, char l>
+class dd_boundary_Tensor2_symmetric
+{
+  const Tensor2_symmetric<T*,Dim01> &a;
+  const Tensor1<int,Dim23> &d_ijk;
+  const Tensor1<double,Dim23> &d_xyz;
+  const Tensor2<bool,Dim23,2> &boundary;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2, const int N3,
+				  const int N4) const
+  {
+    return N3==N4 ?
+      (boundary(N3,0) ?
+       (*(a.ptr(N1,N2)+2*d_ijk(N3))-2**(a.ptr(N1,N2)+d_ijk(N3))+a(N1,N2)) :
+       (boundary(N3,1) ?
+	(a(N1,N2)-2**(a.ptr(N1,N2)-d_ijk(N3))+*(a.ptr(N1,N2)-2*d_ijk(N3))):
+	(*(a.ptr(N1,N2)+d_ijk(N3))-2*a(N1,N2)+*(a.ptr(N1,N2)-d_ijk(N3)))))
+       *d_xyz(N3)*d_xyz(N3) :
+      (boundary(N3,0) ?
+       (boundary(N4,0) ?
+	((*(a.ptr(N1,N2)+d_ijk(N3)+d_ijk(N4)) - *(a.ptr(N1,N2)+d_ijk(N4))
+	  - *(a.ptr(N1,N2)+d_ijk(N3)) + a(N1,N2))*d_xyz(N3)*d_xyz(N4)) :
+	(boundary(N4,1) ?
+	 ((*(a.ptr(N1,N2)+d_ijk(N3)) - a(N1,N2)
+	   - *(a.ptr(N1,N2)+d_ijk(N3)-d_ijk(N4))
+	   + *(a.ptr(N1,N2)-d_ijk(N4)))*d_xyz(N3)*d_xyz(N4)) :
+	 (*(a.ptr(N1,N2)+d_ijk(N3)+d_ijk(N4))
+	  - *(a.ptr(N1,N2)+d_ijk(N4))
+	  - *(a.ptr(N1,N2)+d_ijk(N3)-d_ijk(N4))
+	  + *(a.ptr(N1,N2)-d_ijk(N4)))*d_xyz(N3)*d_xyz(N4)*0.5)) :
+       (boundary(N3,1) ?
+	(boundary(N4,0) ?
+	 ((*(a.ptr(N1,N2)+d_ijk(N4)) - *(a.ptr(N1,N2)-d_ijk(N3)+d_ijk(N4))
+	   - a(N1,N2) + *(a.ptr(N1,N2)-d_ijk(N3)))*d_xyz(N3)*d_xyz(N4)) :
+	 (boundary(N4,1) ?
+	  ((a(N1,N2) - *(a.ptr(N1,N2)-d_ijk(N3))
+	    - *(a.ptr(N1,N2)-d_ijk(N4))
+	    + *(a.ptr(N1,N2)-d_ijk(N3)-d_ijk(N4)))*d_xyz(N3)*d_xyz(N4)) :
+	  (*(a.ptr(N1,N2)+d_ijk(N4))
+	   - *(a.ptr(N1,N2)-d_ijk(N3)+d_ijk(N4))
+	   - *(a.ptr(N1,N2)-d_ijk(N4))
+	   + *(a.ptr(N1,N2)-d_ijk(N3)-d_ijk(N4)))*d_xyz(N3)*d_xyz(N4)*0.5)) :
+	(boundary(N4,0) ?
+	 ((*(a.ptr(N1,N2)+d_ijk(N3)+d_ijk(N4))
+	   - *(a.ptr(N1,N2)-d_ijk(N3)+d_ijk(N4))
+	   - *(a.ptr(N1,N2)+d_ijk(N3))
+	   + *(a.ptr(N1,N2)-d_ijk(N3)))*d_xyz(N3)*d_xyz(N4)*0.5) :
+	 (boundary(N4,1) ?
+	  ((*(a.ptr(N1,N2)+d_ijk(N3))
+	    - *(a.ptr(N1,N2)-d_ijk(N3))
+	    - *(a.ptr(N1,N2)+d_ijk(N3)-d_ijk(N4))
+	    + *(a.ptr(N1,N2)-d_ijk(N3)-d_ijk(N4)))*d_xyz(N3)*d_xyz(N4)*0.5) :
+	  ((*(a.ptr(N1,N2)+d_ijk(N3)+d_ijk(N4))
+	    - *(a.ptr(N1,N2)-d_ijk(N3)+d_ijk(N4))
+	    - *(a.ptr(N1,N2)+d_ijk(N3)-d_ijk(N4))
+	    + *(a.ptr(N1,N2)-d_ijk(N3)-d_ijk(N4)))*d_xyz(N3)*d_xyz(N4)*0.25)))));
+  }
+  dd_boundary_Tensor2_symmetric(const Tensor2_symmetric<T*,Dim01> &A,
+		      const Tensor1<int,Dim23> &D_ijk,
+		      const Tensor1<double,Dim23> &D_xyz,
+		      const Tensor2<bool,Dim23,2> &Boundary)
+    : a(A), d_ijk(D_ijk), d_xyz(D_xyz), boundary(Boundary) {}
+};
+
+template<class T, int Dim01, int Dim23, char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr<const dd_boundary_Tensor2_symmetric<T,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,double>::V,Dim01,Dim23,i,j,k,l>
+dd_boundary(const Tensor2_symmetric<T*,Dim01> &a,
+   const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+   const Index<k,Dim23> index3, const Index<l,Dim23> index4,
+   const Tensor1<int,Dim23> &d_ijk, const Tensor1<double,Dim23> &d_xyz,
+   const Tensor2<bool,Dim23,2> &boundary)
+{
+  typedef const dd_boundary_Tensor2_symmetric<T,Dim01,Dim23,i,j,k,l> Tensor_Expr;
+  return Tensor4_ddg_Expr<Tensor_Expr,typename promote<T,double>::V,Dim01,Dim23,i,j,k,l>
+    (Tensor_Expr(a,d_ijk,d_xyz,boundary));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/diffusion_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/diffusion_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,44 @@
+/* Computes 2*del^2 of a Tensor2_symmetric<T*,Dim> but uses diagonal
+   derivatives for half of it.  Yields a Tensor2_symmetric. */
+
+template<class T, int Dim, char i, char j>
+class diffusion_Tensor2_symmetric
+{
+  const Tensor2_symmetric<T*,Dim> &a;
+  const int di,dj,dk;
+  const double dx;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2) const
+  {
+    return
+      ((*(a.ptr(N1,N2)+di) - 2*a(N1,N2) + *(a.ptr(N1,N2)-di))
+       + (*(a.ptr(N1,N2)+dj) - 2*a(N1,N2) + *(a.ptr(N1,N2)-dj))
+       + (*(a.ptr(N1,N2)+dk) - 2*a(N1,N2) + *(a.ptr(N1,N2)-dk))
+       + ((*(a.ptr(N1,N2)+di+dj) + *(a.ptr(N1,N2)+di-dj)
+	   + *(a.ptr(N1,N2)-di+dj) + *(a.ptr(N1,N2)-di-dj)
+	   - 4*a(N1,N2))
+	  + (*(a.ptr(N1,N2)+di+dk) + *(a.ptr(N1,N2)+di-dk)
+	     + *(a.ptr(N1,N2)-di+dk) + *(a.ptr(N1,N2)-di-dk)
+	     - 4*a(N1,N2))
+	  + (*(a.ptr(N1,N2)+dj+dk) + *(a.ptr(N1,N2)+dj-dk)
+	     + *(a.ptr(N1,N2)-dj+dk) + *(a.ptr(N1,N2)-dj-dk)
+	     - 4*a(N1,N2)))/(std::sqrt(2.0)))*dx*dx;
+  }
+  diffusion_Tensor2_symmetric(const Tensor2_symmetric<T*,Dim> &A, const int Di,
+			      const int Dj, const int Dk,
+			      const double Dx):
+    a(A), di(Di), dj(Dj), dk(Dk), dx(Dx) {}
+};
+
+template<class T, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const diffusion_Tensor2_symmetric<T,Dim,i,j>,typename promote<T,double>::V,Dim,i,j>
+diffusion(const Tensor2_symmetric<T*,Dim> &a, const Index<i,Dim> index1,
+	  const Index<j,Dim> index2,
+	  const int &di, const int &dj, const int &dk,
+	  const double &dx)
+{
+  typedef const diffusion_Tensor2_symmetric<T,Dim,i,j> Tensor_Expr;
+  return Tensor2_symmetric_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i,j>
+    (Tensor_Expr(a,di,dj,dk,dx));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/generic_minus_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/generic_minus_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,26 @@
+/* Subtracts a generic from a Tensor2_symmetric, yielding a
+   Tensor2_symmetric. */
+
+template<class A, class T, class U, int Dim, char i, char j>
+class generic_minus_Tensor2_symmetric
+{
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return d-iterA(N1,N2);
+  }
+  generic_minus_Tensor2_symmetric(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a,
+				  const U &d0): iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const generic_minus_Tensor2_symmetric<A,T,U,Dim,i,j>,typename promote<T,U>::V,Dim,i,j>
+operator-(const U &d0, const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const generic_minus_Tensor2_symmetric<A,T,U,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/interpolate_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/interpolate_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,55 @@
+/* Interpolates to (i0+distance[0], j0+distance[1], k0+distance[2])
+   yielding a Tensor2_symmetric.  (i0,j0,k0) are 3D array coordinates,
+   conjugate==1-distance, and (di,dj,dk) are the stride of the array
+   coordinates.  It is assumed that the Tensor2_symmetric<T*,Dim> is zero
+   centered. */
+
+template<class T, int Dim, char i, char j>
+class interpolate_Tensor2_symmetric
+{
+  const Tensor2_symmetric<T*,Dim> &a;
+  const int di,dj,dk,i0,j0,k0;
+  const double *distance, *conjugate;
+public:
+  typename promote<T,double>::V operator()(const int N1, const int N2) const
+  {
+  return 
+    conjugate[0]*conjugate[1]*conjugate[2]
+    * (*(a.ptr(N1,N2) + di*i0 + dj*j0 + dk*k0))
+    + distance[0]*conjugate[1]*conjugate[2]
+    * (*(a.ptr(N1,N2) + di*(i0+1) + dj*(j0) + dk*(k0)))
+    + conjugate[0]*distance[1]*conjugate[2]
+    * (*(a.ptr(N1,N2) + di*(i0) + dj*(j0+1) + dk*(k0)))
+    + distance[0]*distance[1]*conjugate[2]
+    * (*(a.ptr(N1,N2) + di*(i0+1) + dj*(j0+1) + dk*(k0)))
+    + conjugate[0]*conjugate[1]*distance[2]
+    * (*(a.ptr(N1,N2) + di*(i0) + dj*(j0) + dk*(k0+1)))
+    + distance[0]*conjugate[1]*distance[2]
+    * (*(a.ptr(N1,N2) + di*(i0+1) + dj*(j0) + dk*(k0+1)))
+    + conjugate[0]*distance[1]*distance[2]
+    * (*(a.ptr(N1,N2) + di*(i0) + dj*(j0+1) + dk*(k0+1)))
+    + distance[0]*distance[1]*distance[2]
+    * (*(a.ptr(N1,N2) + di*(i0+1) + dj*(j0+1) + dk*(k0+1)));
+  }
+  interpolate_Tensor2_symmetric(const Tensor2_symmetric<T*,Dim> &A, const int Di,
+				const int Dj, const int Dk, const int I0,
+				const int J0, const int K0,
+				const double Distance[3],
+				const double Conjugate[3]):
+    a(A), di(Di), dj(Dj), dk(Dk), i0(I0), j0(J0), k0(K0),
+    distance(Distance), conjugate(Conjugate) {}
+};
+
+template<class T, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr
+<const interpolate_Tensor2_symmetric<T,Dim,i,j>,typename promote<T,double>::V,Dim,i,j>
+interpolate(const Tensor2_symmetric<T*,Dim> &a, const Index<i,Dim> index1,
+	    const Index<j,Dim> index2,
+	    const int &di, const int &dj, const int &dk,
+	    const int &i0, const int &j0, const int &k0,
+	    const double distance[3], const double conjugate[3])
+{
+  typedef const interpolate_Tensor2_symmetric<T,Dim,i,j> Tensor_Expr;
+  return Tensor2_symmetric_Expr<Tensor_Expr,typename promote<T,double>::V,Dim,i,j>
+    (Tensor_Expr(a,di,dj,dk,i0,j0,k0,distance,conjugate));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor2_symmetric/minus_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor2_symmetric/minus_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,24 @@
+/* Unary minus operator. */
+
+template<class A, class T, int Dim, char i, char j>
+class minus_Tensor2_symmetric
+{
+public:
+  const Tensor2_symmetric_Expr<A,T,Dim,i,j> iterA;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return -iterA(N1,N2);
+  }
+  minus_Tensor2_symmetric(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a):
+    iterA(a) {}
+};
+
+template<class A, class T, int Dim, char i, char j>
+inline const Tensor2_symmetric_Expr<const minus_Tensor2_symmetric<A,T,Dim,i,j>,
+  T,Dim,i,j>
+operator-(const Tensor2_symmetric_Expr<A,T,Dim,i,j> &a)
+{
+  typedef const minus_Tensor2_symmetric<A,T,Dim,i,j> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(a));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,27 @@
+/* Declare a wrapper class for generic rank 3 Tensor expressions.
+   There isn't a Tensor3 class yet.  I only use Tensor3_Expr as an
+   intermediate expression which immediately get contracted with
+   something to make a Tensor2 or Tensor1. */
+
+#include "Tensor3_times_generic.h"
+#include "Tensor3_times_Tensor1.h"
+#include "Tensor3_times_Tensor2_symmetric.h"
+#include "Tensor3_times_Tensor2.h"
+#include "Tensor3_times_Tensor3.h"
+#include "Tensor3_times_Tensor3_dg.h"
+#include "Tensor3_plus_Tensor3.h"
+#include "Tensor3_or_Tensor3.h"
+#include "Tensor3_minus_Tensor3_dg.h"
+
+template<class A, class T, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_Expr
+{
+  A iter;
+public:
+  Tensor3_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N1,N2,N3);
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_contracted.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_contracted.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,77 @@
+/* A helper class that automatically returns the internal contraction
+   of a rank 3 tensor. */
+
+/* Contracts second and third indices. */
+
+template<class A, class T, int Dim>
+class Tensor3_contracted_12
+{
+  const A iterA;
+
+  template<int Current_Dim>
+  T eval(const int N, const Number<Current_Dim> &ND) const
+  {
+    return iterA(N,Current_Dim-1,Current_Dim-1)
+      + eval(N,Number<Current_Dim-1>());
+  }
+  T eval(const int N, const Number<1> &ND) const
+  {
+    return iterA(N,0,0);
+  }
+public:
+  T operator()(const int N) const
+  {
+    return eval(N,Number<Dim>());
+  }
+  Tensor3_contracted_12(const A &a): iterA(a) {}
+};
+
+/* Contracts first and third indices. */
+
+template<class A, class T, int Dim>
+class Tensor3_contracted_02
+{
+  const A iterA;
+
+  template<int Current_Dim>
+  T eval(const int N, const Number<Current_Dim> &ND) const
+  {
+    return iterA(Current_Dim-1,N,Current_Dim-1)
+      + eval(N,Number<Current_Dim-1>());
+  }
+  T eval(const int N, const Number<1> &ND) const
+  {
+    return iterA(0,N,0);
+  }
+public:
+  T operator()(const int N) const
+  {
+    return eval(N,Number<Dim>());
+  }
+  Tensor3_contracted_02(const A &a): iterA(a) {}
+};
+
+/* Contracts first and second indices. */
+
+template<class A, class T, int Dim>
+class Tensor3_contracted_01
+{
+  const A iterA;
+
+  template<int Current_Dim>
+  T eval(const int N, const Number<Current_Dim> &ND) const
+  {
+    return iterA(Current_Dim-1,Current_Dim-1,N)
+      + eval(N,Number<Current_Dim-1>());
+  }
+  T eval(const int N, const Number<1> &ND) const
+  {
+    return iterA(0,0,N);
+  }
+public:
+  T operator()(const int N) const
+  {
+    return eval(N,Number<Dim>());
+  }
+  Tensor3_contracted_01(const A &a): iterA(a) {}
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_minus_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_minus_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,132 @@
+/* Subtracts a Tensor3_dg from a Tensor3, yielding a Tensor3. */
+
+/* A(i,j,k)-B(i,j,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_minus_Tensor3
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N1,N2,N3);
+  }
+
+  Tensor3_minus_Tensor3(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+		       const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_minus_Tensor3<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator-(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b)
+{
+  typedef const Tensor3_minus_Tensor3<A,B,T,U,Dim0,Dim1,Dim2,i,j,k> TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)-B(i,k,j)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_minus_Tensor3_21
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N1,N3,N2);
+  }
+
+  Tensor3_minus_Tensor3_21(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			  const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b)
+    :iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_minus_Tensor3_21<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator-(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b)
+{
+  typedef const Tensor3_minus_Tensor3_21<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)-B(j,i,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_minus_Tensor3_10
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N2,N1,N3);
+  }
+
+  Tensor3_minus_Tensor3_10(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			  const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b)
+    :iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_minus_Tensor3_10<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator-(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b)
+{
+  typedef const Tensor3_minus_Tensor3_10<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)-B(k,i,j)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_minus_Tensor3_120
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N3,N1,N2);
+  }
+
+  Tensor3_minus_Tensor3_120(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			   const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_minus_Tensor3_120<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator-(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b)
+{
+  typedef const Tensor3_minus_Tensor3_120<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_or_Tensor3.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_or_Tensor3.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,66 @@
+/* Adds a Tensor3 to a Tensor3, yielding a Tensor3_dg. */
+
+/* A(i,j,k)+B(i,k,j)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+class Tensor3_or_Tensor3_12
+{
+  const Tensor3_Expr<A,T,Dim0,Dim12,Dim12,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N3,N1,N2)+iterB(N3,N2,N1);
+  }
+
+  Tensor3_or_Tensor3_12(const Tensor3_Expr<A,T,Dim0,Dim12,Dim12,i,j,k> &a,
+			const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr
+<const Tensor3_or_Tensor3_12<A,B,T,U,Dim0,Dim12,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim12,j,k,i>
+operator||(const Tensor3_Expr<A,T,Dim0,Dim12,Dim12,i,j,k> &a,
+	   const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b)
+{
+  typedef const Tensor3_or_Tensor3_12<A,B,T,U,Dim0,Dim12,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim12,j,k,i>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)+B(k,j,i)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim02, int Dim1,
+  char i, char j, char k>
+class Tensor3_or_Tensor3_02
+{
+  const Tensor3_Expr<A,T,Dim02,Dim1,Dim02,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim02,Dim1,Dim02,k,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N3,N2)+iterB(N2,N3,N1);
+  }
+
+  Tensor3_or_Tensor3_02(const Tensor3_Expr<A,T,Dim02,Dim1,Dim02,i,j,k> &a,
+			const Tensor3_Expr<B,U,Dim02,Dim1,Dim02,k,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim02, int Dim1,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr
+<const Tensor3_or_Tensor3_02<A,B,T,U,Dim02,Dim1,i,j,k>,
+  typename promote<T,U>::V,Dim02,Dim1,i,k,j>
+operator||(const Tensor3_Expr<A,T,Dim02,Dim1,Dim02,i,j,k> &a,
+	   const Tensor3_Expr<B,U,Dim02,Dim1,Dim02,k,j,i> &b)
+{
+  typedef const Tensor3_or_Tensor3_02<A,B,T,U,Dim02,Dim1,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim02,Dim1,i,k,j>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_plus_Tensor3.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_plus_Tensor3.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,132 @@
+/* Adds a Tensor3 to a Tensor3, yielding a Tensor3. */
+
+/* A(i,j,k)+B(i,j,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_plus_Tensor3
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N1,N2,N3);
+  }
+
+  Tensor3_plus_Tensor3(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+		       const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_plus_Tensor3<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b)
+{
+  typedef const Tensor3_plus_Tensor3<A,B,T,U,Dim0,Dim1,Dim2,i,j,k> TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)+B(i,k,j)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_plus_Tensor3_21
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N1,N3,N2);
+  }
+
+  Tensor3_plus_Tensor3_21(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			  const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b)
+    :iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_plus_Tensor3_21<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b)
+{
+  typedef const Tensor3_plus_Tensor3_21<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)+B(j,i,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_plus_Tensor3_10
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N2,N1,N3);
+  }
+
+  Tensor3_plus_Tensor3_10(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			  const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b)
+    :iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_plus_Tensor3_10<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b)
+{
+  typedef const Tensor3_plus_Tensor3_10<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)+B(k,i,j)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_plus_Tensor3_120
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N3,N1,N2);
+  }
+
+  Tensor3_plus_Tensor3_120(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			   const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr
+<const Tensor3_plus_Tensor3_120<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b)
+{
+  typedef const Tensor3_plus_Tensor3_120<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_times_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_times_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,123 @@
+/* Declarations for expressions like Tensor3*Tensor1 -> Tensor2 */
+
+/* A(i,j,k)*B(j) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_times_Tensor1_1
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor1_Expr<B,U,Dim1,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,Current_Dim-1,N2)*iterB(Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,0,N2)*iterB(0);
+  }
+public:
+  Tensor3_times_Tensor1_1(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			const Tensor1_Expr<B,U,Dim1,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor3_times_Tensor1_1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim2,i,k>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor1_Expr<B,U,Dim1,j> &b)
+{
+  typedef const Tensor3_times_Tensor1_1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim2,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(j)*A(i,j,k) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor3_times_Tensor1_1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim2,i,k>
+operator*(const Tensor1_Expr<B,U,Dim1,j> &b,
+	  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_times_Tensor1_1<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim2,i,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(i) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_times_Tensor1_0
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor1_Expr<B,U,Dim0,i> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(Current_Dim-1,N1,N2)*iterB(Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &N) const
+  {
+    return iterA(0,N1,N2)*iterB(0);
+  }
+public:
+  Tensor3_times_Tensor1_0(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			  const Tensor1_Expr<B,U,Dim0,i> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim0>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor3_times_Tensor1_0<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor1_Expr<B,U,Dim0,i> &b)
+{
+  typedef const Tensor3_times_Tensor1_0<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(i)*A(i,j,k) -> Tensor2 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor2_Expr
+<const Tensor3_times_Tensor1_0<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor1_Expr<B,U,Dim0,i> &b,
+	  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_times_Tensor1_0<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_times_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_times_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,274 @@
+/* This file has all of the declarations for expressions like
+   Tensor3*Tensor2 and Tensor2*Tensor3, yielding a
+   Tensor3 or Tensor1. */
+
+/* A(i,j,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_times_Tensor2_12
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim1,Dim2,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim1>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,0,0)*iterB(0,0);
+  }
+public:
+  Tensor3_times_Tensor2_12
+  (const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+   const Tensor2_Expr<B,U,Dim1,Dim2,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim1>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_12<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim1,Dim2,j,k> &b)
+{
+  typedef const Tensor3_times_Tensor2_12<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(i,j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_12<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor2_Expr<B,U,Dim1,Dim2,j,k> &b,
+	  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_times_Tensor2_12<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* A(j,i,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_times_Tensor2_02
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,i,k> iterA;
+  const Tensor2_Expr<B,U,Dim0,Dim2,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim0>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0)*iterB(0,0);
+  }
+public:
+  Tensor3_times_Tensor2_02
+  (const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,i,k> &a,
+   const Tensor2_Expr<B,U,Dim0,Dim2,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim0>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_02<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim1,i>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,i,k> &a,
+	  const Tensor2_Expr<B,U,Dim0,Dim2,j,k> &b)
+{
+  typedef const Tensor3_times_Tensor2_02<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim1,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,i,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_02<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim1,i>
+operator*(const Tensor2_Expr<B,U,Dim0,Dim2,j,k> &b,
+	  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,i,k> &a)
+{
+  typedef const Tensor3_times_Tensor2_02<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim1,i>(TensorExpr(a,b));
+}
+
+/* A(j,k,i)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_times_Tensor2_01
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,k,i> iterA;
+  const Tensor2_Expr<B,U,Dim0,Dim1,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,Current_Dim1-1,N1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,Current_Dim1-1,N1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim0>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,0,N1)*iterB(0,0);
+  }
+public:
+  Tensor3_times_Tensor2_01
+  (const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,k,i> &a,
+   const Tensor2_Expr<B,U,Dim0,Dim1,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim0>(),Number<Dim1>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_01<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,k,i> &a,
+	  const Tensor2_Expr<B,U,Dim0,Dim1,j,k> &b)
+{
+  typedef const Tensor3_times_Tensor2_01<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,k,i)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_01<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor2_Expr<B,U,Dim0,Dim1,j,k> &b,
+	  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,j,k,i> &a)
+{
+  typedef const Tensor3_times_Tensor2_01<A,B,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(k,l)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor3_times_Tensor2_0
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N) const
+  {
+    return iterA(N1,N2,Current_Dim-1)*iterB(Current_Dim-1,N3)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,N2,0)*iterB(0,N3);
+  }
+public:
+  Tensor3_times_Tensor2_0(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_times_Tensor2_0<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim3,i,j,l>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b)
+{
+  typedef const Tensor3_times_Tensor2_0<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim3,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l)*A(i,j,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_times_Tensor2_0<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim3,i,j,l>
+operator*(const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b,
+	  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_times_Tensor2_0<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim3,i,j,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_times_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_times_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,215 @@
+/* This file has all of the declarations for expressions like
+   Tensor3*Tensor2_symmetric and Tensor2_symmetric*Tensor3, yielding a
+   Tensor1. */
+
+/* A(i,j,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k>
+class Tensor3_times_Tensor2_symmetric_12
+{
+  const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,0,0)*iterB(0,0);
+  }
+public:
+  Tensor3_times_Tensor2_symmetric_12
+  (const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_symmetric_12<A,B,T,U,Dim0,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor3_times_Tensor2_symmetric_12<A,B,T,U,Dim0,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(i,j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_symmetric_12<A,B,T,U,Dim0,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim0,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b,
+	  const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a)
+{
+  typedef const Tensor3_times_Tensor2_symmetric_12<A,B,T,U,Dim0,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim0,i>(TensorExpr(a,b));
+}
+
+/* A(j,i,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim1, int Dim,
+  char i, char j, char k>
+class Tensor3_times_Tensor2_symmetric_02
+{
+  const Tensor3_Expr<A,T,Dim,Dim1,Dim,j,i,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0)*iterB(0,0);
+  }
+public:
+  Tensor3_times_Tensor2_symmetric_02
+  (const Tensor3_Expr<A,T,Dim,Dim1,Dim,j,i,k> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim1, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_symmetric_02<A,B,T,U,Dim1,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim1,i>
+operator*(const Tensor3_Expr<A,T,Dim,Dim1,Dim,j,i,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor3_times_Tensor2_symmetric_02<A,B,T,U,Dim1,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim1,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,i,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim1, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_symmetric_02<A,B,T,U,Dim1,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim1,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b,
+	  const Tensor3_Expr<A,T,Dim,Dim1,Dim,j,i,k> &a)
+{
+  typedef const Tensor3_times_Tensor2_symmetric_02<A,B,T,U,Dim1,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim1,i>(TensorExpr(a,b));
+}
+
+/* A(j,k,i)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim2, int Dim,
+  char i, char j, char k>
+class Tensor3_times_Tensor2_symmetric_01
+{
+  const Tensor3_Expr<A,T,Dim,Dim,Dim2,j,k,i> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,Current_Dim1-1,N1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,Current_Dim1-1,N1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,0,N1)*iterB(0,0);
+  }
+public:
+  Tensor3_times_Tensor2_symmetric_01
+  (const Tensor3_Expr<A,T,Dim,Dim,Dim2,j,k,i> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim2, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_symmetric_01<A,B,T,U,Dim2,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor3_Expr<A,T,Dim,Dim,Dim2,j,k,i> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor3_times_Tensor2_symmetric_01<A,B,T,U,Dim2,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,k,i)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim2, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_times_Tensor2_symmetric_01<A,B,T,U,Dim2,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b,
+	  const Tensor3_Expr<A,T,Dim,Dim,Dim2,j,k,i> &a)
+{
+  typedef const Tensor3_times_Tensor2_symmetric_01<A,B,T,U,Dim2,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_times_Tensor3.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_times_Tensor3.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,362 @@
+/* Fully contracts a Tensor3 with a Tensor3, yielding a typename promote<T,U>::V. */
+
+/* A(i,j,k)*B(i,j,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_012
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)
+    + T3_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_012
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim0-1,0,Current_Dim2-1)
+    + T3_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3_012
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(Current_Dim0-1,0,0)
+    + T3_times_T3_012(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3_012
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim1,Dim2,i,j,k> &b)
+{
+  return T3_times_T3_012(a,b,Number<Dim0>(),Number<Dim1>(),Number<Dim2>());
+}
+
+/* A(i,j,k)*B(k,i,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_201
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim2-1,Current_Dim0-1,Current_Dim1-1)
+    + T3_times_T3_201(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_201
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim2-1,Current_Dim0-1,0)
+    + T3_times_T3_201(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3_201
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,Current_Dim0-1,0)
+    + T3_times_T3_201(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3_201
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim2,Dim0,Dim1,k,i,j> &b)
+{
+  return T3_times_T3_201(a,b,Number<Dim0>(),Number<Dim1>(),Number<Dim2>());
+}
+
+/* A(i,j,k)*B(j,k,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_120
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim2,Dim0,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim1-1,Current_Dim2-1,Current_Dim0-1)
+    + T3_times_T3_120(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_120
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim2,Dim0,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(0,Current_Dim2-1,Current_Dim0-1)
+    + T3_times_T3_120(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3_120
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim2,Dim0,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,0,Current_Dim0-1)
+    + T3_times_T3_120(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3_120
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim2,Dim0,j,k,i> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim1,Dim2,Dim0,j,k,i> &b)
+{
+  return T3_times_T3_120(a,b,Number<Dim0>(),Number<Dim1>(),Number<Dim2>());
+}
+
+/* A(i,j,k)*B(j,i,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_102
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim1-1,Current_Dim0-1,Current_Dim2-1)
+    + T3_times_T3_102(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_102
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(0,Current_Dim0-1,Current_Dim2-1)
+    + T3_times_T3_102(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3_102
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,Current_Dim0-1,0)
+    + T3_times_T3_102(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3_102
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim1,Dim0,Dim2,j,i,k> &b)
+{
+  return T3_times_T3_102(a,b,Number<Dim0>(),Number<Dim1>(),Number<Dim2>());
+}
+
+/* A(i,j,k)*B(k,j,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_210
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim1,Dim0,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim2-1,Current_Dim1-1,Current_Dim0-1)
+    + T3_times_T3_210(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_210
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim1,Dim0,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim2-1,0,Current_Dim0-1)
+    + T3_times_T3_210(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3_210
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim1,Dim0,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,0,Current_Dim0-1)
+    + T3_times_T3_210(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3_210
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim2,Dim1,Dim0,k,j,i> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim2,Dim1,Dim0,k,j,i> &b)
+{
+  return T3_times_T3_210(a,b,Number<Dim0>(),Number<Dim1>(),Number<Dim2>());
+}
+
+/* A(i,j,k)*B(i,k,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_021
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim0-1,Current_Dim2-1,Current_Dim1-1)
+    + T3_times_T3_021(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3_021
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim0-1,Current_Dim2-1,0)
+    + T3_times_T3_021(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3_021
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(Current_Dim0-1,0,0)
+    + T3_times_T3_021(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3_021
+(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim2,Dim1,i,k,j> &b)
+{
+  return T3_times_T3_021(a,b,Number<Dim0>(),Number<Dim1>(),Number<Dim2>());
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_times_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_times_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,468 @@
+/* Contracts a Tensor3 with a Tensor3_dg, yielding a typename promote<T,U>::V,
+   Tensor2, or Tensor4. */
+
+/* A(i,j,k)*B(i,j,k) */
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_012
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)
+    + T3_times_T3dg_012(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_012
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim0-1,0,Current_Dim2-1)
+    + T3_times_T3dg_012(a,b,Number<Current_Dim0>(),
+			Number<Dim>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3dg_012
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(Current_Dim0-1,0,0)
+    + T3_times_T3dg_012(a,b,Number<Current_Dim0-1>(),
+			Number<Dim>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3dg_012
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,i,j,k> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim2,i,j,k> &b)
+{
+  return T3_times_T3dg_012(a,b,Number<Dim>(),Number<Dim>(),Number<Dim2>());
+}
+
+/* A(i,j,k)*B(k,i,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_201
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim2-1,Current_Dim0-1,Current_Dim1-1)
+    + T3_times_T3dg_201(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_201
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim2-1,Current_Dim0-1,0)
+    + T3_times_T3dg_201(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3dg_201
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,Current_Dim0-1,0)
+    + T3_times_T3dg_201(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3dg_201
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,k,i,j> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim1,k,i,j> &b)
+{
+  return T3_times_T3dg_201(a,b,Number<Dim>(),Number<Dim1>(),Number<Dim>());
+}
+
+/* A(i,j,k)*B(j,k,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_120
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim1-1,Current_Dim2-1,Current_Dim0-1)
+    + T3_times_T3dg_120(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_120
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(0,Current_Dim2-1,Current_Dim0-1)
+    + T3_times_T3dg_120(a,b,Number<Current_Dim0>(),
+			Number<Dim>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3dg_120
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,0,Current_Dim0-1)
+    + T3_times_T3dg_120(a,b,Number<Current_Dim0-1>(),
+			Number<Dim>(),Number<Dim>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3dg_120
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,j,k,i> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim0,j,k,i> &b)
+{
+  return T3_times_T3dg_120(a,b,Number<Dim0>(),Number<Dim>(),Number<Dim>());
+}
+
+/* A(i,j,k)*B(j,i,k) */
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_102
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim1-1,Current_Dim0-1,Current_Dim2-1)
+    + T3_times_T3dg_102(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_102
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(0,Current_Dim0-1,Current_Dim2-1)
+    + T3_times_T3dg_102(a,b,Number<Current_Dim0>(),
+			Number<Dim>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3dg_102
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,Current_Dim0-1,0)
+    + T3_times_T3dg_102(a,b,Number<Current_Dim0-1>(),
+			Number<Dim>(),Number<Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3dg_102
+(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim2,j,i,k> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim2,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim,Dim,Dim2,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim2,j,i,k> &b)
+{
+  return T3_times_T3dg_102(a,b,Number<Dim>(),Number<Dim>(),Number<Dim2>());
+}
+
+/* A(i,j,k)*B(k,j,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_210
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim2-1,Current_Dim1-1,Current_Dim0-1)
+    + T3_times_T3dg_210(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_210
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim2-1,0,Current_Dim0-1)
+    + T3_times_T3dg_210(a,b,Number<Current_Dim0>(),
+			Number<Dim>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3dg_210
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(0,0,Current_Dim0-1)
+    + T3_times_T3dg_210(a,b,Number<Current_Dim0-1>(),
+			Number<Dim>(),Number<Dim>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3dg_210
+(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim0,k,j,i> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim0,Dim,Dim,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim0,k,j,i> &b)
+{
+  return T3_times_T3dg_210(a,b,Number<Dim0>(),Number<Dim>(),Number<Dim>());
+}
+
+/* A(i,j,k)*B(i,k,j) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_021
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim0-1,Current_Dim2-1,Current_Dim1-1)
+    + T3_times_T3dg_021(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3_times_T3dg_021
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim0-1,Current_Dim2-1,0)
+    + T3_times_T3dg_021(a,b,Number<Current_Dim0>(),
+			Number<Dim1>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3_times_T3dg_021
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,0,0)*b(Current_Dim0-1,0,0)
+    + T3_times_T3dg_021(a,b,Number<Current_Dim0-1>(),
+			Number<Dim1>(),Number<Dim>());
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3_times_T3dg_021
+(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+ const Tensor3_dg_Expr<B,U,Dim,Dim1,i,k,j> &b,
+ const Number<1> &ND0, const Number<1> &ND1, const Number<1> &ND2)
+{
+  return a(0,0,0)*b(0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim, int Dim1,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<A,T,Dim,Dim1,Dim,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim1,i,k,j> &b)
+{
+  return T3_times_T3dg_021(a,b,Number<Dim>(),Number<Dim1>(),Number<Dim>());
+}
+
+
+/* A(j,i,k)*B(k,l,j) */
+
+template<class A, class B, class T, class U, int Dim2, int Dim1, int Dim01,
+  char i, char j, char k, char l>
+class Tensor3_times_Tensor3_dg_02_20
+{
+  const Tensor3_Expr<A,T,Dim2,Dim1,Dim01,j,i,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim01,Dim2,k,l,j> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1) const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1)
+      *iterB(Current_Dim1-1,N2,Current_Dim0-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1) const
+  {
+    return iterA(0,N1,Current_Dim1-1)*iterB(Current_Dim1-1,N2,0)
+      + eval(N1,N2,Number<Dim2>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0, const Number<1> &ND1) const
+  {
+    return iterA(0,N1,0)*iterB(0,N2,0);
+  }
+public:
+  Tensor3_times_Tensor3_dg_02_20
+  (const Tensor3_Expr<A,T,Dim2,Dim1,Dim01,j,i,k> &a,
+   const Tensor3_dg_Expr<B,U,Dim01,Dim2,k,l,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim2>(),Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim2, int Dim1, int Dim01,
+  char i, char j, char k, char l>
+inline const Tensor2_Expr
+<const Tensor3_times_Tensor3_dg_02_20<A,B,T,U,Dim2,Dim1,Dim01,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim01,i,l>
+operator*(const Tensor3_Expr<A,T,Dim2,Dim1,Dim01,j,i,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim01,Dim2,k,l,j> &b)
+{
+  typedef const Tensor3_times_Tensor3_dg_02_20<A,B,T,U,Dim2,Dim1,Dim01,i,j,k,l>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim01,i,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l,j)*A(j,i,k) */
+
+
+
+/* A(i,j,k)*B(l,k,m) -> Tensor4 */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim, char i, char j, char k, char l, char m>
+class Tensor3_times_Tensor3_dg
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim,Dim2,l,k,m> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3, const int N4,
+		       const Number<Current_Dim> &ND) const
+  {
+    return iterA(N1,N2,Current_Dim-1)*iterB(N3,Current_Dim-1,N4)
+      + eval(N1,N2,N3,N4,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3, const int N4,
+		       const Number<1> &ND) const
+  {
+    return iterA(N1,N2,0)*iterB(N3,0,N4);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return eval(N1,N2,N3,N4,Number<Dim>());
+  }
+  Tensor3_times_Tensor3_dg(const Tensor3_Expr<A,T,Dim0,Dim1,Dim,i,j,k> &a,
+			   const Tensor3_dg_Expr<B,U,Dim,Dim2,l,k,m> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim, char i, char j, char k, char l, char m>
+inline Tensor4_Expr
+<const Tensor3_times_Tensor3_dg<A,B,T,U,Dim0,Dim1,Dim,Dim2,i,j,k,l,m>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim,Dim2,i,j,l,m>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim2,l,k,m> &b)
+{
+  typedef const Tensor3_times_Tensor3_dg
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim,i,j,k,l,m> TensorExpr;
+  return Tensor4_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim,Dim2,i,j,l,m>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3/Tensor3_times_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3/Tensor3_times_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,47 @@
+/* Multiplies a Tensor3 with a generic, yielding a Tensor3. */
+
+/* A(i,j,k)*generic */
+
+template<class A, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+class Tensor3_times_generic
+{
+  const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)*d;
+  }
+
+  Tensor3_times_generic(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a,
+			const U &d0): iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr<const Tensor3_times_generic<A,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator*(const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a, const U &d0)
+{
+  typedef const Tensor3_times_generic<A,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,d0));
+}
+
+/* generic*A(i,j,k) */
+
+template<class A, class T, class U, int Dim0, int Dim1, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_Expr<const Tensor3_times_generic<A,T,U,Dim0,Dim1,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+operator*(const U &d0, const Tensor3_Expr<A,T,Dim0,Dim1,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_times_generic<A,T,U,Dim0,Dim1,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,i,j,k>
+    (TensorExpr(a,d0));
+}
+
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,11 @@
+/* Declaration for a Tensor3_antisymmetric.  This is antisymmetric on
+   the last two indices, so in 3 dimensions it only has 9 elements.
+   The first declaration is for T's (int, double, etc.) while the
+   second is for pointers to T's, so it is useful for previously
+   contructed arrays. */
+
+#include "Tensor3_antisymmetric/Tensor3_antisymmetric_constructor.h"
+#include "Tensor3_antisymmetric/Tensor3_antisymmetric_value.h"
+#include "Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.h"
+
+#include "Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,60 @@
+/* Declare a wrapper class for rank 3 Tensor expressions,
+   antisymmetric in the last two indices.  I specialize it for when I
+   wrap a simple Tensor3_antisymmetric(_ptr) so that it has a
+   reference to the Tensor3_antisymmetric(_ptr) and not a copy.
+   Otherwise assignment wouldn't work. */
+
+#include "Tensor3_antisymmetric_plus_Tensor3_antisymmetric.h"
+#include "Tensor3_antisymmetric_or_Tensor3_antisymmetric.h"
+#include "Tensor3_antisymmetric_times_Tensor3.h"
+//  #include "Tensor3_antisymmetric_mod_Tensor1.h"
+#include "Tensor3_antisymmetric_times_generic.h"
+
+template<class A, class T, int Dim0, int Dim12, char i, char j, char k>
+class Tensor3_antisymmetric_Expr
+{
+  A iter;
+public:
+  Tensor3_antisymmetric_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N1,N2,N3);
+  }
+};
+
+template<class A, class T, int Dim0, int Dim12, char i, char j, char k>
+class Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+  T,Dim0,Dim12,i,j,k>
+{
+  Tensor3_antisymmetric<A,Dim0,Dim12> &iter;
+public:
+  Tensor3_antisymmetric_Expr(Tensor3_antisymmetric<A,Dim0,Dim12> &a)
+    : iter(a) {}
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N1,N2,N3);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+    T,Dim0,Dim12,i,j,k> &
+  operator=(const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k> &result);
+
+  const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+    T,Dim0,Dim12,i,j,k> &
+  operator=(const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric
+	    <A,Dim0,Dim12>,T,Dim0,Dim12,i,j,k> &result);
+
+  /* This is for when the indices are switched (i,j,k) -> (i,k,j). */
+
+  template<class B, class U>
+  const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+    T,Dim0,Dim12,i,j,k> &
+  operator=(const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,k,j> &result);
+};
+
+#include "Tensor3_antisymmetric_Expr_equals.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_Expr_equals.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_Expr_equals.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,157 @@
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+/* T3as=T3as */
+
+template<class A, class B, class U, int Dim0, int Dim12, char i, char j,
+  char k, int Current_Dim0, int Current_Dim1, int Current_Dim2> inline
+void T3as_equals_T3as(A &iter,
+		      const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k>
+		      &result,
+		      const Number<Current_Dim0> &ND0,
+		      const Number<Current_Dim1> &ND1,
+		      const Number<Current_Dim2> &ND2)
+{
+  iter.unsafe(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)=
+    result(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1);
+  T3as_equals_T3as(iter,result,Number<Current_Dim0>(),Number<Current_Dim1-1>(),
+		   Number<Current_Dim2>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2> inline
+void T3as_equals_T3as(A &iter,
+		      const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k>
+		      &result,
+		      const Number<Current_Dim0> &ND0,
+		      const Number<1> &ND1,
+		      const Number<Current_Dim2> &ND2)
+{
+  iter.unsafe(Current_Dim0-1,0,Current_Dim2-1)=
+    result(Current_Dim0-1,0,Current_Dim2-1);
+  T3as_equals_T3as(iter,result,Number<Current_Dim0>(),Number<Current_Dim2-2>(),
+		   Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0> inline
+void T3as_equals_T3as(A &iter,
+		      const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k>
+		      &result,
+		      const Number<Current_Dim0> &ND0,
+		      const Number<1> &ND1,
+		      const Number<2> &ND2)
+{
+  iter.unsafe(Current_Dim0-1,0,1)=result(Current_Dim0-1,0,1);
+  T3as_equals_T3as(iter,result,Number<Current_Dim0-1>(),
+		   Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim12,
+  char i, char j, char k> inline
+void T3as_equals_T3as(A &iter,
+		      const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k>
+		      &result,
+		      const Number<1> &ND0,
+		      const Number<1> &ND1,
+		      const Number<2> &ND2)
+{
+  iter.unsafe(0,0,1)=result(0,0,1);
+}
+
+
+template<class A, class T, int Dim0, int Dim12, char i, char j, char k>
+template<class B, class U> inline
+const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+  T,Dim0,Dim12,i,j,k> &
+Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+  T,Dim0,Dim12,i,j,k>::
+operator=(const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k> &result)
+{
+  T3as_equals_T3as(iter,result,Number<Dim0>(),Number<Dim12-1>(),
+		   Number<Dim12>());
+  return *this;
+}
+
+/* T3as=T3as_Expr(T3as) */
+
+template<class A, class T, int Dim0, int Dim12, char i, char j, char k> inline
+const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+  T,Dim0,Dim12,i,j,k> &
+Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+  T,Dim0,Dim12,i,j,k>::
+operator=(const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric
+	  <A,Dim0,Dim12>,T,Dim0,Dim12,i,j,k> &result)
+{
+  return operator=<Tensor3_antisymmetric<A,Dim0,Dim12>,T>(result);
+}
+
+/* This is for when the indices are switched (i,j,k) -> (i,k,j). */
+
+template<class A, class B, class U, int Dim0, int Dim12, char i, char j,
+  char k, int Current_Dim0, int Current_Dim1, int Current_Dim2> inline
+void T3as_switched_equals_T3as(A &iter, const Tensor3_antisymmetric_Expr
+			       <B,U,Dim0,Dim12,i,k,j> &result,
+			       const Number<Current_Dim0> &ND0,
+			       const Number<Current_Dim1> &ND1,
+			       const Number<Current_Dim2> &ND2)
+{
+  iter.unsafe(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)=
+    -result(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1);
+  T3as_switched_equals_T3as(iter,result,Number<Current_Dim0>(),
+			    Number<Current_Dim1-1>(),
+			    Number<Current_Dim2>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2> inline
+void T3as_switched_equals_T3as(A &iter, const Tensor3_antisymmetric_Expr
+			       <B,U,Dim0,Dim12,i,k,j> &result,
+			       const Number<Current_Dim0> &ND0,
+			       const Number<1> &ND1,
+			       const Number<Current_Dim2> &ND2)
+{
+  iter.unsafe(Current_Dim0-1,0,Current_Dim2-1)=
+    -result(Current_Dim0-1,0,Current_Dim2-1);
+  T3as_switched_equals_T3as(iter,result,Number<Current_Dim0>(),
+			    Number<Current_Dim2-2>(),
+			    Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0> inline
+void T3as_switched_equals_T3as(A &iter, const Tensor3_antisymmetric_Expr
+			       <B,U,Dim0,Dim12,i,k,j> &result,
+			       const Number<Current_Dim0> &ND0,
+			       const Number<1> &ND1,
+			       const Number<2> &ND2)
+{
+  iter.unsafe(Current_Dim0-1,0,1)=-result(Current_Dim0-1,0,1);
+  T3as_switched_equals_T3as(iter,result,Number<Current_Dim0-1>(),
+			    Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class U, int Dim0, int Dim12,
+  char i, char j, char k> inline
+void T3as_switched_equals_T3as(A &iter, const Tensor3_antisymmetric_Expr
+			       <B,U,Dim0,Dim12,i,k,j> &result,
+			       const Number<1> &ND0,
+			       const Number<1> &ND1,
+			       const Number<2> &ND2)
+{
+  iter.unsafe(0,0,1)=-result(0,0,1);
+}
+
+template<class A, class T, int Dim0, int Dim12, char i, char j, char k>
+template<class B, class U> inline
+const Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+  T,Dim0,Dim12,i,j,k> &
+Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<A,Dim0,Dim12>,
+  T,Dim0,Dim12,i,j,k>::
+operator=(const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,k,j> &result)
+{
+  T3as_switched_equals_T3as(iter,result,Number<Dim0>(),Number<Dim12-1>(),
+			    Number<Dim12>());
+  return *this;
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_constructor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_constructor.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,79 @@
+/* A helper class that allows simple initialization of the
+   Tensor3_antisymmetric, but only if it has the correct number of
+   elements. */
+
+template<class T, int Tensor_Dim0, int Tensor_Dim12>
+class Tensor3_antisymmetric_constructor;
+
+template<class T>
+class Tensor3_antisymmetric_constructor<T,2,2>
+{
+public:
+  Tensor3_antisymmetric_constructor(T data[2][1], T d001, T d101)
+  {
+    data[0][0]=d001;
+    data[1][0]=d101;
+  }
+};
+
+template<class T>
+class Tensor3_antisymmetric_constructor<T,3,3>
+{
+public:
+  Tensor3_antisymmetric_constructor(T data[3][3], T d001, T d002, T d012,
+				    T d101, T d102, T d112,
+				    T d201, T d202, T d212)
+  {
+    data[0][0]=d001;
+    data[1][0]=d101;
+    data[2][0]=d201;
+
+    data[0][1]=d002;
+    data[1][1]=d102;
+    data[2][1]=d202;
+
+    data[0][2]=d012;
+    data[1][2]=d112;
+    data[2][2]=d212;
+  }
+};
+
+template<class T>
+class Tensor3_antisymmetric_constructor<T,4,4>
+{
+public:
+  Tensor3_antisymmetric_constructor
+  (T data[10][4], T d001, T d002, T d003, T d012, T d013, T d023,
+   T d101, T d102, T d103, T d112, T d113, T d123,
+   T d201, T d202, T d203, T d212, T d213, T d223)
+  {
+    data[0][0]=d001;
+    data[0][1]=d002;
+    data[0][2]=d003;
+    data[0][3]=d012;
+    data[0][4]=d013;
+    data[0][5]=d023;
+
+    data[1][0]=d001;
+    data[1][1]=d002;
+    data[1][2]=d003;
+    data[1][3]=d012;
+    data[1][4]=d013;
+    data[1][5]=d023;
+
+    data[2][0]=d001;
+    data[2][1]=d002;
+    data[2][2]=d003;
+    data[2][3]=d012;
+    data[2][4]=d013;
+    data[2][5]=d023;
+
+    data[3][0]=d001;
+    data[3][1]=d002;
+    data[3][2]=d003;
+    data[3][3]=d012;
+    data[3][4]=d013;
+    data[3][5]=d023;
+  }
+};
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_mod_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_mod_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,52 @@
+/* Multiplies a Tensor3_antisymmetric and a Tensor1, yielding a
+   Tensor4_Riemann. */
+
+/* A(j,k,l)*B(i) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor3_antisymmetric_mod_Tensor1
+{
+  const Tensor3_antisymmetric_Expr<A,T,Dim,Dim,j,k,l> iterA;
+  const Tensor1_Expr<B,U,Dim,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N2,N3,N4)*iterB(N1);
+  }
+
+  Tensor3_antisymmetric_mod_Tensor1
+  (const Tensor3_antisymmetric_Expr<A,T,Dim,Dim,j,k,l> &a,
+   const Tensor1_Expr<B,U,Dim,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_Riemann_Expr
+<const Tensor3_antisymmetric_mod_Tensor1<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,j,k,l>
+operator%(const Tensor3_antisymmetric_Expr<A,T,Dim,Dim,j,k,l> &a,
+	  const Tensor1_Expr<B,U,Dim,i> &b)
+{
+  typedef const Tensor3_antisymmetric_mod_Tensor1<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Riemann_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(i)*A(j,k,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_Riemann_Expr
+<const Tensor3_antisymmetric_mod_Tensor1<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,j,k,l>
+operator%(const Tensor1_Expr<B,U,Dim,i> &b,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim,Dim,j,k,l> &a)
+{
+  typedef const Tensor3_antisymmetric_mod_Tensor1<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Riemann_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_or_Tensor3_antisymmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_or_Tensor3_antisymmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* Adds two Tensor3_antisymmetrics together to make a Tensor3_dg. */
+
+/* A(i,j,k) + B(k,j,i) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor3_antisymmetric_or_Tensor3_antisymmetric
+{
+  const Tensor3_antisymmetric_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor3_antisymmetric_Expr<B,U,Dim,Dim,k,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N3,N2)+iterB(N2,N3,N1);
+  }
+
+  Tensor3_antisymmetric_or_Tensor3_antisymmetric
+  (const Tensor3_antisymmetric_Expr<A,T,Dim,Dim,i,j,k> &a,
+   const Tensor3_antisymmetric_Expr<B,U,Dim,Dim,k,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_antisymmetric_or_Tensor3_antisymmetric
+<A,B,T,U,Dim,i,j,k>,typename promote<T,U>::V,Dim,Dim,i,k,j>
+operator||(const Tensor3_antisymmetric_Expr<A,T,Dim,Dim,i,j,k> &a,
+	   const Tensor3_antisymmetric_Expr<B,U,Dim,Dim,k,j,i> &b)
+{
+  typedef const Tensor3_antisymmetric_or_Tensor3_antisymmetric
+    <A,B,T,U,Dim,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k,j>
+    (TensorExpr(a,b));
+}
+
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_plus_Tensor3_antisymmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_plus_Tensor3_antisymmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,70 @@
+/* Adds two Tensor3_antisymmetric's together, yielding a
+   Tensor3_antisymmetric. */
+
+/* A(i,j,k) + B(i,j,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+class Tensor3_antisymmetric_plus_Tensor3_antisymmetric
+{
+  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> iterA;
+  const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N1,N2,N3);
+  }
+
+  Tensor3_antisymmetric_plus_Tensor3_antisymmetric
+  (const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+   const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor3_antisymmetric_plus_Tensor3_antisymmetric
+<A,B,T,U,Dim0,Dim12,i,j,k>,typename promote<T,U>::V,Dim0,Dim12,i,j,k>
+operator+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,j,k> &b)
+{
+  typedef const Tensor3_antisymmetric_plus_Tensor3_antisymmetric
+    <A,B,T,U,Dim0,Dim12,i,j,k> TensorExpr;
+  return Tensor3_antisymmetric_Expr
+    <TensorExpr,typename promote<T,U>::V,Dim0,Dim12,i,j,k>(TensorExpr(a,b));
+}
+
+/* A(i,j,k) + B(i,k,j) (which simplifies to A(i,j,k) - B(i,j,k)) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+class Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12
+{
+  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> iterA;
+  const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N1,N2,N3);
+  }
+
+  Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12
+  (const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+   const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,k,j> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12
+<A,B,T,U,Dim0,Dim12,i,j,k>,typename promote<T,U>::V,Dim0,Dim12,i,j,k>
+operator+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_antisymmetric_Expr<B,U,Dim0,Dim12,i,k,j> &b)
+{
+  typedef const Tensor3_antisymmetric_plus_Tensor3_antisymmetric_12
+    <A,B,T,U,Dim0,Dim12,i,j,k> TensorExpr;
+  return Tensor3_antisymmetric_Expr
+    <TensorExpr,typename promote<T,U>::V,Dim0,Dim12,i,j,k>(TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_pointer.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,125 @@
+/* A version for pointers. */
+
+template <class T, int Tensor_Dim0, int Tensor_Dim12>
+class Tensor3_antisymmetric<T*,Tensor_Dim0,Tensor_Dim12>
+{
+  mutable T * restrict data[Tensor_Dim0][(Tensor_Dim12*(Tensor_Dim12-1))/2];
+public:
+  Tensor3_antisymmetric() {}
+
+  /* Tensor_Dim0=2, Tensor_Dim12=2 */
+  Tensor3_antisymmetric(T* d001, T* d101)
+  {
+    Tensor3_antisymmetric_constructor<T* restrict,2,2>(data,d001,d101);
+  }
+
+  /* Tensor_Dim0=3, Tensor_Dim12=3 */
+  Tensor3_antisymmetric(T* d001, T* d002, T* d012, T* d101, T* d102, T* d112,
+			T* d201, T* d202, T* d212)
+  {
+    Tensor3_antisymmetric_constructor<T* restrict,3,3>
+      (data,d001,d002,d012,d101,d102,d112,d201,d202,d212);
+  }
+
+  /* Tensor_Dim0=4, Tensor_Dim12=4 */
+  Tensor3_antisymmetric(T* d001, T* d002, T* d003, T* d012, T* d013, T* d023,
+			T* d101, T* d102, T* d103, T* d112, T* d113, T* d123,
+			T* d201, T* d202, T* d203, T* d212, T* d213, T* d223)
+  {
+    Tensor3_antisymmetric_constructor<T* restrict,4,4>
+      (data,d001,d002,d003,d012,d013,d023,d101,d102,d103,d112,d113,d123,
+       d201,d202,d203,d212,d213,d223);
+  }
+
+  /* There are two ways of accessing the values inside,
+     unsafe(int,int,int) and operator(int,int,int).
+     unsafe(int,int,int) will give you a wrong answer if you aren't
+     careful.  The problem is that we only store the minimal set of
+     components, but some have different signs.  We can't return the
+     negative of a component, and assign something to it, because that
+     would assign something to a temporary.  To get the correct answer
+     if you don't want to change the value, just use
+     operator(int,int,int). */
+
+  T & unsafe(const int N1, const int N2, const int N3)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0
+       || N2>=N3)
+      {
+	std::cerr << "Bad index in Tensor3_antisymmetric<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.unsafe("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return *data[N1][N3-1+(N2*(2*(Tensor_Dim12-1)-N2-1))/2];
+  }
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_antisymmetric<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return N2<N3 ? *data[N1][N3-1+(N2*(2*(Tensor_Dim12-1)-N2-1))/2]
+      : (N2>N3 ? -*data[N1][N2-1+(N3*(2*(Tensor_Dim12-1)-N3-1))/2] : 0.0);
+  }
+
+  T* ptr(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_antisymmetric<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.ptr("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N2<N3 ? data[N1][N3-1+(N2*(2*(Tensor_Dim12-1)-N2-1))/2]
+      : (N2>N3 ? -data[N1][N2-1+(N3*(2*(Tensor_Dim12-1)-N3-1))/2] : 0);
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions. */
+  
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<T*,Tensor_Dim0,Tensor_Dim12>,
+    T,Dim0,Dim12,i,j,k>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<k,Dim12> index3)
+  {
+    return Tensor3_antisymmetric_Expr<Tensor3_antisymmetric
+      <T*,Tensor_Dim0,Tensor_Dim12>,T,Dim0,Dim12,i,j,k>(*this);
+  }
+
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_antisymmetric_Expr<const Tensor3_antisymmetric
+  <T*,Tensor_Dim0,Tensor_Dim12>,T,Dim0,Dim12,i,j,k>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<k,Dim12> index3) const
+  {
+    return Tensor3_antisymmetric_Expr<const Tensor3_antisymmetric
+      <T*,Tensor_Dim0,Tensor_Dim12>,T,Dim0,Dim12,i,j,k>(*this);
+  }
+
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+
+  const Tensor3_antisymmetric<T*,Tensor_Dim0,Tensor_Dim12> & operator++() const
+  {
+    for(int i=0;i<Tensor_Dim0;++i)
+      for(int j=0;j<(Tensor_Dim12*(Tensor_Dim12-1))/2;++j)
+	++data[i][j];
+    return *this;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_times_Tensor3.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_times_Tensor3.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,507 @@
+/* Fully contracts a Tensor3_antisymmetric with a Tensor3, yielding a
+   typename promote<T,U>::V.  I removed the identically zero components of
+   Tensor3_antisymmetric.*/
+
+/* A(i,j,k)*B(i,j,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)
+    + T3as_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim0-1,0,Current_Dim2-1)
+    + T3as_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Dim12>(),Number<Current_Dim2-1>());
+}
+
+/* A special case for when the last two indices are equal. */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim2> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return T3as_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim2-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,j,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,1,0)*b(Current_Dim0-1,1,0)
+    + T3as_times_T3_012(a,b,Number<Current_Dim0-1>(),
+			Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,j,k> &b,
+ const Number<1> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(0,1,0)*b(0,1,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,j,k> &b)
+{
+  return T3as_times_T3_012(a,b,Number<Dim0>(),Number<Dim12-1>(),
+			   Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,j,k> &b,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a)
+{
+  return a*b;
+}
+
+/* A(i,j,k)*B(k,i,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_201
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim2-1,Current_Dim0-1,Current_Dim1-1)
+    + T3as_times_T3_201(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_201
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim2-1,Current_Dim0-1,0)
+    + T3as_times_T3_201(a,b,Number<Current_Dim0>(),
+			Number<Dim12>(),Number<Current_Dim2-1>());
+}
+
+/* A special case for when the last two indices are equal. */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_201
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim2> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return T3as_times_T3_201(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim2-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3as_times_T3_201
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,i,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,1,0)*b(0,Current_Dim0-1,1)
+    + T3as_times_T3_201(a,b,Number<Current_Dim0-1>(),
+			Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3as_times_T3_201
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,i,j> &b,
+ const Number<1> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(0,1,0)*b(0,0,1);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,i,j> &b)
+{
+  return T3as_times_T3_201(a,b,Number<Dim0>(),Number<Dim12-1>(),
+			   Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<B,U,Dim12,Dim0,Dim12,k,i,j> &b,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a)
+{
+  return a*b;
+}
+
+/* A(i,j,k)*B(j,k,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_120
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim1-1,Current_Dim2-1,Current_Dim0-1)
+    + T3as_times_T3_120(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_120
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(0,Current_Dim2-1,Current_Dim0-1)
+    + T3as_times_T3_120(a,b,Number<Current_Dim0>(),
+			Number<Dim12>(),Number<Current_Dim2-1>());
+}
+
+/* A special case for when the last two indices are equal. */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_120
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim2> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return T3as_times_T3_120(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim2-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3as_times_T3_120
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,k,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,1,0)*b(1,0,Current_Dim0-1)
+    + T3as_times_T3_120(a,b,Number<Current_Dim0-1>(),
+			Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3as_times_T3_120
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,k,i> &b,
+ const Number<1> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(0,1,0)*b(1,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,k,i> &b)
+{
+  return T3as_times_T3_120(a,b,Number<Dim0>(),Number<Dim12-1>(),
+			   Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<B,U,Dim12,Dim12,Dim0,j,k,i> &b,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a)
+{
+  return a*b;
+}
+
+/* A(i,j,k)*B(j,i,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_102
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim1-1,Current_Dim0-1,Current_Dim2-1)
+    + T3as_times_T3_102(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_102
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(0,Current_Dim0-1,Current_Dim2-1)
+    + T3as_times_T3_102(a,b,Number<Current_Dim0>(),
+			Number<Dim12>(),Number<Current_Dim2-1>());
+}
+
+/* A special case for when the last two indices are equal. */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_102
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim2> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return T3as_times_T3_102(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim2-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3as_times_T3_102
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,i,k> &b,
+ const Number<Current_Dim0> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,1,0)*b(1,Current_Dim0-1,0)
+    + T3as_times_T3_102(a,b,Number<Current_Dim0-1>(),
+			Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3as_times_T3_102
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,i,k> &b,
+ const Number<1> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(0,1,0)*b(1,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,j,i,k> &b)
+{
+  return T3as_times_T3_102(a,b,Number<Dim0>(),Number<Dim12-1>(),
+			   Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<B,U,Dim12,Dim0,Dim12,j,i,k> &b,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a)
+{
+  return a*b;
+}
+
+/* A(i,j,k)*B(k,j,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_210
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim2-1,Current_Dim1-1,Current_Dim0-1)
+    + T3as_times_T3_210(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_210
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim2-1,0,Current_Dim0-1)
+    + T3as_times_T3_210(a,b,Number<Current_Dim0>(),
+			Number<Dim12>(),Number<Current_Dim2-1>());
+}
+
+/* A special case for when the last two indices are equal. */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_210
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim2> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return T3as_times_T3_210(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim2-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3as_times_T3_210
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,j,i> &b,
+ const Number<Current_Dim0> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,1,0)*b(0,1,Current_Dim0-1)
+    + T3as_times_T3_210(a,b,Number<Current_Dim0-1>(),
+			Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3as_times_T3_210
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,j,i> &b,
+ const Number<1> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(0,1,0)*b(0,1,0);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,k,j,i> &b)
+{
+  return T3as_times_T3_210(a,b,Number<Dim0>(),Number<Dim12-1>(),
+			   Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<B,U,Dim12,Dim12,Dim0,k,j,i> &b,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a)
+{
+  return a*b;
+}
+
+/* A(i,j,k)*B(i,k,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)*
+    b(Current_Dim0-1,Current_Dim2-1,Current_Dim1-1)
+    + T3as_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<1> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return a(Current_Dim0-1,0,Current_Dim2-1)*b(Current_Dim0-1,Current_Dim2-1,0)
+    + T3as_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Dim12>(),Number<Current_Dim2-1>());
+}
+
+/* A special case for when the last two indices are equal. */
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0, int Current_Dim2>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<Current_Dim2> &ND1,
+ const Number<Current_Dim2> &ND2)
+{
+  return T3as_times_T3_012(a,b,Number<Current_Dim0>(),
+			Number<Current_Dim2-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k, int Current_Dim0>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b,
+ const Number<Current_Dim0> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(Current_Dim0-1,1,0)*b(Current_Dim0-1,0,1)
+    + T3as_times_T3_012(a,b,Number<Current_Dim0-1>(),
+			Number<Dim12-1>(),Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V T3as_times_T3_012
+(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+ const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b,
+ const Number<1> &ND0, const Number<2> &ND1, const Number<1> &ND2)
+{
+  return a(0,1,0)*b(0,0,1);
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b)
+{
+  return T3as_times_T3_012(a,b,Number<Dim0>(),Number<Dim12-1>(),
+			   Number<Dim12>());
+}
+
+template<class A, class B, class T, class U, int Dim0, int Dim12,
+  char i, char j, char k>
+inline const typename promote<T,U>::V
+operator*(const Tensor3_Expr<B,U,Dim0,Dim12,Dim12,i,k,j> &b,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a)
+{
+  return a*b;
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_times_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_times_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,48 @@
+/* Multiplies a Tensor3_antisymmetric with a generic, yielding a
+   Tensor3_antisymmetric. */
+
+/* A(i,j,k)*generic */
+
+template<class A, class T, class U, int Dim0, int Dim12, char i, char j,char k>
+class Tensor3_antisymmetric_times_generic
+{
+  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)*d;
+  }
+
+  Tensor3_antisymmetric_times_generic
+  (const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a, const U &d0):
+    iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim0, int Dim12, char i, char j,char k>
+inline const Tensor3_antisymmetric_Expr<const Tensor3_antisymmetric_times_generic
+<A,T,U,Dim0,Dim12,i,j,k>,typename promote<T,U>::V,Dim0,Dim12,i,j,k>
+operator*(const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a,
+	  const U &d0)
+{
+  typedef const Tensor3_antisymmetric_times_generic<A,T,U,Dim0,Dim12,i,j,k>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr
+    <TensorExpr,typename promote<T,U>::V,Dim0,Dim12,i,j,k>(TensorExpr(a,d0));
+}
+
+/* generic*A(i,j,k) */
+
+template<class A, class T, class U, int Dim0, int Dim12, char i, char j,char k>
+inline const Tensor3_antisymmetric_Expr<const Tensor3_antisymmetric_times_generic
+<A,T,U,Dim0,Dim12,i,j,k>,typename promote<T,U>::V,Dim0,Dim12,i,j,k>
+operator*(const U &d0,
+	  const Tensor3_antisymmetric_Expr<A,T,Dim0,Dim12,i,j,k> &a)
+{
+  typedef const Tensor3_antisymmetric_times_generic<A,T,U,Dim0,Dim12,i,j,k>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr
+    <TensorExpr,typename promote<T,U>::V,Dim0,Dim12,i,j,k>(TensorExpr(a,d0));
+}
+
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_antisymmetric/Tensor3_antisymmetric_value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_antisymmetric/Tensor3_antisymmetric_value.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+/* A general version, not for pointers. */
+
+template <class T, int Tensor_Dim0, int Tensor_Dim12>
+class Tensor3_antisymmetric
+{
+  T data[Tensor_Dim0][(Tensor_Dim12*(Tensor_Dim12-1))/2];
+public:
+  Tensor3_antisymmetric() {}
+
+  /* Tensor_Dim0=2, Tensor_Dim12=2 */
+  Tensor3_antisymmetric(T d001, T d101)
+  {
+    Tensor3_antisymmetric_constructor<T,2,2>(data,d001,d101);
+  }
+
+  /* Tensor_Dim0=3, Tensor_Dim12=3 */
+  Tensor3_antisymmetric(T d001, T d002, T d012,	T d101, T d102, T d112,
+			T d201, T d202, T d212)
+  {
+    Tensor3_antisymmetric_constructor<T,3,3>
+      (data,d001,d002,d012,d101,d102,d112,d201,d202,d212);
+  }
+
+  /* Tensor_Dim0=4, Tensor_Dim12=4 */
+  Tensor3_antisymmetric(T d001, T d002, T d003, T d012, T d013, T d023,
+			T d101, T d102, T d103, T d112, T d113, T d123,
+			T d201, T d202, T d203, T d212, T d213, T d223)
+  {
+    Tensor3_antisymmetric_constructor<T,4,4>
+      (data,d001,d002,d003,d012,d013,d023,d101,d102,d103,d112,d113,d123,
+       d201,d202,d203,d212,d213,d223);
+  }
+
+  /* There are two ways of accessing the values inside,
+     unsafe(int,int,int) and operator(int,int,int).
+     unsafe(int,int,int) will give you a wrong answer if you aren't
+     careful.  The problem is that we only store the minimal set of
+     components, but some have different signs.  We can't return the
+     negative of a component, and assign something to it, because that
+     would assign something to a temporary.  To get the correct answer
+     if you don't want to change the value, just use
+     operator(int,int,int). */
+
+  T & unsafe(const int N1, const int N2, const int N3)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0
+       || N2>=N3)
+      {
+	std::cerr << "Bad index in Tensor3_antisymmetric<T,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return data[N1][N3-1+(N2*(2*(Tensor_Dim12-1)-N2-1))/2];
+  }
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_antisymmetric<T,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return N2<N3 ? data[N1][N3-1+(N2*(2*(Tensor_Dim12-1)-N2-1))/2]
+      : (N2>N3 ? -data[N1][N2-1+(N3*(2*(Tensor_Dim12-1)-N3-1))/2] : 0.0);
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions. */
+  
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_antisymmetric_Expr<Tensor3_antisymmetric<T,Tensor_Dim0,Tensor_Dim12>,
+    T,Dim0,Dim12,i,j,k>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<k,Dim12> index3)
+  {
+    return Tensor3_antisymmetric_Expr<Tensor3_antisymmetric
+      <T,Tensor_Dim0,Tensor_Dim12>,T,Dim0,Dim12,i,j,k>(*this);
+  }
+
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_antisymmetric_Expr<const Tensor3_antisymmetric
+  <T,Tensor_Dim0,Tensor_Dim12>,T,Dim0,Dim12,i,j,k>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<k,Dim12> index3) const
+  {
+    return Tensor3_antisymmetric_Expr<const Tensor3_antisymmetric
+      <T,Tensor_Dim0,Tensor_Dim12>,T,Dim0,Dim12,i,j,k>(*this);
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_christof.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_christof.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,9 @@
+/* Declarations for a Tensor3_christof.  This is symmetric on the last
+   two indices. */
+
+#include "Tensor3_christof/Tensor3_christof_number.h"
+#include "Tensor3_christof/Tensor3_christof_numeral.h"
+
+#include "Tensor3_christof/Tensor3_christof_constructor.h"
+#include "Tensor3_christof/Tensor3_christof_value.h"
+#include "Tensor3_christof/Tensor3_christof_pointer.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor3_christof/Tensor3_christof_constructor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_christof/Tensor3_christof_constructor.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,164 @@
+/* A helper class that allows simple initialization of the Tensor3_christof,
+   but only if it has the correct number of elements. */
+
+template<class T, int Tensor_Dim0, int Tensor_Dim12>
+class Tensor3_christof_constructor;
+
+template<class T>
+class Tensor3_christof_constructor<T,2,2>
+{
+public:
+  Tensor3_christof_constructor(T data[2][3], T d000, T d100, T d001, T d101,
+			       T d011, T d111)
+  {
+    data[0][0]=d000;
+    data[1][0]=d100;
+    data[0][1]=d001;
+    data[1][1]=d101;
+    data[0][2]=d011;
+    data[1][2]=d111;
+  }
+};
+
+template<class T>
+class Tensor3_christof_constructor<T,3,3>
+{
+public:
+  Tensor3_christof_constructor(T data[3][6], T d000, T d100, T d200, T d001, T d101,
+			 T d201, T d002, T d102, T d202, T d011, T d111,
+			 T d211, T d012, T d112, T d212, T d022, T d122,
+			 T d222)
+  {
+    data[0][0]=d000;
+    data[0][1]=d001;
+    data[0][2]=d002;
+    data[0][3]=d011;
+    data[0][4]=d012;
+    data[0][5]=d022;
+
+    data[1][0]=d100;
+    data[1][1]=d101;
+    data[1][2]=d102;
+    data[1][3]=d111;
+    data[1][4]=d112;
+    data[1][5]=d122;
+
+    data[2][0]=d200;
+    data[2][1]=d201;
+    data[2][2]=d202;
+    data[2][3]=d211;
+    data[2][4]=d212;
+    data[2][5]=d222;
+  }
+};
+
+template<class T>
+class Tensor3_christof_constructor<T,4,4>
+{
+public:
+  Tensor3_christof_constructor(T data[4][10], T d000, T d100, T d200, T d300,
+			 T d001, T d101, T d201, T d301,
+			 T d002, T d102, T d202, T d302,
+			 T d003, T d103, T d203, T d303,
+			 T d011, T d111, T d211, T d311,
+			 T d012, T d112, T d212, T d312,
+			 T d013, T d113, T d213, T d313,
+			 T d022, T d122, T d222, T d322,
+			 T d023, T d123, T d223, T d323,
+			 T d033, T d133, T d233, T d333)
+  {
+    data[0][0]=d000;
+    data[0][1]=d001;
+    data[0][2]=d002;
+    data[0][3]=d003;
+    data[0][4]=d011;
+    data[0][5]=d012;
+    data[0][6]=d013;
+    data[0][7]=d022;
+    data[0][8]=d023;
+    data[0][9]=d033;
+
+    data[1][0]=d100;
+    data[1][1]=d101;
+    data[1][2]=d102;
+    data[1][3]=d103;
+    data[1][4]=d111;
+    data[1][5]=d112;
+    data[1][6]=d113;
+    data[1][7]=d122;
+    data[1][8]=d123;
+    data[1][9]=d133;
+
+    data[2][0]=d200;
+    data[2][1]=d201;
+    data[2][2]=d202;
+    data[2][3]=d203;
+    data[2][4]=d211;
+    data[2][5]=d212;
+    data[2][6]=d213;
+    data[2][7]=d222;
+    data[2][8]=d223;
+    data[2][9]=d233;
+
+    data[3][0]=d300;
+    data[3][1]=d301;
+    data[3][2]=d302;
+    data[3][3]=d303;
+    data[3][4]=d311;
+    data[3][5]=d312;
+    data[3][6]=d313;
+    data[3][7]=d322;
+    data[3][8]=d323;
+    data[3][9]=d333;
+  }
+};
+
+template<class T>
+class Tensor3_christof_constructor<T,3,4>
+{
+public:
+  Tensor3_christof_constructor(T data[3][10], T d000, T d100, T d200,
+			 T d001, T d101, T d201,
+			 T d002, T d102, T d202,
+			 T d003, T d103, T d203,
+			 T d011, T d111, T d211,
+			 T d012, T d112, T d212,
+			 T d013, T d113, T d213,
+			 T d022, T d122, T d222,
+			 T d023, T d123, T d223,
+			 T d033, T d133, T d233)
+  {
+    data[0][0]=d000;
+    data[0][1]=d001;
+    data[0][2]=d002;
+    data[0][3]=d003;
+    data[0][4]=d011;
+    data[0][5]=d012;
+    data[0][6]=d013;
+    data[0][7]=d022;
+    data[0][8]=d023;
+    data[0][9]=d033;
+
+    data[1][0]=d100;
+    data[1][1]=d101;
+    data[1][2]=d102;
+    data[1][3]=d103;
+    data[1][4]=d111;
+    data[1][5]=d112;
+    data[1][6]=d113;
+    data[1][7]=d122;
+    data[1][8]=d123;
+    data[1][9]=d133;
+
+    data[2][0]=d200;
+    data[2][1]=d201;
+    data[2][2]=d202;
+    data[2][3]=d203;
+    data[2][4]=d211;
+    data[2][5]=d212;
+    data[2][6]=d213;
+    data[2][7]=d222;
+    data[2][8]=d223;
+    data[2][9]=d233;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_christof/Tensor3_christof_number.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_christof/Tensor3_christof_number.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,15 @@
+/* This is for expressions where a number is used for one slot, and
+   an index for the other, yielding a Tensor2_symmetric_Expr. */
+
+template<class A, class T, int N>
+class Tensor3_christof_number_0
+{
+  const A iterA;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N,N1,N2);
+  }
+  Tensor3_christof_number_0(const A &a): iterA(a) {}
+};
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_christof/Tensor3_christof_numeral.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_christof/Tensor3_christof_numeral.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,33 @@
+/* This is for expressions where an int is used for one slot, and an
+   Index for the others, yielding a Tensor2_symmetric_Expr or
+   Tensor2_Expr. */
+
+template<class A, class T>
+class Tensor3_christof_numeral_0
+{
+  const A iterA;
+  const int N;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N,N1,N2);
+  }
+  Tensor3_christof_numeral_0(const A &a, const int NN): iterA(a), N(NN) {}
+};
+
+/* We can use this version for when there is an int in either of the
+   last slots, because Tensor3_christof is symmetric. */
+
+template<class A, class T>
+class Tensor3_christof_numeral_1
+{
+  const A iterA;
+  const int N;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N,N2);
+  }
+  Tensor3_christof_numeral_1(const A &a, const int NN): iterA(a), N(NN) {}
+};
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_christof/Tensor3_christof_pointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_christof/Tensor3_christof_pointer.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,251 @@
+/* A version for pointers */
+
+template <class T, int Tensor_Dim0, int Tensor_Dim12>
+class Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>
+{
+  mutable T * restrict  data[Tensor_Dim0][(Tensor_Dim12*(Tensor_Dim12+1))/2];
+public:
+  Tensor3_christof() {}
+
+  /* Tensor_Dim0=Tensor_Dim12=2 */
+  Tensor3_christof(T *d000, T *d100, T *d001, T *d101, T *d011, T *d111)
+  {
+    Tensor3_christof_constructor<T* restrict,Tensor_Dim0,Tensor_Dim12>
+      (data,d000,d100,d001,d101,d011,d111);
+  }
+
+  /* Tensor_Dim0=Tensor_Dim12=3 */
+  Tensor3_christof(T *d000, T *d100, T *d200, T *d001, T *d101, T *d201,
+		   T *d002, T *d102, T *d202, T *d011, T *d111, T *d211,
+		   T *d012, T *d112, T *d212, T *d022, T *d122, T *d222)
+  {
+    Tensor3_christof_constructor<T* restrict,Tensor_Dim0,Tensor_Dim12>
+      (data,d000,d100,d200,d001,d101,d201,d002,d102,d202,d011,d111,d211,
+       d012,d112,d212,d022,d122,d222);
+  }
+
+  /* Tensor_Dim0=Tensor_Dim12=4 */
+  Tensor3_christof(T *d000, T *d100, T *d200, T *d300,
+		   T *d001, T *d101, T *d201, T *d301,
+		   T *d002, T *d102, T *d202, T *d302,
+		   T *d003, T *d103, T *d203, T *d303,
+		   T *d011, T *d111, T *d211, T *d311,
+		   T *d012, T *d112, T *d212, T *d312,
+		   T *d013, T *d113, T *d213, T *d313,
+		   T *d022, T *d122, T *d222, T *d322,
+		   T *d023, T *d123, T *d223, T *d323,
+		   T *d033, T *d133, T *d233, T *d333)
+  {
+    Tensor3_christof_constructor<T* restrict,Tensor_Dim0,Tensor_Dim12>
+      (data,d000,d100,d200,d300,d001,d101,d201,d301,
+       d002,d102,d202,d302,d003,d103,d203,d303,
+       d011,d111,d211,d311,d012,d112,d212,d312,
+       d013,d113,d213,d313,d022,d122,d222,d322,
+       d023,d123,d223,d323,d033,d133,d233,d333);
+  }
+
+  /* There are two operator(int,int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2, const int N3)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_christof<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N2>N3 ? *data[N1][N2+(N3*(2*Tensor_Dim12-N3-1))/2]
+      : *data[N1][N3+(N2*(2*Tensor_Dim12-N2-1))/2];
+  }
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_christof<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return N2>N3 ? *data[N1][N2+(N3*(2*Tensor_Dim12-N3-1))/2]
+      : *data[N1][N3+(N2*(2*Tensor_Dim12-N2-1))/2];
+  }
+
+  T* ptr(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_christof<T*,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.ptr("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N2>N3 ? data[N1][N2+(N3*(2*Tensor_Dim12-N3-1))/2]
+      : data[N1][N3+(N2*(2*Tensor_Dim12-N2-1))/2];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  I mix up the indices here so that it behaves like a
+     Tensor3_dg.  That way I don't have to have a separate wrapper
+     class Tensor3_christof_Expr, which simplifies things. */
+
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_dg_Expr<Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,
+    T,Dim12,Dim0,i,j,k> operator()
+    (const Index<k,Dim0> index1, const Index<i,Dim12> index2,
+     const Index<j,Dim12> index3)
+  {
+    return Tensor3_dg_Expr<Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,
+      T,Dim12,Dim0,i,j,k>(*this);
+  }
+
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_dg_Expr<const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,
+    T,Dim12,Dim0,i,j,k>
+  operator()(const Index<k,Dim0> index1, const Index<i,Dim12> index2,
+	     const Index<j,Dim12> index3) const
+  {
+    return Tensor3_dg_Expr<const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,
+      T,Dim12,Dim0,i,j,k>(*this);
+  }
+
+  /* These operators are for internal contractions. */
+
+  /* const versions */
+
+  template<char i, char j, int Dim0, int Dim12>
+  inline Tensor1_Expr<const Tensor3_contracted_12
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim12>,T,Dim0,i>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<j,Dim12> index3) const
+  {
+    typedef const Tensor3_contracted_12
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim12>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim0,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim02, int Dim1>
+  inline Tensor1_Expr<const Tensor3_contracted_02
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim02>,T,Dim1,i>
+  operator()(const Index<j,Dim02> index1, const Index<i,Dim1> index2,
+	     const Index<j,Dim02> index3) const
+  {
+    typedef const Tensor3_contracted_02
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim02>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim1,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim01, int Dim2>
+  inline Tensor1_Expr<const Tensor3_contracted_01
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim01>,T,Dim2,i>
+  operator()(const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+	     const Index<i,Dim2> index3) const
+  {
+    typedef const Tensor3_contracted_01
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim01>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim2,i>(TensorExpr(*this));
+  }
+
+  /* non-const versions */
+
+  template<char i, char j, int Dim0, int Dim12>
+  inline Tensor1_Expr<const Tensor3_contracted_12
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim12>,T,Dim0,i>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<j,Dim12> index3)
+  {
+    typedef const Tensor3_contracted_12
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim12>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim0,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim02, int Dim1>
+  inline Tensor1_Expr<const Tensor3_contracted_02
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim02>,T,Dim1,i>
+  operator()(const Index<j,Dim02> index1, const Index<i,Dim1> index2,
+	     const Index<j,Dim02> index3)
+  {
+    typedef const Tensor3_contracted_02
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim02>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim1,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim01, int Dim2>
+  inline Tensor1_Expr<const Tensor3_contracted_01
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim01>,T,Dim2,i>
+  operator()(const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+	     const Index<i,Dim2> index3)
+  {
+    typedef const Tensor3_contracted_01
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,Dim01>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim2,i>(TensorExpr(*this));
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     an index for the others, yielding a Tensor2_symmetric_Expr. */
+
+  template<char i, char j, int N, int Dim12>
+  Tensor2_symmetric_Expr<const Tensor3_christof_number_0
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,N>,T,Dim12,i,j>
+  operator()(const Number<N> n1, const Index<i,Dim12> index1,
+	     const Index<j,Dim12> index2) const
+  {
+    typedef const Tensor3_christof_number_0
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T,N> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim12,i,j>(TensorExpr(*this));
+  }
+  
+  /* An int in one spot, Index for the others, yielding a Tensor2.  I
+     can use the same structure for both, since Tensor3_christof is
+     symmetric on the last two indices. */
+
+  template<char i, char j, int Dim0, int Dim2>
+  Tensor2_Expr<const Tensor3_christof_numeral_1
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const int N,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_christof_numeral_1
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this,N));
+  }
+
+  template<char i, char j, int Dim0, int Dim2>
+  Tensor2_Expr<const Tensor3_christof_numeral_1
+  <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim2> index2,
+	     const int N) const
+  {
+    typedef const Tensor3_christof_numeral_1
+      <const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this,N));
+  }
+  
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+
+  const Tensor3_christof<T*,Tensor_Dim0,Tensor_Dim12> & operator++() const
+  {
+    for(int i=0;i<Tensor_Dim0;++i)
+      for(int j=0;j<(Tensor_Dim12*(Tensor_Dim12+1))/2;++j)
+	++data[i][j];
+    return *this;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_christof/Tensor3_christof_value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_christof/Tensor3_christof_value.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,286 @@
+/* A general version, not for pointers */
+
+template <class T, int Tensor_Dim0, int Tensor_Dim12>
+class Tensor3_christof
+{
+  T data[Tensor_Dim0][(Tensor_Dim12*(Tensor_Dim12+1))/2];
+public:
+  Tensor3_christof() {}
+
+  /* Tensor_Dim0=Tensor_Dim12=2 */
+  Tensor3_christof(T d000, T d100, T d001, T d101, T d011, T d111)
+  {
+    Tensor3_christof_constructor<T,Tensor_Dim0,Tensor_Dim12>
+      (data,d000,d100,d001,d101,d011,d111);
+  }
+
+  /* Tensor_Dim0=Tensor_Dim12=3 */
+  Tensor3_christof(T d000, T d100, T d200, T d001, T d101, T d201,
+		   T d002, T d102, T d202, T d011, T d111, T d211,
+		   T d012, T d112, T d212, T d022, T d122, T d222)
+  {
+    Tensor3_christof_constructor<T,Tensor_Dim0,Tensor_Dim12>
+      (data,d000,d100,d200,d001,d101,d201,d002,d102,d202,d011,d111,d211,
+       d012,d112,d212,d022,d122,d222);
+  }
+
+  /* Tensor_Dim0=Tensor_Dim12=4 */
+  Tensor3_christof(T d000, T d100, T d200, T d300,
+		   T d001, T d101, T d201, T d301,
+		   T d002, T d102, T d202, T d302,
+		   T d003, T d103, T d203, T d303,
+		   T d011, T d111, T d211, T d311,
+		   T d012, T d112, T d212, T d312,
+		   T d013, T d113, T d213, T d313,
+		   T d022, T d122, T d222, T d322,
+		   T d023, T d123, T d223, T d323,
+		   T d033, T d133, T d233, T d333)
+  {
+    Tensor3_christof_constructor<T,Tensor_Dim0,Tensor_Dim12>
+      (data,d000,d100,d200,d300,d001,d101,d201,d301,
+       d002,d102,d202,d302,d003,d103,d203,d303,
+       d011,d111,d211,d311,d012,d112,d212,d312,
+       d013,d113,d213,d313,d022,d122,d222,d322,
+       d023,d123,d223,d323,d033,d133,d233,d333);
+  }
+
+  /* There are two operator(int,int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2, const int N3)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_christof<T,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N2>N3 ? data[N1][N2+(N3*(2*Tensor_Dim12-N3-1))/2]
+      : data[N1][N3+(N2*(2*Tensor_Dim12-N2-1))/2];
+  }
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim0 || N1<0
+       || N2>=Tensor_Dim12 || N2<0 || N3>=Tensor_Dim12 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_christof<T,"
+		  << Tensor_Dim0 << "," << Tensor_Dim12 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return N2>N3 ? data[N1][N2+(N3*(2*Tensor_Dim12-N3-1))/2]
+      : data[N1][N3+(N2*(2*Tensor_Dim12-N2-1))/2];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  I mix up the indices here so that it behaves like a
+     Tensor3_dg.  That way I don't have to have a separate wrapper
+     class Tensor3_christof_Expr, which simplifies things. */
+
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_dg_Expr<Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k> operator()
+    (const Index<k,Dim0> index1, const Index<i,Dim12> index2,
+     const Index<j,Dim12> index3)
+  {
+    return Tensor3_dg_Expr<Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k>(*this);
+  }
+
+  template<char i, char j, char k, int Dim0, int Dim12>
+  Tensor3_dg_Expr<const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k>
+  operator()(const Index<k,Dim0> index1, const Index<i,Dim12> index2,
+	     const Index<j,Dim12> index3) const
+  {
+    return Tensor3_dg_Expr<const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,
+      T,Dim12,Dim0,i,j,k>(*this);
+  }
+
+  /* These operators are for internal contractions.  Some of them are
+     less general, because, for example, A(j,i,j) with i and j having
+     different dimensions is ambiguous. */
+
+  /* const versions */
+
+  template<char i, char j, int Dim0, int Dim12>
+  inline Tensor1_Expr<const Tensor3_contracted_12
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim12>,T,Dim0,i>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<j,Dim12> index3) const
+  {
+    typedef const Tensor3_contracted_12
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim12>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim0,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_02
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>,T,Dim,i>
+  operator()(const Index<j,Dim> index1, const Index<i,Dim> index2,
+	     const Index<j,Dim> index3) const
+  {
+    typedef const Tensor3_contracted_02
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+//    template<char i, char j, int Dim02, int Dim1>
+//    inline Tensor1_Expr<const Tensor3_contracted_02
+//    <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim02>,T,Dim1,i>
+//    operator()(const Index<j,Dim02> index1, const Index<i,Dim1> index2,
+//  	     const Index<j,Dim02> index3) const
+//    {
+//      typedef const Tensor3_contracted_02
+//        <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim02>
+//        TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim1,i>(TensorExpr(*this));
+//    }
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_01
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>,T,Dim,i>
+  operator()(const Index<j,Dim> index1, const Index<j,Dim> index2,
+	     const Index<i,Dim> index3) const
+  {
+    typedef const Tensor3_contracted_01
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+//    template<char i, char j, int Dim01, int Dim2>
+//    inline Tensor1_Expr<const Tensor3_contracted_01
+//    <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim01>,T,Dim2,i>
+//    operator()(const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+//  	     const Index<i,Dim2> index3) const
+//    {
+//      typedef const Tensor3_contracted_01
+//        <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim01>
+//        TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim2,i>(TensorExpr(*this));
+//    }
+
+  /* non-const versions, needed so that overload resolution doesn't
+     pick the more general indexing operator. */
+
+  template<char i, char j, int Dim0, int Dim12>
+  inline Tensor1_Expr<const Tensor3_contracted_12
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim12>,T,Dim0,i>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+	     const Index<j,Dim12> index3)
+  {
+    typedef const Tensor3_contracted_12
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim12>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim0,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_02
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>,T,Dim,i>
+  operator()(const Index<j,Dim> index1, const Index<i,Dim> index2,
+	     const Index<j,Dim> index3)
+  {
+    typedef const Tensor3_contracted_02
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+//    template<char i, char j, int Dim02, int Dim1>
+//    inline Tensor1_Expr<const Tensor3_contracted_02
+//    <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim02>,T,Dim1,i>
+//    operator()(const Index<j,Dim02> index1, const Index<i,Dim1> index2,
+//  	     const Index<j,Dim02> index3)
+//    {
+//      typedef const Tensor3_contracted_02
+//        <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim02>
+//        TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim1,i>(TensorExpr(*this));
+//    }
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_01
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>,T,Dim,i>
+  operator()(const Index<j,Dim> index1, const Index<j,Dim> index2,
+	     const Index<i,Dim> index3)
+  {
+    typedef const Tensor3_contracted_01
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim>
+      TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+//    template<char i, char j, int Dim01, int Dim2>
+//    inline Tensor1_Expr<const Tensor3_contracted_01
+//    <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim01>,T,Dim2,i>
+//    operator()(const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+//  	     const Index<i,Dim2> index3)
+//    {
+//      typedef const Tensor3_contracted_01
+//        <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,Dim01>
+//        TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim2,i>(TensorExpr(*this));
+//    }
+
+  /* This is for expressions where a Number<> is used for one slot, and
+     an index for the others, yielding a Tensor2_symmetric_Expr. */
+
+  template<char i, char j, int N, int Dim12>
+  Tensor2_symmetric_Expr<const Tensor3_christof_number_0
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,N>,T,Dim12,i,j>
+  operator()(const Number<N> n1, const Index<i,Dim12> index1,
+	     const Index<j,Dim12> index2) const
+  {
+    typedef const Tensor3_christof_number_0
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T,N> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim12,i,j>(TensorExpr(*this));
+  }
+
+  /* This is for expressions where an int is used for one slot, and
+     an index for the others, yielding a Tensor2_symmetric_Expr. */
+
+  template<char i, char j, int Dim12>
+  Tensor2_symmetric_Expr<const Tensor3_christof_numeral_0
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T>,T,Dim12,i,j>
+  operator()(const int N, const Index<i,Dim12> index1,
+	     const Index<j,Dim12> index2) const
+  {
+    typedef const Tensor3_christof_numeral_0
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim12,i,j>(TensorExpr(*this,N));
+  }
+  
+  /* An int in one spot, Index for the others, yielding a Tensor2.  I
+     can use the same structure for both, since Tensor3_christof is
+     symmetric on the last two indices. */
+
+  template<char i, char j, int Dim0, int Dim2>
+  Tensor2_Expr<const Tensor3_christof_numeral_1
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const int N,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_christof_numeral_1
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this,N));
+  }
+
+  template<char i, char j, int Dim0, int Dim2>
+  Tensor2_Expr<const Tensor3_christof_numeral_1
+  <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const Index<j,Dim2> index2,
+	     const int N) const
+  {
+    typedef const Tensor3_christof_numeral_1
+      <const Tensor3_christof<T,Tensor_Dim0,Tensor_Dim12>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this,N));
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,11 @@
+/* Declarations for a Tensor3_dg.  This is symmetric on the first two
+   indices. */
+
+#include "Tensor3_dg/Tensor3_dg_number.h"
+#include "Tensor3_dg/Tensor3_dg_numeral.h"
+
+#include "Tensor3_dg/Tensor3_dg_constructor.h"
+#include "Tensor3_dg/Tensor3_dg_value.h"
+#include "Tensor3_dg/Tensor3_dg_pointer.h"
+
+#include "Tensor3_dg/Tensor3_dg_Expr.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,152 @@
+/* Declares a wrapper class for symmetric rank 3 Tensor expressions
+   that are symmetric on the first two indices.  It is also used for
+   Tensor3_christof's but with some games played with the
+   indices. */
+
+#include "Tensor3_dg_plus_Tensor3_dg.h"
+#include "Tensor3_dg_minus_Tensor3_dg.h"
+#include "Tensor3_dg_and_Tensor3_dg.h"
+#include "Tensor3_dg_or_Tensor3_dg.h"
+#include "Tensor3_dg_times_Tensor3_dg.h"
+#include "Tensor3_dg_times_Tensor2.h"
+#include "Tensor3_dg_times_Tensor2_symmetric.h"
+#include "Tensor3_dg_and_Tensor2_symmetric.h"
+#include "Tensor3_dg_times_Tensor1.h"
+#include "Tensor3_dg_and_Tensor1.h"
+#include "Tensor3_dg_times_generic.h"
+#include "Tensor3_dg_divide_generic.h"
+#include "minus_Tensor3_dg.h"
+
+template<class A, class T, int Dim01, int Dim2, char i, char j, char k>
+class Tensor3_dg_Expr
+{
+  A iter;
+public:
+  Tensor3_dg_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N1,N2,N3);
+  }
+};
+
+template<class A, class T, int Tensor_Dim01, int Tensor_Dim2,
+  int Dim01, int Dim2, char i, char j, char k>
+class Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k>
+{
+  Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2> &iter;
+public:
+  Tensor3_dg_Expr(Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2> &a): iter(a) {}
+  T & operator()(const int N1, const int N2, const int N3)
+  {
+    return iter(N1,N2,N3);
+  }
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N1,N2,N3);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U> inline
+  const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &
+  operator=(const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &result);
+
+  const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &
+  operator=(const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &result);
+
+  template <class U> inline
+  const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &
+  operator=(const U &d);
+};
+
+/* I need a version for const and non-const Tensor3_christof,
+   otherwise it will use the default and the index order will get all
+   messed up. The class A is either T or T*, depending on whether
+   Tensor3_christof has an array of T's or T *'s. */
+
+template<class A, class T, int Tensor_Dim0, int Tensor_Dim12,
+  int Dim12, int Dim0, char i, char j, char k>
+class Tensor3_dg_Expr<const Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,
+  T,Dim12,Dim0,i,j,k>
+{
+  const Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12> &iter;
+public:
+  Tensor3_dg_Expr(const Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12> &a): iter(a) {}
+
+  /* Need to switch the index order because a christof tensor is just
+     a dg tensor with the indices switched. */
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N3,N1,N2);
+  }
+};
+
+template<class A, class T, int Tensor_Dim0, int Tensor_Dim12,
+  int Dim12, int Dim0, char i, char j, char k>
+class Tensor3_dg_Expr<Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k>
+{
+  Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12> &iter;
+public:
+  Tensor3_dg_Expr(Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12> &a): iter(a) {}
+
+  /* Need to switch the index order because a christof tensor is just
+     a dg tensor with the indices switched.  I have to explicitly
+     declare the second operator= because otherwise the compiler will
+     generate its own and not use the template code. */
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N3,N1,N2);
+  }
+  template<class B, class U> inline
+  const Tensor3_dg_Expr<Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k> &
+  operator=(const Tensor3_dg_Expr<B,U,Dim12,Dim0,i,j,k> &result);
+
+  inline
+  const Tensor3_dg_Expr<Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k> &
+  operator=(const Tensor3_dg_Expr<Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,
+	    T,Dim12,Dim0,i,j,k> &result);
+
+  template<class U> inline
+  const Tensor3_dg_Expr<Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k> &
+  operator=(const U &d);
+};
+
+/* Specialized for Tensor4_ddg_number_rhs_0 (Tensor4_ddg with the
+   first index explicitly given). */
+
+template<class A, class T, int Dim23, int Dim1, char i, char j, char k, int N0>
+class Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N0>,
+  T,Dim23,Dim1,i,j,k>
+{
+  A &iter;
+public:
+  Tensor3_dg_Expr(A &a): iter(a) {}
+  T & operator()(const int N1, const int N2, const int N3)
+  {
+    return iter(N0,N1,N2,N3);
+  }
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return iter(N0,N1,N2,N3);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N0>,
+    T,Dim23,Dim1,i,j,k> &
+  operator=(const Tensor3_dg_Expr<B,U,Dim23,Dim1,i,j,k> &result);
+
+  const Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N0>,
+    T,Dim23,Dim1,i,j,k> &
+  operator=(const Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N0>,
+	    T,Dim23,Dim1,i,j,k> &result);
+};
+
+#include "Tensor3_dg_Expr_equals.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_Expr_equals.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_Expr_equals.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,366 @@
+/* Various assignment operators, including specializations to
+   Tensor3_christof.  I have to explicitly declare the second
+   operator= because otherwise the compiler will generate its own and
+   not use the template code. */
+
+/* T3dg=T3dg */
+
+template<class A, class B, class U, int Dim01, int Dim2,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline void T3dg_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &result,
+ const Number<Current_Dim0> &N0, const Number<Current_Dim1> &N1,
+ const Number<Current_Dim2> &N2)
+{
+  iter(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)=
+    result(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1);
+  T3dg_equals_T3dg(iter,result,Number<Current_Dim0-1>(),
+		   Number<Current_Dim1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class U, int Dim01, int Dim2,
+  char i, char j, char k, int Current_Dim1, int Current_Dim2>
+inline void T3dg_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &result,
+ const Number<1> &N0, const Number<Current_Dim1> &N1,
+ const Number<Current_Dim2> &N2)
+{
+  iter(0,Current_Dim1-1,Current_Dim2-1)=
+    result(0,Current_Dim1-1,Current_Dim2-1);
+  T3dg_equals_T3dg(iter,result,Number<Current_Dim1-1>(),
+		   Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class U, int Dim01, int Dim2,
+  char i, char j, char k, int Current_Dim2>
+inline void T3dg_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &result,
+ const Number<1> &N0, const Number<1> &N1,
+ const Number<Current_Dim2> &N2)
+{
+  iter(0,0,Current_Dim2-1)=result(0,0,Current_Dim2-1);
+  T3dg_equals_T3dg(iter,result,Number<Dim01>(),
+		   Number<Dim01>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline void T3dg_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &result,
+ const Number<1> &N0, const Number<1> &N1, const Number<1> &N2)
+{
+  iter(0,0,0)=result(0,0,0);
+}
+
+template<class A, class T, int Tensor_Dim01, int Tensor_Dim2,
+  int Dim01, int Dim2, char i, char j, char k>
+template<class B, class U> inline
+const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &
+Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k>::
+operator=(const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &result)
+{
+  T3dg_equals_T3dg(iter,result,Number<Dim01>(),Number<Dim01>(),Number<Dim2>());
+  return *this;
+}
+
+/* T3dg=T3dg_Expr(T3dg) */
+
+template<class A, class T, int Tensor_Dim01, int Tensor_Dim2,
+  int Dim01, int Dim2, char i, char j, char k> inline
+const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &
+Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k>::
+operator=(const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &result)
+{
+  return operator=<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T>(result);
+}
+
+/* T3dg=U */
+
+template<class A, class U, int Dim01, int Dim2,
+  int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline void T3dg_equals_generic(A &iter, const U &u,
+				const Number<Current_Dim0> &N0,
+				const Number<Current_Dim1> &N1,
+				const Number<Current_Dim2> &N2,
+				const Number<Dim01> &ND01,
+				const Number<Dim2> &ND2)
+{
+  iter(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1)=u;
+  T3dg_equals_generic(iter,u,Number<Current_Dim0-1>(),
+		      Number<Current_Dim1>(),Number<Current_Dim2>(),
+		      Number<Dim01>(),Number<Dim2>());
+}
+
+template<class A, class U, int Dim01, int Dim2,
+  int Current_Dim1, int Current_Dim2>
+inline void T3dg_equals_generic(A &iter, const U &u,
+				const Number<1> &N0,
+				const Number<Current_Dim1> &N1,
+				const Number<Current_Dim2> &N2,
+				const Number<Dim01> &ND01,
+				const Number<Dim2> &ND2)
+{
+  iter(0,Current_Dim1-1,Current_Dim2-1)=u;
+  T3dg_equals_generic(iter,u,Number<Current_Dim1-1>(),
+		      Number<Current_Dim1-1>(),Number<Current_Dim2>(),
+		      Number<Dim01>(),Number<Dim2>());
+}
+
+template<class A, class U, int Dim01, int Dim2, int Current_Dim2>
+inline void T3dg_equals_generic(A &iter, const U &u,
+				const Number<1> &N0, const Number<1> &N1,
+				const Number<Current_Dim2> &N2,
+				const Number<Dim01> &ND01,
+				const Number<Dim2> &ND2)
+{
+  iter(0,0,Current_Dim2-1)=u;
+  T3dg_equals_generic(iter,u,Number<Dim01>(),
+		      Number<Dim01>(),Number<Current_Dim2-1>(),
+		      Number<Dim01>(),Number<Dim2>());
+}
+
+template<class A, class U, int Dim01, int Dim2>
+inline void T3dg_equals_generic(A &iter, const U &u,
+				const Number<1> &N0, const Number<1> &N1,
+				const Number<1> &N2,
+				const Number<Dim01> &ND01,
+				const Number<Dim2> &ND2)
+{
+  iter(0,0,0)=u;
+}
+
+template<class A, class T, int Tensor_Dim01, int Tensor_Dim2,
+  int Dim01, int Dim2, char i, char j, char k>
+template<class U> inline
+const Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k> &
+Tensor3_dg_Expr<Tensor3_dg<A,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k>::
+operator=(const U &u)
+{
+  T3dg_equals_generic(iter,u,Number<Dim01>(),Number<Dim01>(),Number<Dim2>(),
+		      Number<Dim01>(),Number<Dim2>());
+  return *this;
+}
+
+
+/* Assignment operators for the specializations to Tensor3_christof. */
+
+/* T3ch=T3dg */
+
+template<class A, class B, class U, int Dim12, int Dim0,
+  char i, char j, char k, int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline void T3ch_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim12,Dim0,i,j,k> &result,
+ const Number<Current_Dim0> &N0, const Number<Current_Dim1> &N1,
+ const Number<Current_Dim2> &N2)
+{
+  iter(Current_Dim2-1,Current_Dim0-1,Current_Dim1-1)=
+    result(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1);
+  T3ch_equals_T3dg(iter,result,Number<Current_Dim0-1>(),
+		   Number<Current_Dim1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class U, int Dim12, int Dim0,
+  char i, char j, char k, int Current_Dim1, int Current_Dim2>
+inline void T3ch_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim12,Dim0,i,j,k> &result,
+ const Number<1> &N0, const Number<Current_Dim1> &N1,
+ const Number<Current_Dim2> &N2)
+{
+  iter(Current_Dim2-1,0,Current_Dim1-1)=
+    result(0,Current_Dim1-1,Current_Dim2-1);
+  T3ch_equals_T3dg(iter,result,Number<Current_Dim1-1>(),
+		   Number<Current_Dim1-1>(),Number<Current_Dim2>());
+}
+
+template<class A, class B, class U, int Dim12, int Dim0,
+  char i, char j, char k, int Current_Dim2>
+inline void T3ch_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim12,Dim0,i,j,k> &result,
+ const Number<1> &N0, const Number<1> &N1,
+ const Number<Current_Dim2> &N2)
+{
+  iter(Current_Dim2-1,0,0)=result(0,0,Current_Dim2-1);
+  T3ch_equals_T3dg(iter,result,Number<Dim12>(),
+		   Number<Dim12>(),Number<Current_Dim2-1>());
+}
+
+template<class A, class B, class U, int Dim12, int Dim0,
+  char i, char j, char k>
+inline void T3ch_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim12,Dim0,i,j,k> &result,
+ const Number<1> &N0, const Number<1> &N1, const Number<1> &N2)
+{
+  iter(0,0,0)=result(0,0,0);
+}
+
+
+template<class Tp, class T, int Tensor_Dim0, int Tensor_Dim12,
+  int Dim12, int Dim0, char i, char j, char k>
+template<class B, class U> inline
+const Tensor3_dg_Expr<Tensor3_christof<Tp,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k> &
+Tensor3_dg_Expr<Tensor3_christof<Tp,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k>::
+operator=(const Tensor3_dg_Expr<B,U,Dim12,Dim0,i,j,k> &result)
+{
+  T3ch_equals_T3dg(iter,result,Number<Dim12>(),Number<Dim12>(),Number<Dim0>());
+  return *this;
+}
+
+/* T3ch=T3ch_Expr(T3ch) */
+
+template<class Tp, class T, int Tensor_Dim0, int Tensor_Dim12,
+  int Dim12, int Dim0, char i, char j, char k> inline
+const Tensor3_dg_Expr<Tensor3_christof<Tp,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k> &
+Tensor3_dg_Expr<Tensor3_christof<Tp,Tensor_Dim0,Tensor_Dim12>,T,Dim12,Dim0,i,j,k>::
+operator=(const Tensor3_dg_Expr<Tensor3_christof<Tp,Tensor_Dim0,Tensor_Dim12>,
+	  T,Dim12,Dim0,i,j,k> &result)
+{
+  return operator=<Tensor3_christof<Tp,Tensor_Dim0,Tensor_Dim12>,T>(result);
+}
+
+
+/* T3ch=U */
+
+template<class A, class U, int Dim12, int Dim0,
+  int Current_Dim0, int Current_Dim1, int Current_Dim2>
+inline void T3ch_equals_generic(A &iter, const U &u,
+				const Number<Current_Dim0> &N0,
+				const Number<Current_Dim1> &N1,
+				const Number<Current_Dim2> &N2,
+				const Number<Dim12> &ND01,
+				const Number<Dim0> &ND2)
+{
+  iter(Current_Dim2-1,Current_Dim0-1,Current_Dim1-1)=u;
+  T3ch_equals_generic(iter,u,Number<Current_Dim0-1>(),
+		      Number<Current_Dim1>(),Number<Current_Dim2>(),
+		      Number<Dim12>(),Number<Dim0>());
+}
+
+template<class A, class U, int Dim12, int Dim0,
+  int Current_Dim1, int Current_Dim2>
+inline void T3ch_equals_generic(A &iter, const U &u,
+				const Number<1> &N0,
+				const Number<Current_Dim1> &N1,
+				const Number<Current_Dim2> &N2,
+				const Number<Dim12> &ND01,
+				const Number<Dim0> &ND2)
+{
+  iter(Current_Dim2-1,0,Current_Dim1-1)=u;
+  T3ch_equals_generic(iter,u,Number<Current_Dim1-1>(),
+		      Number<Current_Dim1-1>(),Number<Current_Dim2>(),
+		      Number<Dim12>(),Number<Dim0>());
+}
+
+template<class A, class U, int Dim12, int Dim0, int Current_Dim2>
+inline void T3ch_equals_generic(A &iter, const U &u,
+				const Number<1> &N0, const Number<1> &N1,
+				const Number<Current_Dim2> &N2,
+				const Number<Dim12> &ND01,
+				const Number<Dim0> &ND2)
+{
+  iter(Current_Dim2-1,0,0)=u;
+  T3ch_equals_generic(iter,u,Number<Dim12>(),
+		      Number<Dim12>(),Number<Current_Dim2-1>(),
+		      Number<Dim12>(),Number<Dim0>());
+}
+
+template<class A, class U, int Dim12, int Dim0>
+inline void T3ch_equals_generic(A &iter, const U &u,
+				const Number<1> &N0, const Number<1> &N1,
+				const Number<1> &N2,
+				const Number<Dim12> &ND01,
+				const Number<Dim0> &ND2)
+{
+  iter(0,0,0)=u;
+}
+
+template<class A, class T, int Tensor_Dim0, int Tensor_Dim12,
+  int Dim12, int Dim0, char i, char j, char k>
+template<class U> inline
+const Tensor3_dg_Expr<Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,
+  T,Dim12,Dim0,i,j,k> &
+Tensor3_dg_Expr<Tensor3_christof<A,Tensor_Dim0,Tensor_Dim12>,
+  T,Dim12,Dim0,i,j,k>::
+operator=(const U &u)
+{
+  T3ch_equals_generic(iter,u,Number<Dim12>(),Number<Dim12>(),Number<Dim0>(),
+		      Number<Dim12>(),Number<Dim0>());
+  return *this;
+}
+
+/* Assignment operators for the specializations to Tensor4_ddg_number_rhs_0. */
+
+/* T4ddgrhs0=T3dg */
+
+template<class A, class B, class U, int Dim23, int Dim1, char i, char j,
+  char k, int Current_Dim0, int Current_Dim1, int Current_Dim2, int N>
+inline void T4ddgrhs0_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim23,Dim1,i,j,k> &result,
+ const Number<Current_Dim0> &N0, const Number<Current_Dim1> &N1,
+ const Number<Current_Dim2> &N2, const Number<N> &NN)
+{
+  iter(N,Current_Dim2-1,Current_Dim0-1,Current_Dim1-1)=
+    result(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1);
+  T4ddgrhs0_equals_T3dg(iter,result,Number<Current_Dim0-1>(),
+			Number<Current_Dim1>(),Number<Current_Dim2>(),
+			Number<N>());
+}
+
+template<class A, class B, class U, int Dim23, int Dim1,
+  char i, char j, char k, int Current_Dim1, int Current_Dim2, int N>
+inline void T4ddgrhs0_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim23,Dim1,i,j,k> &result,
+ const Number<1> &N0, const Number<Current_Dim1> &N1,
+ const Number<Current_Dim2> &N2, const Number<N> &NN)
+{
+  iter(N,Current_Dim2-1,0,Current_Dim1-1)=
+    result(0,Current_Dim1-1,Current_Dim2-1);
+  T4ddgrhs0_equals_T3dg(iter,result,Number<Current_Dim1-1>(),
+			Number<Current_Dim1-1>(),Number<Current_Dim2>(),
+			Number<N>());
+}
+
+template<class A, class B, class U, int Dim23, int Dim1,
+  char i, char j, char k, int Current_Dim2, int N>
+inline void T4ddgrhs0_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim23,Dim1,i,j,k> &result,
+ const Number<1> &N0, const Number<1> &N1,
+ const Number<Current_Dim2> &N2, const Number<N> &NN)
+{
+  iter(N,Current_Dim2-1,0,0)=result(0,0,Current_Dim2-1);
+  T4ddgrhs0_equals_T3dg(iter,result,Number<Dim23>(),
+		   Number<Dim23>(),Number<Current_Dim2-1>(),Number<N>());
+}
+
+template<class A, class B, class U, int Dim23, int Dim1,
+  char i, char j, char k, int N>
+inline void T4ddgrhs0_equals_T3dg
+(A &iter, const Tensor3_dg_Expr<B,U,Dim23,Dim1,i,j,k> &result,
+ const Number<1> &N0, const Number<1> &N1, const Number<1> &N2,
+ const Number<N> &NN)
+{
+  iter(N,0,0,0)=result(0,0,0);
+}
+
+template<class A, class T, int Dim23, int Dim1, char i, char j, char k, int N>
+template<class B, class U> inline
+const Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N>,T,Dim23,Dim1,i,j,k> &
+Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N>,T,Dim23,Dim1,i,j,k>::
+operator=(const Tensor3_dg_Expr<B,U,Dim23,Dim1,i,j,k> &result)
+{
+  T4ddgrhs0_equals_T3dg(iter,result,Number<Dim23>(),Number<Dim23>(),
+			Number<Dim1>(),Number<N>());
+  return *this;
+}
+
+/* T4ddgrhs0=T4ddgrhs0 */
+
+template<class A, class T, int Dim23, int Dim1, char i, char j, char k, int N>
+inline
+const Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N>,T,Dim23,Dim1,i,j,k> &
+Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N>,T,Dim23,Dim1,i,j,k>::
+operator=(const Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0<A,T,N>,
+	  T,Dim23,Dim1,i,j,k> &result)
+{
+  return operator=<Tensor4_ddg_number_rhs_0<A,T,N>,T>(result);
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_and_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_and_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,47 @@
+/* Multiply a Tensor1 and a Tensor3_dg together but don't contract, yielding a
+   Tensor3_dg. */
+
+/* A(i,j,k) & B(k) -> Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_and_Tensor1
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor1_Expr<B,U,Dim2,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)*iterB(N3);
+  }
+  
+  Tensor3_dg_and_Tensor1(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			 const Tensor1_Expr<B,U,Dim2,k> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_and_Tensor1<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator&(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	   const Tensor1_Expr<B,U,Dim2,k> &b)
+{
+  typedef const Tensor3_dg_and_Tensor1<A,B,T,U,Dim01,Dim2,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(k) & A(i,j,k) -> Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_and_Tensor1<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator&(const Tensor1_Expr<B,U,Dim2,k> &b,
+	   const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_and_Tensor1<A,B,T,U,Dim01,Dim2,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_and_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_and_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+/* Multiply a Tensor2_symmetric and a Tensor3_dg together but don't
+   contract, yielding a Tensor3_dg. */
+
+/* A(i,j,k) & B(i,j) -> Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_and_Tensor2_symmetric
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)*iterB(N1,N2);
+  }
+
+  Tensor3_dg_and_Tensor2_symmetric
+  (const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_and_Tensor2_symmetric<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator&(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b)
+{
+  typedef const Tensor3_dg_and_Tensor2_symmetric<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(i,j) & A(i,j,k) -> Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_and_Tensor2_symmetric<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator&(const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_and_Tensor2_symmetric<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_and_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_and_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,66 @@
+/* Subtracts a Tensor3_dg from a Tensor3_dg, yielding a
+   Tensor3_antisymmetric. */
+
+/* A(i,j,k)-B(i,k,j)->Tensor3_antisymmetric */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor3_dg_and_Tensor3_dg_12
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim,Dim,i,k,j> iterB;
+public:
+  typename promote<T,U>::V  operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N1,N3,N2);
+  }
+
+  Tensor3_dg_and_Tensor3_dg_12(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+			       const Tensor3_dg_Expr<B,U,Dim,Dim,i,k,j> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor3_dg_and_Tensor3_dg_12<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim,i,j,k>
+operator&&(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+	   const Tensor3_dg_Expr<B,U,Dim,Dim,i,k,j> &b)
+{
+  typedef const Tensor3_dg_and_Tensor3_dg_12<A,B,T,U,Dim,i,j,k> TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)-B(k,j,i)->Tensor3_antisymmetric */
+/* We have to do a little index gymnastics here because a
+   Tensor3_antisymmetric is antisymmetric on the last two indices, not
+   the first and last index. */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor3_dg_and_Tensor3_dg_02
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> iterB;
+public:
+  typename promote<T,U>::V  operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N2,N1,N3)-iterB(N3,N1,N2);
+  }
+
+  Tensor3_dg_and_Tensor3_dg_02(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+			       const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor3_dg_and_Tensor3_dg_02<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim,j,i,k>
+operator&&(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+	   const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> &b)
+{
+  typedef const Tensor3_dg_and_Tensor3_dg_02<A,B,T,U,Dim,i,j,k> TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,j,i,k>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_constructor.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_constructor.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,164 @@
+/* A helper class that allows simple initialization of the Tensor3_dg,
+   but only if it has the correct number of elements. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+class Tensor3_dg_constructor;
+
+template<class T>
+class Tensor3_dg_constructor<T,2,2>
+{
+public:
+  Tensor3_dg_constructor(T data[3][2], T d000, T d001, T d010, T d011,
+			 T d110, T d111)
+  {
+    data[0][0]=d000;
+    data[0][1]=d001;
+    data[1][0]=d010;
+    data[1][1]=d011;
+    data[2][0]=d110;
+    data[2][1]=d111;
+  }
+};
+
+template<class T>
+class Tensor3_dg_constructor<T,3,3>
+{
+public:
+  Tensor3_dg_constructor(T data[6][3], T d000, T d001, T d002, T d010, T d011,
+			 T d012, T d020, T d021, T d022, T d110, T d111,
+			 T d112, T d120, T d121, T d122, T d220, T d221,
+			 T d222)
+  {
+    data[0][0]=d000;
+    data[1][0]=d010;
+    data[2][0]=d020;
+    data[3][0]=d110;
+    data[4][0]=d120;
+    data[5][0]=d220;
+
+    data[0][1]=d001;
+    data[1][1]=d011;
+    data[2][1]=d021;
+    data[3][1]=d111;
+    data[4][1]=d121;
+    data[5][1]=d221;
+
+    data[0][2]=d002;
+    data[1][2]=d012;
+    data[2][2]=d022;
+    data[3][2]=d112;
+    data[4][2]=d122;
+    data[5][2]=d222;
+  }
+};
+
+template<class T>
+class Tensor3_dg_constructor<T,4,4>
+{
+public:
+  Tensor3_dg_constructor(T data[10][4], T d000, T d001, T d002, T d003,
+			 T d010, T d011, T d012, T d013,
+			 T d020, T d021, T d022, T d023,
+			 T d030, T d031, T d032, T d033,
+			 T d110, T d111, T d112, T d113,
+			 T d120, T d121, T d122, T d123,
+			 T d130, T d131, T d132, T d133,
+			 T d220, T d221, T d222, T d223,
+			 T d230, T d231, T d232, T d233,
+			 T d330, T d331, T d332, T d333)
+  {
+    data[0][0]=d000;
+    data[1][0]=d010;
+    data[2][0]=d020;
+    data[3][0]=d030;
+    data[4][0]=d110;
+    data[5][0]=d120;
+    data[6][0]=d130;
+    data[7][0]=d220;
+    data[8][0]=d230;
+    data[9][0]=d330;
+
+    data[0][1]=d001;
+    data[1][1]=d011;
+    data[2][1]=d021;
+    data[3][1]=d031;
+    data[4][1]=d111;
+    data[5][1]=d121;
+    data[6][1]=d131;
+    data[7][1]=d221;
+    data[8][1]=d231;
+    data[9][1]=d331;
+
+    data[0][2]=d002;
+    data[1][2]=d012;
+    data[2][2]=d022;
+    data[3][2]=d032;
+    data[4][2]=d112;
+    data[5][2]=d122;
+    data[6][2]=d132;
+    data[7][2]=d222;
+    data[8][2]=d232;
+    data[9][2]=d332;
+
+    data[0][3]=d003;
+    data[1][3]=d013;
+    data[2][3]=d023;
+    data[3][3]=d033;
+    data[4][3]=d113;
+    data[5][3]=d123;
+    data[6][3]=d133;
+    data[7][3]=d223;
+    data[8][3]=d233;
+    data[9][3]=d333;
+  }
+};
+
+template<class T>
+class Tensor3_dg_constructor<T,4,3>
+{
+public:
+  Tensor3_dg_constructor(T data[10][3], T d000, T d001, T d002,
+			 T d010, T d011, T d012,
+			 T d020, T d021, T d022,
+			 T d030, T d031, T d032,
+			 T d110, T d111, T d112,
+			 T d120, T d121, T d122,
+			 T d130, T d131, T d132,
+			 T d220, T d221, T d222,
+			 T d230, T d231, T d232,
+			 T d330, T d331, T d332)
+  {
+    data[0][0]=d000;
+    data[1][0]=d010;
+    data[2][0]=d020;
+    data[3][0]=d030;
+    data[4][0]=d110;
+    data[5][0]=d120;
+    data[6][0]=d130;
+    data[7][0]=d220;
+    data[8][0]=d230;
+    data[9][0]=d330;
+
+    data[0][1]=d001;
+    data[1][1]=d011;
+    data[2][1]=d021;
+    data[3][1]=d031;
+    data[4][1]=d111;
+    data[5][1]=d121;
+    data[6][1]=d131;
+    data[7][1]=d221;
+    data[8][1]=d231;
+    data[9][1]=d331;
+
+    data[0][2]=d002;
+    data[1][2]=d012;
+    data[2][2]=d022;
+    data[3][2]=d032;
+    data[4][2]=d112;
+    data[5][2]=d122;
+    data[6][2]=d132;
+    data[7][2]=d222;
+    data[8][2]=d232;
+    data[9][2]=d332;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_divide_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_divide_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,28 @@
+/* Divides a Tensor3_dg by a generic, yielding a Tensor3_dg. */
+
+template<class A, class T, class U, int Dim01, int Dim2, char i, char j,char k>
+class Tensor3_dg_divide_generic
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)/d;
+  }
+
+  Tensor3_dg_divide_generic(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			   const U &d0): iterA(a), d(d0) {}
+};
+
+/* A(i,j,k)/d0->Tensor3_dg */
+
+template<class A, class T, class U, int Dim01, int Dim2, char i, char j,char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_divide_generic<A,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator/(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a, const U &d0)
+{
+  typedef const Tensor3_dg_divide_generic<A,T,U,Dim01,Dim2,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_function_operator.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_function_operator.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,330 @@
+/* This contains the definitions of the almost all of the indexing
+   operators for Tensor3_dg. */
+
+/* These operator()'s are the first part in constructing template
+   expressions. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, char k, int Dim01, int Dim2>
+inline Tensor3_dg_Expr<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T,Dim01,Dim2,i,j,k>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()
+  (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+   const Index<k,Dim2> index3)
+{
+  return Tensor3_dg_Expr<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,Dim01,Dim2,i,j,k>(*this);
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, char k, int Dim01, int Dim2>
+inline Tensor3_dg_Expr<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T,Dim01,Dim2,i,j,k>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()
+  (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+   const Index<k,Dim2> index3) const
+{
+  return Tensor3_dg_Expr<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,Dim01,Dim2,i,j,k> (*this);
+}
+
+/* These operators are for internal contractions. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int Dim, int Dim12>
+inline Tensor1_Expr<const Tensor3_contracted_12
+<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,Dim12,i>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()
+  (const Index<i,Dim> index1, const Index<j,Dim12> index2,
+   const Index<j,Dim12> index3) const
+{
+  typedef const Tensor3_contracted_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,Dim12,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int Dim, int Dim02>
+inline Tensor1_Expr<const Tensor3_contracted_02
+<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,Dim02,i>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()
+  (const Index<j,Dim02> index1, const Index<i,Dim> index2,
+   const Index<j,Dim02> index3) const
+{
+  typedef const Tensor3_contracted_02<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,Dim02,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int Dim, int Dim01>
+inline Tensor1_Expr<const Tensor3_contracted_01
+<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,Dim01,i>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()
+  (const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+   const Index<i,Dim> index3) const
+{
+  typedef const Tensor3_contracted_01<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,Dim01,i> TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+}
+
+/* This is for expressions where a number is used for one slot, and
+   indices for the others, yielding a Tensor2_Expr or
+   Tensor2_symmetric_Expr.  The non-const versions don't actually
+   create a Tensor3_dg_number_rhs_* object, while the const versions
+   do create a Tensor3_dg_number_*. */
+
+/* First slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int N, int Dim0, int Dim1>
+Tensor2_Expr<Tensor3_dg_number_rhs_0<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>,
+  T,Dim0,Dim1,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Number<N> n1,
+				     const Index<i,Dim0> index1,
+				     const Index<j,Dim1> index2)
+{
+  typedef Tensor3_dg_number_rhs_0<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(*this);
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int N, int Dim0, int Dim1>
+const Tensor2_Expr<const Tensor3_dg_number_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>,
+  T,Dim0,Dim1,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Number<N> n1,
+				     const Index<i,Dim0> index1,
+				     const Index<j,Dim1> index2) const
+{
+  typedef const Tensor3_dg_number_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(TensorExpr(*this));
+}
+
+/* Second slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int N, int Dim0, int Dim1>
+Tensor2_Expr<Tensor3_dg_number_rhs_0<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>,
+  T,Dim0,Dim1,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim0> index1,
+				     const Number<N> n1,
+				     const Index<j,Dim1> index2)
+{
+  typedef Tensor3_dg_number_rhs_0<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(*this);
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int N, int Dim0, int Dim1>
+const Tensor2_Expr<const Tensor3_dg_number_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>,
+  T,Dim0,Dim1,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim0> index1,
+				     const Number<N> n1,
+				     const Index<j,Dim1> index2) const
+{
+  typedef const Tensor3_dg_number_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(TensorExpr(*this));
+}
+
+/* Third slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int N, int Dim>
+inline Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>,
+  T,Dim,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim> index1,
+				     const Index<j,Dim> index2,
+				     const Number<N> n1)
+{
+  typedef Tensor3_dg_number_rhs_2<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(*this);
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int N, int Dim>
+const Tensor2_symmetric_Expr<const Tensor3_dg_number_2
+<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim> index1,
+				     const Index<j,Dim> index2,
+				     const Number<N> n1) const
+{
+  typedef const Tensor3_dg_number_2<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this));
+}
+
+/* This is for expressions where a number is used for two slots, and
+   an Index for the other, yielding a Tensor1_Expr.  The non-const
+   versions don't actually create a Tensor3_dg_number_rhs_* object,
+   while the const versions do create a Tensor3_dg_number_*. */
+
+/* Index in first slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int N1, int N2, int Dim>
+Tensor1_Expr<Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim> index,
+				     const Number<N1> n1,
+				     const Number<N2> n2)
+{
+  typedef Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int N1, int N2, int Dim>
+const Tensor1_Expr<const Tensor3_dg_number_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T,N1,N2>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim> index,
+				     const Number<N1> n1,
+				     const Number<N2> n2) const
+{
+  typedef const Tensor3_dg_number_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+}
+
+/* Index in second slot.  I use the same structures as for the Index
+   in the first slot since the tensor is symmetric on the first two
+   indices. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int N1, int N2, int Dim>
+Tensor1_Expr<Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Number<N1> n1,
+				     const Index<i,Dim> index,
+				     const Number<N2> n2)
+{
+  typedef Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int N1, int N2, int Dim>
+const Tensor1_Expr<const Tensor3_dg_number_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T,N1,N2>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Number<N1> n1,
+				     const Index<i,Dim> index,
+				     const Number<N2> n2) const
+{
+  typedef const Tensor3_dg_number_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+}
+
+/* Index in third slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int N1, int N2, int Dim>
+Tensor1_Expr<Tensor3_dg_number_rhs_01<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Number<N1> n1, const Number<N2> n2,
+				     const Index<i,Dim> index)
+{
+  typedef Tensor3_dg_number_rhs_01<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+}
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int N1, int N2, int Dim>
+const Tensor1_Expr<const Tensor3_dg_number_01<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T,N1,N2>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Number<N1> n1, const Number<N2> n2,
+				     const Index<i,Dim> index) const
+{
+  typedef const Tensor3_dg_number_01<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+}
+
+/* Specializations for using actual numbers instead of Number<>.
+   This is for expressions where an actual number is used for one
+   slot, and indices for the others, yielding a Tensor2_Expr or
+   Tensor2_symmetric_Expr. I only define the const versions. */
+
+/* First slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int Dim0, int Dim1>
+const Tensor2_Expr<const Tensor3_dg_numeral_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T>,
+  T,Dim0,Dim1,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const int N, const Index<i,Dim0> index1,
+				     const Index<j,Dim1> index2) const
+{
+  typedef const Tensor3_dg_numeral_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(TensorExpr(*this,N));
+}
+
+/* Second slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int Dim0, int Dim1>
+const Tensor2_Expr<const Tensor3_dg_numeral_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T>,
+  T,Dim0,Dim1,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim0> index1, const int N,
+				     const Index<j,Dim1> index2) const
+{
+  typedef const Tensor3_dg_numeral_0<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+  return Tensor2_Expr<TensorExpr,T,Dim0,Dim1,i,j>(TensorExpr(*this,N));
+}
+
+/* Third slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, char j, int Dim>
+const Tensor2_symmetric_Expr<const Tensor3_dg_numeral_2
+<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i,j>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim> index1,
+				     const Index<j,Dim> index2,
+				     const int N) const
+{
+  typedef const Tensor3_dg_numeral_2<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this,N));
+}
+
+/* This is for expressions where an actual number is used for two
+   slots, and an Index for the other, yielding a Tensor1_Expr. I
+   only define the const versions. */
+
+/* Index in first slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int Dim>
+const Tensor1_Expr<const Tensor3_dg_numeral_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const Index<i,Dim> index, const int N1,
+				     const int N2) const
+{
+  typedef const Tensor3_dg_numeral_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+}
+
+/* Index in second slot.  I use the same structures as for the Index
+   in the first slot since the tensor is symmetric on the first two
+   indices. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int Dim>
+const Tensor1_Expr<const Tensor3_dg_numeral_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const int N1, const Index<i,Dim> index,
+				     const int N2) const
+{
+  typedef const Tensor3_dg_numeral_12<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+}
+
+/* Index in third slot. */
+
+template<class T, int Tensor_Dim01, int Tensor_Dim2>
+template<char i, int Dim>
+const Tensor1_Expr<const Tensor3_dg_numeral_01<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+  T>,T,Dim,i>
+Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>::operator()(const int N1, const int N2,
+				     const Index<i,Dim> index) const
+{
+  typedef const Tensor3_dg_numeral_01<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_minus_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_minus_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,62 @@
+/* Subtracts a Tensor3_dg from a Tensor3_dg, yielding a Tensor3_dg or
+   Tensor3. */
+
+/* A(i,j,k)-B(i,j,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_minus_Tensor3_dg
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N1,N2,N3);
+  }
+
+  Tensor3_dg_minus_Tensor3_dg(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a, const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_minus_Tensor3_dg
+<A,B,T,U,Dim01,Dim2,i,j,k>,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator-(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &b)
+{
+  typedef const Tensor3_dg_minus_Tensor3_dg<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)-B(k,j,i)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor3_dg_minus_Tensor3_dg_02
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)-iterB(N3,N2,N1);
+  }
+
+  Tensor3_dg_minus_Tensor3_dg_02(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+				const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor3_Expr<const Tensor3_dg_minus_Tensor3_dg_02<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim,Dim,i,j,k>
+operator-(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> &b)
+{
+  typedef const Tensor3_dg_minus_Tensor3_dg_02<A,B,T,U,Dim,i,j,k> TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,Dim,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_number.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_number.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,74 @@
+/* This is for expressions where a number is used for one or two
+   slots, and an index for the others, yielding a Tensor1_Expr,
+   Tensor2_Expr, or Tensor2_symmetric_Expr. */
+
+/* First or second slot. */
+
+template<class A, class T, int N>
+class Tensor3_dg_number_0
+{
+  A iterA;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N,N1,N2);
+  }
+  Tensor3_dg_number_0(const A &a): iterA(a) {}
+};
+
+template<class A, class T, int N>
+class Tensor3_dg_number_rhs_0
+{};
+
+/* Third slot. */
+
+template<class A, class T, int N>
+class Tensor3_dg_number_2
+{
+  A iterA;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2,N);
+  }
+  Tensor3_dg_number_2(const A &a): iterA(a) {}
+};
+
+template<class A, class T, int N>
+class Tensor3_dg_number_rhs_2
+{};
+
+/* Second and third slot (or first and third slot). */
+
+template<class A, class T, int N1, int N2>
+class Tensor3_dg_number_12
+{
+  A iterA;
+public:
+  T operator()(const int N) const
+  {
+    return iterA(N,N1,N2);
+  }
+  Tensor3_dg_number_12(const A &a):iterA(a) {}
+};
+
+template<class A, class T, int N1, int N2>
+class Tensor3_dg_number_rhs_12 {};
+
+
+/* First and second slot. */
+
+template<class A, class T, int N1, int N2>
+class Tensor3_dg_number_01
+{
+  A iterA;
+public:
+  T operator()(const int N) const
+  {
+    return iterA(N1,N2,N);
+  }
+  Tensor3_dg_number_01(const A &a):iterA(a) {}
+};
+
+template<class A, class T, int N1, int N2>
+class Tensor3_dg_number_rhs_01 {};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_numeral.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_numeral.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,65 @@
+/* This is for expressions where a number is used for one or two
+   slots, and an index for the others, yielding a Tensor1_Expr,
+   Tensor2_Expr, or Tensor2_symmetric_Expr. */
+
+/* First or second slot. */
+
+template<class A, class T>
+class Tensor3_dg_numeral_0
+{
+  A iterA;
+  const int N;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N,N1,N2);
+  }
+  Tensor3_dg_numeral_0(const A &a, const int NN): iterA(a), N(NN) {}
+};
+
+/* Third slot. */
+
+template<class A, class T>
+class Tensor3_dg_numeral_2
+{
+  A iterA;
+  const int N;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2,N);
+  }
+  Tensor3_dg_numeral_2(const A &a, const int NN): iterA(a), N(NN) {}
+};
+
+/* Second and third slot (or first and third slot). */
+
+template<class A, class T>
+class Tensor3_dg_numeral_12
+{
+  A iterA;
+  const int N1,N2;
+public:
+  T operator()(const int N) const
+  {
+    return iterA(N,N1,N2);
+  }
+  Tensor3_dg_numeral_12(const A &a, const int NN1, const int NN2)
+    :iterA(a), N1(NN1), N2(NN2) {}
+};
+
+/* First and second slot. */
+
+template<class A, class T>
+class Tensor3_dg_numeral_01
+{
+  A iterA;
+  const int N1,N2;
+public:
+  T operator()(const int N) const
+  {
+    return iterA(N1,N2,N);
+  }
+  Tensor3_dg_numeral_01(const A &a, const int NN1, const int NN2)
+    :iterA(a), N1(NN1), N2(NN2) {}
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_or_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_or_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,63 @@
+/* Adds two Tensor3_dg's to make a Tensor3_dg, but with different
+   symmetries. */
+
+/* A(i,j,k)+B(i,k,j) -> Tensor3_dg(j,k,i) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor3_dg_or_Tensor3_dg_12
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim,Dim,i,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N3,N1,N2)+iterB(N3,N2,N1);
+  }
+
+  Tensor3_dg_or_Tensor3_dg_12(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+			      const Tensor3_dg_Expr<B,U,Dim,Dim,i,k,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_or_Tensor3_dg_12<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim,j,k,i>
+operator||(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+	   const Tensor3_dg_Expr<B,U,Dim,Dim,i,k,j> &b)
+{
+  typedef const Tensor3_dg_or_Tensor3_dg_12<A,B,T,U,Dim,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,j,k,i>
+    (TensorExpr(a,b));
+}
+
+/* A(j,i,k)+B(k,i,j) -> Tensor3_dg(j,k,i) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor3_dg_or_Tensor3_dg_02
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,j,i,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim,Dim,k,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N3,N2)+iterB(N2,N3,N1);
+  }
+
+  Tensor3_dg_or_Tensor3_dg_02(const Tensor3_dg_Expr<A,T,Dim,Dim,j,i,k> &a,
+			      const Tensor3_dg_Expr<B,U,Dim,Dim,k,i,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_or_Tensor3_dg_02<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim,j,k,i>
+operator||(const Tensor3_dg_Expr<A,T,Dim,Dim,j,i,k> &a,
+	   const Tensor3_dg_Expr<B,U,Dim,Dim,k,i,j> &b)
+{
+  typedef const Tensor3_dg_or_Tensor3_dg_02<A,B,T,U,Dim,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,j,k,i>
+    (TensorExpr(a,b));
+}
+
+
+    
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_plus_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_plus_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,92 @@
+/* Adds two Tensor3_dg's together, yielding a Tensor3_dg or Tensor3. */
+
+/* A(i,j,k)+B(i,j,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_plus_Tensor3_dg
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N1,N2,N3);
+  }
+
+  Tensor3_dg_plus_Tensor3_dg(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a, const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_plus_Tensor3_dg
+<A,B,T,U,Dim01,Dim2,i,j,k>,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator+(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim01,Dim2,i,j,k> &b)
+{
+  typedef const Tensor3_dg_plus_Tensor3_dg<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)+B(j,i,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_plus_Tensor3_dg_10
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim01,Dim2,j,i,k> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N1,N2,N3);
+  }
+
+  Tensor3_dg_plus_Tensor3_dg_10(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a, const Tensor3_dg_Expr<B,U,Dim01,Dim2,j,i,k> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_plus_Tensor3_dg_10
+<A,B,T,U,Dim01,Dim2,i,j,k>,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator+(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim01,Dim2,j,i,k> &b)
+{
+  typedef const Tensor3_dg_plus_Tensor3_dg_10<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)+B(k,j,i)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+class Tensor3_dg_plus_Tensor3_dg_210
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)+iterB(N3,N2,N1);
+  }
+
+  Tensor3_dg_plus_Tensor3_dg_210(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+				const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, char i, char j, char k>
+inline const Tensor3_Expr<const Tensor3_dg_plus_Tensor3_dg_210<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,Dim,Dim,i,j,k>
+operator+(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim,Dim,k,j,i> &b)
+{
+  typedef const Tensor3_dg_plus_Tensor3_dg_210<A,B,T,U,Dim,i,j,k> TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,Dim,i,j,k>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_pointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_pointer.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,453 @@
+/* A version for pointers. */
+
+template <class T, int Tensor_Dim01, int Tensor_Dim2>
+class Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>
+{
+  mutable T * restrict data[(Tensor_Dim01*(Tensor_Dim01+1))/2][Tensor_Dim2];
+public:
+  Tensor3_dg() {}
+
+  /* Tensor_Dim01=2, Tensor_Dim2=2 */
+  Tensor3_dg(T *d000, T *d001, T *d010, T *d011, T *d110, T *d111)
+  {
+    Tensor3_dg_constructor<T* restrict,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d010,d011,d110,d111);
+  }
+
+  /* Tensor_Dim01=3, Tensor_Dim2=3 */
+  Tensor3_dg(T *d000, T *d001, T *d002, T *d010,
+	     T *d011, T *d012, T *d020, T *d021,
+	     T *d022, T *d110, T *d111, T *d112,
+	     T *d120, T *d121, T *d122,
+	     T *d220, T *d221, T *d222)
+  {
+    Tensor3_dg_constructor<T* restrict,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d002,d010,d011,d012,d020,d021,
+       d022,d110,d111,d112,d120,d121,d122,d220,d221,d222);
+  }
+
+  /* Tensor_Dim01=4, Tensor_Dim2=4 */
+  Tensor3_dg(T *d000, T *d001, T *d002, T *d003,
+	     T *d010, T *d011, T *d012, T *d013,
+	     T *d020, T *d021, T *d022, T *d023,
+	     T *d030, T *d031, T *d032, T *d033,
+	     T *d110, T *d111, T *d112, T *d113,
+	     T *d120, T *d121, T *d122, T *d123,
+	     T *d130, T *d131, T *d132, T *d133,
+	     T *d220, T *d221, T *d222, T *d223,
+	     T *d230, T *d231, T *d232, T *d233,
+	     T *d330, T *d331, T *d332, T *d333)
+  {
+    Tensor3_dg_constructor<T* restrict,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d002,d003,d010,d011,d012,d013,
+       d020,d021,d022,d023,d030,d031,d032,d033,
+       d110,d111,d112,d113,d120,d121,d122,d123,
+       d130,d131,d132,d133,d220,d221,d222,d223,
+       d230,d231,d232,d233,d330,d331,d332,d333);
+  }
+
+  /* Tensor_Dim01=4, Tensor_Dim2=3 */
+  Tensor3_dg(T *d000, T *d001, T *d002, T *d010, T *d011, T *d012,
+	     T *d020, T *d021, T *d022, T *d030, T *d031, T *d032,
+	     T *d110, T *d111, T *d112, T *d120, T *d121, T *d122,
+	     T *d130, T *d131, T *d132, T *d220, T *d221, T *d222,
+	     T *d230, T *d231, T *d232, T *d330, T *d331, T *d332)
+  {
+    Tensor3_dg_constructor<T* restrict,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d002,d010,d011,d012,
+       d020,d021,d022,d030,d031,d032,
+       d110,d111,d112,d120,d121,d122,
+       d130,d131,d132,d220,d221,d222,
+       d230,d231,d232,d330,d331,d332);
+  }
+
+  /* There are two operator(int,int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2, const int N3)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0
+       || N2>=Tensor_Dim01 || N2<0 || N3>=Tensor_Dim2 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T*,"
+		  << Tensor_Dim01 << "," << Tensor_Dim2 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? *data[N1+(N2*(2*Tensor_Dim01-N2-1))/2][N3]
+      : *data[N2+(N1*(2*Tensor_Dim01-N1-1))/2][N3];
+  }
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0
+       || N2>=Tensor_Dim01 || N2<0 || N3>=Tensor_Dim2 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T*,"
+		  << Tensor_Dim01 << "," << Tensor_Dim2 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? *data[N1+(N2*(2*Tensor_Dim01-N2-1))/2][N3]
+      : *data[N2+(N1*(2*Tensor_Dim01-N1-1))/2][N3];
+  }
+
+  T* ptr(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0
+       || N2>=Tensor_Dim01 || N2<0 || N3>=Tensor_Dim2 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T,"
+		  << Tensor_Dim01 << "," << Tensor_Dim2 << ">.ptr("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? data[N1+(N2*(2*Tensor_Dim01-N2-1))/2][N3]
+      : data[N2+(N1*(2*Tensor_Dim01-N1-1))/2][N3];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions. */
+
+  template<char i, char j, char k, int Dim01, int Dim2>
+  Tensor3_dg_Expr<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k>
+  operator()(const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+	     const Index<k,Dim2> index3)
+  {
+    return Tensor3_dg_Expr<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim01,Dim2,i,j,k>(*this);
+  }
+
+  template<char i, char j, char k, int Dim01, int Dim2>
+  Tensor3_dg_Expr<const Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+    T,Dim01,Dim2,i,j,k> operator()
+    (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+     const Index<k,Dim2> index3) const
+  {
+    return Tensor3_dg_Expr<const Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim01,Dim2,i,j,k>(*this);
+  }
+
+  /* These operators are for internal contractions. The commented out
+     versions are more general, but are ambiguous.  This means,
+     unfortunately, that you can't do something like A(i,j,j) where i
+     and j have different dimensions. */
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_12<Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,Dim>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const Index<j,Dim> index3) const
+  {
+    typedef const Tensor3_contracted_12<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_02<Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,Dim>,T,Dim,i>
+  operator()(const Index<j,Dim> index1, const Index<i,Dim> index2,
+	     const Index<j,Dim> index3) const
+  {
+    typedef const Tensor3_contracted_02<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+//    template<char i, char j, int Dim0, int Dim12>
+//    inline Tensor1_Expr<const Tensor3_contracted_12<Tensor3_dg
+//    <T*,Tensor_Dim01,Tensor_Dim2>,T,Dim12>,T,Dim0,i>
+//    operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+//  	     const Index<j,Dim12> index3) const
+//    {
+//      typedef const Tensor3_contracted_12<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+//        T,Dim12> TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim0,i>(TensorExpr(*this));
+//    }
+
+//    template<char i, char j, int Dim02, int Dim1>
+//    inline Tensor1_Expr<const Tensor3_contracted_02<Tensor3_dg
+//    <T*,Tensor_Dim01,Tensor_Dim2>,T,Dim02>,T,Dim1,i>
+//    operator()(const Index<j,Dim02> index1, const Index<i,Dim1> index2,
+//  	     const Index<j,Dim02> index3) const
+//    {
+//      typedef const Tensor3_contracted_02<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+//        T,Dim02> TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim1,i>(TensorExpr(*this));
+//    }
+
+  template<char i, char j, int Dim01, int Dim2>
+  inline Tensor1_Expr<const Tensor3_contracted_01<Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,Dim01>,T,Dim2,i>
+  operator()(const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+	     const Index<i,Dim2> index3) const
+  {
+    typedef const Tensor3_contracted_01<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim01> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim2,i>(TensorExpr(*this));
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     indices for the others, yielding a Tensor2_Expr or
+     Tensor2_symmetric_Expr.  The non-const versions don't actually
+     create a Tensor3_dg_number_rhs_* object, while the const versions
+     do create a Tensor3_dg_number_*. */
+
+  /* First slot. */
+
+  template<char i, char j, int N, int Dim1, int Dim2>
+  Tensor2_Expr<Tensor3_dg_number_rhs_0<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+    T,N>,T,Dim1,Dim2,i,j>
+  operator()(const Number<N> n1, const Index<i,Dim1> index1,
+	     const Index<j,Dim2> index2)
+  {
+    typedef Tensor3_dg_number_rhs_0<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,T,N>
+      TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim1,Dim2,i,j>(*this);
+  }
+
+  template<char i, char j, int N, int Dim1, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_number_0<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim1,Dim2,i,j>
+  operator()(const Number<N> n1, const Index<i,Dim1> index1,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_number_0<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim1,Dim2,i,j>(TensorExpr(*this));
+  }
+
+  /* Second slot. */
+
+  template<char i, char j, int N, int Dim0, int Dim2>
+  Tensor2_Expr<Tensor3_dg_number_rhs_0<Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const Number<N> n1,
+	     const Index<j,Dim2> index2)
+  {
+    typedef Tensor3_dg_number_rhs_0<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,T,N>
+      TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(*this);
+  }
+
+  template<char i, char j, int N, int Dim0, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_number_0<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const Number<N> n1,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_number_0<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this));
+  }
+
+  /* Third slot. */
+
+  template<char i, char j, int N, int Dim>
+  Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const Number<N> n1)
+  {
+    typedef Tensor3_dg_number_rhs_2<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,T,N>
+      TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(*this);
+  }
+
+  template<char i, char j, int N, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor3_dg_number_2
+  <const Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const Number<N> n1) const
+  {
+    typedef const Tensor3_dg_number_2<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this));
+  }
+
+  /* This is for expressions where a number is used for two slots, and
+     an Index for the other, yielding a Tensor1_Expr.  The non-const
+     versions don't actually create a Tensor3_dg_number_rhs_* object,
+     while the const versions do create a Tensor3_dg_number_*. */
+
+  /* Index in first slot. */
+
+  template<char i, int N1, int N2, int Dim>
+  Tensor1_Expr<Tensor3_dg_number_rhs_12<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+    T,N1,N2>,T,Dim,i>
+  operator()(const Index<i,Dim> index, const Number<N1> n1,
+	     const Number<N2> n2)
+  {
+    typedef Tensor3_dg_number_rhs_12<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N1, int N2, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_number_12<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Index<i,Dim> index, const Number<N1> n1,
+	     const Number<N2> n2) const
+  {
+    typedef const Tensor3_dg_number_12<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Index in second slot.  I use the same structures as for the Index
+     in the first slot since the tensor is symmetric on the first two
+     indices. */
+
+  template<char i, int N1, int N2, int Dim>
+  Tensor1_Expr<Tensor3_dg_number_rhs_12<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+    T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Index<i,Dim> index,
+	     const Number<N2> n2)
+  {
+    typedef Tensor3_dg_number_rhs_12<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N1, int N2, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_number_12<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Index<i,Dim> index,
+	     const Number<N2> n2) const
+  {
+    typedef const Tensor3_dg_number_12<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Index in third slot. */
+
+  template<char i, int N1, int N2, int Dim>
+  Tensor1_Expr<Tensor3_dg_number_rhs_01<Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Number<N2> n2,
+	     const Index<i,Dim> index)
+  {
+    typedef Tensor3_dg_number_rhs_01<Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,
+      T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N1, int N2, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_number_01<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Number<N2> n2,
+	     const Index<i,Dim> index) const
+  {
+    typedef const Tensor3_dg_number_01<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Specializations for using actual numbers instead of Number<>.
+     This is for expressions where an actual number is used for one
+     slot, and indices for the others, yielding a Tensor2_Expr or
+     Tensor2_symmetric_Expr. I only define the const versions. */
+
+  /* First slot. */
+
+  template<char i, char j, int Dim1, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_numeral_0<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim1,Dim2,i,j>
+  operator()(const int N, const Index<i,Dim1> index1,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_numeral_0<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim1,Dim2,i,j>(TensorExpr(*this,N));
+  }
+
+  /* Second slot. */
+
+  template<char i, char j, int Dim0, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_numeral_0<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const int N,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_numeral_0<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this,N));
+  }
+
+  /* Third slot. */
+
+  template<char i, char j, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor3_dg_numeral_2
+  <const Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const int N) const
+  {
+    typedef const Tensor3_dg_numeral_2<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this,N));
+  }
+
+  /* This is for expressions where a numeral is used for two slots, and
+     an Index for the other, yielding a Tensor1_Expr. */
+
+  /* Index in first slot. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_numeral_12<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i>
+  operator()(const Index<i,Dim> index, const int N1,
+	     const int N2) const
+  {
+    typedef const Tensor3_dg_numeral_12<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+  }
+
+  /* Index in second slot.  I use the same structures as for the Index
+     in the first slot since the tensor is symmetric on the first two
+     indices. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_numeral_12<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i>
+  operator()(const int N1, const Index<i,Dim> index,
+	     const int N2) const
+  {
+    typedef const Tensor3_dg_numeral_12<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+  }
+
+  /* Index in third slot. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_numeral_01<const Tensor3_dg
+  <T*,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i>
+  operator()(const int N1, const int N2,
+	     const Index<i,Dim> index) const
+  {
+    typedef const Tensor3_dg_numeral_01<const Tensor3_dg
+      <T*,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+  }
+  
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+
+  const Tensor3_dg<T*,Tensor_Dim01,Tensor_Dim2> & operator++() const
+  {
+    for(int i=0;i<(Tensor_Dim01*(Tensor_Dim01+1))/2;++i)
+      for(int j=0;j<Tensor_Dim2;++j)
+	++data[i][j];
+    return *this;
+  }
+};
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_times_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_times_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,182 @@
+/* This file has all of the declarations for expressions like
+   Tensor3_dg*Tensor1 and Tensor1*Tensor3_dg, yielding a
+   Tensor2_symmetric or Tensor2. */
+
+/* A(i,j,k)*B(k)->Tensor2_symmetric */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor1_2
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor1_Expr<B,U,Dim2,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,N2,Current_Dim-1)*iterB(Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,N2,0)*iterB(0);
+  }
+public:
+  Tensor3_dg_times_Tensor1_2(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			     const Tensor1_Expr<B,U,Dim2,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor3_dg_times_Tensor1_2<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor1_Expr<B,U,Dim2,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor1_2<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(k)*A(i,j,k)->Tensor2_symmetric */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+inline const Tensor2_symmetric_Expr
+<const Tensor3_dg_times_Tensor1_2<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor1_Expr<B,U,Dim2,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor1_2<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,k,j)*B(k)->Tensor2 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor1_1
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,k,j> iterA;
+  const Tensor1_Expr<B,U,Dim01,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,Current_Dim-1,N2)*iterB(Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,0,N2)*iterB(0);
+  }
+public:
+  Tensor3_dg_times_Tensor1_1(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,k,j> &a,
+			     const Tensor1_Expr<B,U,Dim01,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor3_dg_times_Tensor1_1<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,k,j> &a,
+	  const Tensor1_Expr<B,U,Dim01,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor1_1<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(k)*A(i,k,j)->Tensor2 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor3_dg_times_Tensor1_1<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j>
+operator*(const Tensor1_Expr<B,U,Dim01,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,k,j> &a)
+{
+  typedef const Tensor3_dg_times_Tensor1_1<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(k,i,j)*B(k)->Tensor2 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor1_0
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> iterA;
+  const Tensor1_Expr<B,U,Dim01,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,Current_Dim-1,N2)*iterB(Current_Dim-1)
+      + eval(N1,N2,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,0,N2)*iterB(0);
+  }
+public:
+  Tensor3_dg_times_Tensor1_0(const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> &a,
+			     const Tensor1_Expr<B,U,Dim01,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor3_dg_times_Tensor1_0<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> &a,
+	  const Tensor1_Expr<B,U,Dim01,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor1_0<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(k)*A(k,i,j)->Tensor2 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, 
+  char i, char j, char k>
+inline const Tensor2_Expr<const Tensor3_dg_times_Tensor1_0<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j>
+operator*(const Tensor1_Expr<B,U,Dim01,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> &a)
+{
+  typedef const Tensor3_dg_times_Tensor1_0<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_times_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_times_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,668 @@
+/* This file has all of the declarations for expressions like
+   Tensor3_dg*Tensor2 and Tensor2*Tensor3_dg, yielding a
+   Tensor3_dg, Tensor3, or Tensor1. */
+
+/* A(i,j,k)*B(k,l)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_0
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,N2,Current_Dim-1)*iterB(Current_Dim-1,N3)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,N2,0)*iterB(0,N3);
+  }
+public:
+  Tensor3_dg_times_Tensor2_0(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			     const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l)*A(i,j,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+operator*(const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(l,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_1
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim3,Dim2,l,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,N2,Current_Dim-1)*iterB(N3,Current_Dim-1)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,N2,0)*iterB(N3,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_1(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			     const Tensor2_Expr<B,U,Dim3,Dim2,l,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim3,Dim2,l,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(l,k)*A(i,j,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+operator*(const Tensor2_Expr<B,U,Dim3,Dim2,l,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim3,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(j,l)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_1_0
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim01,Dim3,j,l> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,Current_Dim-1,N2)*iterB(Current_Dim-1,N3)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,0,N2)*iterB(0,N3);
+  }
+public:
+  Tensor3_dg_times_Tensor2_1_0(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			       const Tensor2_Expr<B,U,Dim01,Dim3,j,l> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_1_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim01,Dim3,j,l> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_1_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(j,l)*A(i,j,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_1_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+operator*(const Tensor2_Expr<B,U,Dim01,Dim3,j,l> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_1_0<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(l,j)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_1_1
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim3,Dim01,l,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,Current_Dim-1,N2)*iterB(N3,Current_Dim-1)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,0,N2)*iterB(N3,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_1_1(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			       const Tensor2_Expr<B,U,Dim3,Dim01,l,j> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_1_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim3,Dim01,l,j> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_1_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(l,j)*A(i,j,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_1_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+operator*(const Tensor2_Expr<B,U,Dim3,Dim01,l,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_1_1<A,B,T,U,Dim01,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim3,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_12
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim01,Dim2,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,0,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_12(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			      const Tensor2_Expr<B,U,Dim01,Dim2,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_12<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim01,Dim2,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_12<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(i,j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_12<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor2_Expr<B,U,Dim01,Dim2,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_12<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(k,j)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_21
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim01,k,j> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(Current_Dim1-1,0)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,0,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_21(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			      const Tensor2_Expr<B,U,Dim2,Dim01,k,j> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_21<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim01,k,j> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_21<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* B(k,j)*A(i,j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_21<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor2_Expr<B,U,Dim2,Dim01,k,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_21<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* A(j,i,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_02
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,i,k> iterA;
+  const Tensor2_Expr<B,U,Dim01,Dim2,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_02(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,i,k> &a,
+			      const Tensor2_Expr<B,U,Dim01,Dim2,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_02<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,i,k> &a,
+	  const Tensor2_Expr<B,U,Dim01,Dim2,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_02<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,i,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_02<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor2_Expr<B,U,Dim01,Dim2,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,i,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_02<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* A(k,i,j)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_20
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim01,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1)*iterB(Current_Dim1-1,0)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_20(const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> &a,
+			      const Tensor2_Expr<B,U,Dim2,Dim01,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_20<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim01,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_20<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(k,i,j)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_20<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,i>
+operator*(const Tensor2_Expr<B,U,Dim2,Dim01,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,k,i,j> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_20<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i>(TensorExpr(a,b));
+}
+
+/* A(j,k,i)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_01
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> iterA;
+  const Tensor2_Expr<B,U,Dim01,Dim01,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,Current_Dim1-1,N1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,Current_Dim1-1,N1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,0,N1)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_01(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+			      const Tensor2_Expr<B,U,Dim01,Dim01,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_01<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+	  const Tensor2_Expr<B,U,Dim01,Dim01,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_01<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,k,i)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_01<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor2_Expr<B,U,Dim01,Dim01,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_01<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* A(j,k,i)*B(k,j)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_10
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> iterA;
+  const Tensor2_Expr<B,U,Dim01,Dim01,k,j> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,Current_Dim1-1,N1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,Current_Dim1-1,N1)*iterB(Current_Dim1-1,0)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,0,N1)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_10(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+			      const Tensor2_Expr<B,U,Dim01,Dim01,k,j> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_10<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+	  const Tensor2_Expr<B,U,Dim01,Dim01,k,j> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_10<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* B(k,j)*A(j,k,i)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_10<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor2_Expr<B,U,Dim01,Dim01,k,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_10<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_times_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_times_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,668 @@
+/* This file has all of the declarations for expressions like
+   Tensor3_dg*Tensor2_symmetric and Tensor2_symmetric*Tensor3_dg,
+   yielding a Tensor3_dg, Tensor3, or Tensor1. */
+
+/* A(i,j,k)*B(k,l)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_symmetric_0
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim2,k,l> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,N2,Current_Dim-1)*iterB(Current_Dim-1,N3)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,N2,0)*iterB(0,N3);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_0(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			     const Tensor2_symmetric_Expr<B,U,Dim2,k,l> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_0<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim2,k,l> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_0<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l)*A(i,j,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_0<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim2,k,l> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_0<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(l,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_symmetric_1
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim2,l,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,N2,Current_Dim-1)*iterB(N3,Current_Dim-1)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,N2,0)*iterB(N3,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_1(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			     const Tensor2_symmetric_Expr<B,U,Dim2,l,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_1<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim2,l,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_1<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(l,k)*A(i,j,k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_1<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim2,l,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_1<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(j,l)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_symmetric_1_0
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,j,l> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,Current_Dim-1,N2)*iterB(Current_Dim-1,N3)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,0,N2)*iterB(0,N3);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_1_0(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			       const Tensor2_symmetric_Expr<B,U,Dim01,j,l> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_1_0<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,j,l> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_1_0<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(j,l)*A(i,j,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_1_0<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim01,j,l> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_1_0<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(l,j)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor2_symmetric_1_1
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,l,j> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,Current_Dim-1,N2)*iterB(N3,Current_Dim-1)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,0,N2)*iterB(N3,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_1_1(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			       const Tensor2_symmetric_Expr<B,U,Dim01,l,j> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_1_1<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,l,j> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_1_1<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(l,j)*A(i,j,k)->Tensor3 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor3_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_1_1<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim01,l,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_1_1<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor3_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,Dim01,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_symmetric_12
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,0,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_12(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+			      const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_12<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_12<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(i,j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_12<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_12<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(k,j)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_symmetric_21
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,k,j> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(Current_Dim1-1,0)
+      + eval(N1,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,0,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_21(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+			      const Tensor2_symmetric_Expr<B,U,Dim,k,j> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_21<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,k,j> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_21<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* B(k,j)*A(i,j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_21<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,k,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim,Dim,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_21<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* A(j,i,k)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_symmetric_02
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,j,i,k> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_02(const Tensor3_dg_Expr<A,T,Dim,Dim,j,i,k> &a,
+			      const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_02<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim,Dim,j,i,k> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_02<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,i,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_02<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim,Dim,j,i,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_02<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* A(k,i,j)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_symmetric_20
+{
+  const Tensor3_dg_Expr<A,T,Dim,Dim,k,i,j> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1)*iterB(Current_Dim1-1,0)
+      + eval(N1,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_20(const Tensor3_dg_Expr<A,T,Dim,Dim,k,i,j> &a,
+			      const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_20<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim,Dim,k,i,j> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_20<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(k,i,j)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_20<A,B,T,U,Dim,i,j,k>,
+  typename promote<T,U>::V,Dim,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim,Dim,k,i,j> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_20<A,B,T,U,Dim,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim,i>(TensorExpr(a,b));
+}
+
+/* A(j,k,i)*B(j,k)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_symmetric_01
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,j,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,Current_Dim1-1,N1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,Current_Dim1-1,N1)*iterB(0,Current_Dim1-1)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,0,N1)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_01(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+			      const Tensor2_symmetric_Expr<B,U,Dim01,j,k> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,j,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* B(j,k)*A(j,k,i)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim01,j,k> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* A(j,k,i)*B(k,j)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+class Tensor3_dg_times_Tensor2_symmetric_10
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,k,j> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,Current_Dim1-1,N1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,Current_Dim1-1,N1)*iterB(Current_Dim1-1,0)
+      + eval(N1,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,0,N1)*iterB(0,0);
+  }
+public:
+  Tensor3_dg_times_Tensor2_symmetric_10(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+			      const Tensor2_symmetric_Expr<B,U,Dim01,k,j> &b)
+    : iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1) const
+  {
+    return eval(N1,Number<Dim01>(),Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_10<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,k,j> &b)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_10<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
+/* B(k,j)*A(j,k,i)->Tensor1 */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k>
+inline const Tensor1_Expr
+<const Tensor3_dg_times_Tensor2_symmetric_10<A,B,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim2,i>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim01,k,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,j,k,i> &a)
+{
+  typedef const Tensor3_dg_times_Tensor2_symmetric_10<A,B,T,U,Dim01,Dim2,i,j,k>
+    TensorExpr;
+  return Tensor1_Expr<TensorExpr,typename promote<T,U>::V,Dim2,i>(TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_times_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_times_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,192 @@
+/* This file has all of the declarations for expressions like
+   Tensor3_dg*Tensor3_dg yielding a Tensor2 or Tensor4_ddg. */
+
+/* A(i,j,k)*B(j,k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor3_dg_12_01
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim01,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim01,Dim2,j,k,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1) const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1,N2)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1) const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(0,Current_Dim1-1,N2)
+      + eval(N1,N2,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0, const Number<1> &ND1) const
+  {
+    return iterA(N1,0,0)*iterB(0,0,N2);
+  }
+public:
+  Tensor3_dg_times_Tensor3_dg_12_01
+  (const Tensor3_dg_Expr<A,T,Dim01,Dim01,i,j,k> &a,
+   const Tensor3_dg_Expr<B,U,Dim01,Dim2,j,k,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim01>(),Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor2_Expr
+<const Tensor3_dg_times_Tensor3_dg_12_01<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim01,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim01,Dim2,j,k,l> &b)
+{
+  typedef const Tensor3_dg_times_Tensor3_dg_12_01<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,l>
+    (TensorExpr(a,b));
+}
+
+/* B(j,k,l)*A(i,j,k) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor2_Expr
+<const Tensor3_dg_times_Tensor3_dg_12_01<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,l>
+operator*(const Tensor3_dg_Expr<B,U,Dim01,Dim2,j,k,l> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim01,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor3_dg_12_01<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(k,l,j) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+class Tensor3_dg_times_Tensor3_dg_12_20
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim2,Dim01,k,l,j> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1) const
+  {
+    return iterA(N1,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim1-1,N2,Current_Dim0-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1) const
+  {
+    return iterA(N1,0,Current_Dim1-1)*iterB(Current_Dim1-1,N2,0)
+      + eval(N1,N2,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0, const Number<1> &ND1) const
+  {
+    return iterA(N1,0,0)*iterB(0,N2,0);
+  }
+public:
+  Tensor3_dg_times_Tensor3_dg_12_20
+  (const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+   const Tensor3_dg_Expr<B,U,Dim2,Dim01,k,l,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim01>(),Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor2_Expr
+<const Tensor3_dg_times_Tensor3_dg_12_20<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,l>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim2,Dim01,k,l,j> &b)
+{
+  typedef const Tensor3_dg_times_Tensor3_dg_12_20<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l,j)*A(i,j,k) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim2,
+  char i, char j, char k, char l>
+inline const Tensor2_Expr
+<const Tensor3_dg_times_Tensor3_dg_12_20<A,B,T,U,Dim01,Dim2,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim2,i,l>
+operator*(const Tensor3_dg_Expr<B,U,Dim2,Dim01,k,l,j> &b,
+	  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_Tensor3_dg_12_20<A,B,T,U,Dim01,Dim2,i,j,k,l>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k)*B(l,m,k) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23, int Dim2,
+  char i, char j, char k, char l, char m>
+class Tensor3_dg_times_Tensor3_dg_2
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const Tensor3_dg_Expr<B,U,Dim23,Dim2,l,m,k> iterB;
+
+  template<int Current_Dim0>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3, const int N4,
+		       const Number<Current_Dim0> &ND0) const
+  {
+    return iterA(N1,N2,Current_Dim0-1)*iterB(N3,N4,Current_Dim0-1)
+      + eval(N1,N2,N3,N4,Number<Current_Dim0-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3, const int N4,
+		       const Number<1> &ND0) const
+  {
+    return iterA(N1,N2,0)*iterB(N3,N4,0);
+  }
+public:
+  Tensor3_dg_times_Tensor3_dg_2
+  (const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+   const Tensor3_dg_Expr<B,U,Dim23,Dim2,l,m,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			  const int N4) const
+  {
+    return eval(N1,N2,N3,N4,Number<Dim2>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23, int Dim2,
+  char i, char j, char k, char l, char m>
+inline const Tensor4_ddg_Expr
+<const Tensor3_dg_times_Tensor3_dg_2<A,B,T,U,Dim01,Dim23,Dim2,i,j,k,l,m>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,l,m>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+	  const Tensor3_dg_Expr<B,U,Dim23,Dim2,l,m,k> &b)
+{
+  typedef const Tensor3_dg_times_Tensor3_dg_2
+    <A,B,T,U,Dim01,Dim23,Dim2,i,j,k,l,m> TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,l,m>
+    (TensorExpr(a,b));
+}
+
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_times_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_times_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+/* Multiplies a Tensor3_dg with a generic, yielding a Tensor3_dg. */
+
+template<class A, class T, class U, int Dim01, int Dim2, char i, char j,char k>
+class Tensor3_dg_times_generic
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3)*d;
+  }
+
+  Tensor3_dg_times_generic(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a,
+			   const U &d0): iterA(a), d(d0) {}
+};
+
+/* A(i,j,k)*d0->Tensor3_dg */
+
+template<class A, class T, class U, int Dim01, int Dim2, char i, char j,char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_times_generic<A,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator*(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a, const U &d0)
+{
+  typedef const Tensor3_dg_times_generic<A,T,U,Dim01,Dim2,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,d0));
+}
+
+/* d0*A(i,j,k)->Tensor3_dg */
+
+template<class A, class T, class U, int Dim01, int Dim2, char i, char j,char k>
+inline const Tensor3_dg_Expr<const Tensor3_dg_times_generic<A,T,U,Dim01,Dim2,i,j,k>,
+  typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+operator*(const U &d0, const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+  typedef const Tensor3_dg_times_generic<A,T,U,Dim01,Dim2,i,j,k> TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim2,i,j,k>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/Tensor3_dg_value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/Tensor3_dg_value.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,465 @@
+/* A general version, not for pointers. */
+
+template <class T, int Tensor_Dim01, int Tensor_Dim2>
+class Tensor3_dg
+{
+  T data[(Tensor_Dim01*(Tensor_Dim01+1))/2][Tensor_Dim2];
+public:
+  Tensor3_dg() {}
+
+  /* Tensor_Dim01=2, Tensor_Dim2=2 */
+  Tensor3_dg(T d000, T d001, T d010, T d011, T d110, T d111)
+  {
+    Tensor3_dg_constructor<T,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d010,d011,d110,d111);
+  }
+
+  /* Tensor_Dim01=3, Tensor_Dim2=3 */
+  Tensor3_dg(T d000, T d001, T d002, T d010,
+	     T d011, T d012, T d020, T d021,
+	     T d022, T d110, T d111, T d112,
+	     T d120, T d121, T d122,
+	     T d220, T d221, T d222)
+  {
+    Tensor3_dg_constructor<T,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d002,d010,d011,d012,d020,d021,
+       d022,d110,d111,d112,d120,d121,d122,d220,d221,d222);
+  }
+
+  /* Tensor_Dim01=4, Tensor_Dim2=4 */
+  Tensor3_dg(T d000, T d001, T d002, T d003,
+	     T d010, T d011, T d012, T d013,
+	     T d020, T d021, T d022, T d023,
+	     T d030, T d031, T d032, T d033,
+	     T d110, T d111, T d112, T d113,
+	     T d120, T d121, T d122, T d123,
+	     T d130, T d131, T d132, T d133,
+	     T d220, T d221, T d222, T d223,
+	     T d230, T d231, T d232, T d233,
+	     T d330, T d331, T d332, T d333)
+  {
+    Tensor3_dg_constructor<T,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d002,d003,d010,d011,d012,d013,
+       d020,d021,d022,d023,d030,d031,d032,d033,
+       d110,d111,d112,d113,d120,d121,d122,d123,
+       d130,d131,d132,d133,d220,d221,d222,d223,
+       d230,d231,d232,d233,d330,d331,d332,d333);
+  }
+
+  /* Tensor_Dim01=4, Tensor_Dim2=3 */
+  Tensor3_dg(T d000, T d001, T d002, T d010, T d011, T d012,
+	     T d020, T d021, T d022, T d030, T d031, T d032,
+	     T d110, T d111, T d112, T d120, T d121, T d122,
+	     T d130, T d131, T d132, T d220, T d221, T d222,
+	     T d230, T d231, T d232, T d330, T d331, T d332)
+  {
+    Tensor3_dg_constructor<T,Tensor_Dim01,Tensor_Dim2>
+      (data,d000,d001,d002,d010,d011,d012,
+       d020,d021,d022,d030,d031,d032,
+       d110,d111,d112,d120,d121,d122,
+       d130,d131,d132,d220,d221,d222,
+       d230,d231,d232,d330,d331,d332);
+  }
+
+  /* There are two operator(int,int,int)'s, one for non-consts that lets you
+     change the value, and one for consts that doesn't. */
+
+  T & operator()(const int N1, const int N2, const int N3)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0
+       || N2>=Tensor_Dim01 || N2<0 || N3>=Tensor_Dim2 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T,"
+		  << Tensor_Dim01 << "," << Tensor_Dim2 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ")" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? data[N1+(N2*(2*Tensor_Dim01-N2-1))/2][N3]
+      : data[N2+(N1*(2*Tensor_Dim01-N1-1))/2][N3];
+  }
+
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0
+       || N2>=Tensor_Dim01 || N2<0 || N3>=Tensor_Dim2 || N3<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T,"
+		  << Tensor_Dim01 << "," << Tensor_Dim2 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << ") const" << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? data[N1+(N2*(2*Tensor_Dim01-N2-1))/2][N3]
+      : data[N2+(N1*(2*Tensor_Dim01-N1-1))/2][N3];
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions. */
+
+  template<char i, char j, char k, int Dim01, int Dim2>
+  Tensor3_dg_Expr<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,Dim01,Dim2,i,j,k>
+  operator()(const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+	     const Index<k,Dim2> index3)
+  {
+    return Tensor3_dg_Expr<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim01,Dim2,i,j,k>(*this);
+  }
+
+  template<char i, char j, char k, int Dim01, int Dim2>
+  Tensor3_dg_Expr<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,Dim01,Dim2,i,j,k> operator()
+    (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+     const Index<k,Dim2> index3) const
+  {
+    return Tensor3_dg_Expr<const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim01,Dim2,i,j,k>(*this);
+  }
+
+  /* These operators are for internal contractions. The commented out
+     versions are more general, but are ambiguous.  This means,
+     unfortunately, that you can't do something like A(i,j,j) where i
+     and j have different dimensions. */
+
+  /* A(i,j,j) */
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_12<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,Dim>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const Index<j,Dim> index3) const
+  {
+    typedef const Tensor3_contracted_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_12<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,Dim>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const Index<j,Dim> index3)
+  {
+    typedef const Tensor3_contracted_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+//    template<char i, char j, int Dim0, int Dim12>
+//    inline Tensor1_Expr<const Tensor3_contracted_12<Tensor3_dg
+//    <T,Tensor_Dim01,Tensor_Dim2>,T,Dim12>,T,Dim0,i>
+//    operator()(const Index<i,Dim0> index1, const Index<j,Dim12> index2,
+//  	     const Index<j,Dim12> index3) const
+//    {
+//      typedef const Tensor3_contracted_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+//        T,Dim12> TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim0,i>(TensorExpr(*this));
+//    }
+
+  /* A(j,i,j) */
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_02<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,Dim>,T,Dim,i>
+  operator()(const Index<j,Dim> index1, const Index<i,Dim> index2,
+	     const Index<j,Dim> index3) const
+  {
+    typedef const Tensor3_contracted_02<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim>
+  inline Tensor1_Expr<const Tensor3_contracted_02<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,Dim>,T,Dim,i>
+  operator()(const Index<j,Dim> index1, const Index<i,Dim> index2,
+	     const Index<j,Dim> index3)
+  {
+    typedef const Tensor3_contracted_02<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+//    template<char i, char j, int Dim02, int Dim1>
+//    inline Tensor1_Expr<const Tensor3_contracted_02<Tensor3_dg
+//    <T,Tensor_Dim01,Tensor_Dim2>,T,Dim02>,T,Dim1,i>
+//    operator()(const Index<j,Dim02> index1, const Index<i,Dim1> index2,
+//  	     const Index<j,Dim02> index3) const
+//    {
+//      typedef const Tensor3_contracted_02<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+//        T,Dim02> TensorExpr;
+//      return Tensor1_Expr<TensorExpr,T,Dim1,i>(TensorExpr(*this));
+//    }
+
+  /* A(j,j,i) */
+
+  template<char i, char j, int Dim01, int Dim2>
+  inline Tensor1_Expr<const Tensor3_contracted_01<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,Dim01>,T,Dim2,i>
+  operator()(const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+	     const Index<i,Dim2> index3) const
+  {
+    typedef const Tensor3_contracted_01<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim01> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim2,i>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int Dim01, int Dim2>
+  inline Tensor1_Expr<const Tensor3_contracted_01<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,Dim01>,T,Dim2,i>
+  operator()(const Index<j,Dim01> index1, const Index<j,Dim01> index2,
+	     const Index<i,Dim2> index3)
+  {
+    typedef const Tensor3_contracted_01<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,Dim01> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim2,i>(TensorExpr(*this));
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     indices for the others, yielding a Tensor2_Expr or
+     Tensor2_symmetric_Expr.  The non-const versions don't actually
+     create a Tensor3_dg_number_rhs_* object, while the const versions
+     do create a Tensor3_dg_number_*. */
+
+  /* First slot. */
+
+  template<char i, char j, int N, int Dim1, int Dim2>
+  Tensor2_Expr<Tensor3_dg_number_rhs_0<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,N>,T,Dim1,Dim2,i,j>
+  operator()(const Number<N> n1, const Index<i,Dim1> index1,
+	     const Index<j,Dim2> index2)
+  {
+    typedef Tensor3_dg_number_rhs_0<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>
+      TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim1,Dim2,i,j>(*this);
+  }
+
+  template<char i, char j, int N, int Dim1, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_number_0<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim1,Dim2,i,j>
+  operator()(const Number<N> n1, const Index<i,Dim1> index1,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_number_0<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim1,Dim2,i,j>(TensorExpr(*this));
+  }
+
+  /* Second slot. */
+
+  template<char i, char j, int N, int Dim0, int Dim2>
+  Tensor2_Expr<Tensor3_dg_number_rhs_0<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const Number<N> n1,
+	     const Index<j,Dim2> index2)
+  {
+    typedef Tensor3_dg_number_rhs_0<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>
+      TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(*this);
+  }
+
+  template<char i, char j, int N, int Dim0, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_number_0<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const Number<N> n1,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_number_0<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this));
+  }
+
+  /* Third slot. */
+
+  template<char i, char j, int N, int Dim>
+  Tensor2_symmetric_Expr<Tensor3_dg_number_rhs_2<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const Number<N> n1)
+  {
+    typedef Tensor3_dg_number_rhs_2<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>
+      TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(*this);
+  }
+
+  template<char i, char j, int N, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor3_dg_number_2
+  <const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T,N>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const Number<N> n1) const
+  {
+    typedef const Tensor3_dg_number_2<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T,N> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this));
+  }
+
+  /* This is for expressions where a number is used for two slots, and
+     an Index for the other, yielding a Tensor1_Expr.  The non-const
+     versions don't actually create a Tensor3_dg_number_rhs_* object,
+     while the const versions do create a Tensor3_dg_number_*. */
+
+  /* Index in first slot. */
+
+  template<char i, int N1, int N2, int Dim>
+  Tensor1_Expr<Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,N1,N2>,T,Dim,i>
+  operator()(const Index<i,Dim> index, const Number<N1> n1,
+	     const Number<N2> n2)
+  {
+    typedef Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N1, int N2, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_number_12<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Index<i,Dim> index, const Number<N1> n1,
+	     const Number<N2> n2) const
+  {
+    typedef const Tensor3_dg_number_12<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Index in second slot.  I use the same structures as for the Index
+     in the first slot since the tensor is symmetric on the first two
+     indices. */
+
+  template<char i, int N1, int N2, int Dim>
+  Tensor1_Expr<Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+    T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Index<i,Dim> index,
+	     const Number<N2> n2)
+  {
+    typedef Tensor3_dg_number_rhs_12<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N1, int N2, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_number_12<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Index<i,Dim> index,
+	     const Number<N2> n2) const
+  {
+    typedef const Tensor3_dg_number_12<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Index in third slot. */
+
+  template<char i, int N1, int N2, int Dim>
+  Tensor1_Expr<Tensor3_dg_number_rhs_01<Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Number<N2> n2,
+	     const Index<i,Dim> index)
+  {
+    typedef Tensor3_dg_number_rhs_01<Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,
+      T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(*this);
+  }
+
+  template<char i, int N1, int N2, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_number_01<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2>,T,Dim,i>
+  operator()(const Number<N1> n1, const Number<N2> n2,
+	     const Index<i,Dim> index) const
+  {
+    typedef const Tensor3_dg_number_01<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T,N1,N2> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this));
+  }
+
+  /* Specializations for using actual numbers instead of Number<>.
+     This is for expressions where an actual number is used for one
+     slot, and indices for the others, yielding a Tensor2_Expr or
+     Tensor2_symmetric_Expr. I only define the const versions. */
+
+  /* First slot. */
+
+  template<char i, char j, int Dim1, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_numeral_0<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim1,Dim2,i,j>
+  operator()(const int N, const Index<i,Dim1> index1,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_numeral_0<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim1,Dim2,i,j>(TensorExpr(*this,N));
+  }
+
+  /* Second slot. */
+
+  template<char i, char j, int Dim0, int Dim2>
+  const Tensor2_Expr<const Tensor3_dg_numeral_0<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim0,Dim2,i,j>
+  operator()(const Index<i,Dim0> index1, const int N,
+	     const Index<j,Dim2> index2) const
+  {
+    typedef const Tensor3_dg_numeral_0<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim0,Dim2,i,j>(TensorExpr(*this,N));
+  }
+
+  /* Third slot. */
+
+  template<char i, char j, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor3_dg_numeral_2
+  <const Tensor3_dg<T,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const int N) const
+  {
+    typedef const Tensor3_dg_numeral_2<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this,N));
+  }
+
+  /* This is for expressions where a numeral is used for two slots, and
+     an Index for the other, yielding a Tensor1_Expr. */
+
+  /* Index in first slot. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_numeral_12<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i>
+  operator()(const Index<i,Dim> index, const int N1,
+	     const int N2) const
+  {
+    typedef const Tensor3_dg_numeral_12<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+  }
+
+  /* Index in second slot.  I use the same structures as for the Index
+     in the first slot since the tensor is symmetric on the first two
+     indices. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_numeral_12<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i>
+  operator()(const int N1, const Index<i,Dim> index,
+	     const int N2) const
+  {
+    typedef const Tensor3_dg_numeral_12<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+  }
+
+  /* Index in third slot. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor3_dg_numeral_01<const Tensor3_dg
+  <T,Tensor_Dim01,Tensor_Dim2>,T>,T,Dim,i>
+  operator()(const int N1, const int N2,
+	     const Index<i,Dim> index) const
+  {
+    typedef const Tensor3_dg_numeral_01<const Tensor3_dg
+      <T,Tensor_Dim01,Tensor_Dim2>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2));
+  }
+};
+
diff -r 000000000000 -r 34fc4fd9248b Tensor3_dg/minus_Tensor3_dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor3_dg/minus_Tensor3_dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,24 @@
+/* Unary minus operator. */
+
+template<class A, class T, int Dim01, int Dim2, char i, char j, char k>
+class minus_Tensor3_dg
+{
+  const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> iterA;
+public:
+  T operator()(const int N1, const int N2, const int N3) const
+  {
+    return -iterA(N1,N2,N3);
+  }
+
+  minus_Tensor3_dg(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a): iterA(a) {}
+};
+
+template<class A, class T, int Dim01, int Dim2, char i, char j, char k>
+inline const Tensor3_dg_Expr<const minus_Tensor3_dg<A,T,Dim01,Dim2,i,j,k>,
+  T,Dim01,Dim2,i,j,k>
+operator-(const Tensor3_dg_Expr<A,T,Dim01,Dim2,i,j,k> &a)
+{
+    typedef const minus_Tensor3_dg<A,T,Dim01,Dim2,i,j,k> TensorExpr;
+    return Tensor3_dg_Expr<TensorExpr,T,Dim01,Dim2,i,j,k>(TensorExpr(a));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4/Tensor4_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4/Tensor4_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,19 @@
+/* Declare a wrapper class for generic rank 4 Tensor expressions. */
+
+#include "Tensor4_plus_Tensor4.h"
+#include "Tensor4_times_Tensor2_symmetric.h"
+#include "Tensor4_times_Tensor2.h"
+
+template<class A, class T, int Dim0, int Dim1, int Dim2, int Dim3,
+  char i, char j, char k, char l>
+class Tensor4_Expr
+{
+  A iter;
+public:
+  Tensor4_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3,
+	       const int N4) const
+  {
+    return iter(N1,N2,N3,N4);
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor4/Tensor4_minus_Tensor4.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4/Tensor4_minus_Tensor4.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,28 @@
+//  /* Subtracts a Tensor4 from a Tensor4, yielding a Tensor4_Riemann
+//     (definitely not a general purpose subtraction routine). */
+
+//  template<class A, class B, char i, char j, char k, char l>
+//  class Tensor4_minus_Tensor4
+//  {
+//    Tensor4_Expr<A,i,j,k,l> iterA;
+//    Tensor4_Expr<B,i,l,k,j> iterB;
+//  public:
+//    double operator()(const int N1, const int N2, const int N3,
+//  			  const int N4) const
+//    {
+//      return iterA(N2,N3,N1,N4)-iterB(N2,N4,N1,N3);
+//    }
+//    Tensor4_minus_Tensor4(const Tensor4_Expr<A,i,j,k,l> &a,
+//  			const Tensor4_Expr<B,i,l,k,j> &b):
+//      iterA(a), iterB(b) {}
+//  };
+
+//  template<class A, class B, char i, char j, char k, char l>
+//  inline Tensor4_Riemann_Expr<const Tensor4_minus_Tensor4
+//  <const Tensor4_Expr<A,i,j,k,l>, const Tensor4_Expr<B,i,l,k,j>,i,j,k,l>,k,i,j,l>
+//  operator-(const Tensor4_Expr<A,i,j,k,l> &a, const Tensor4_Expr<B,i,l,k,j> &b)
+//  {
+//    typedef const Tensor4_minus_Tensor4<const Tensor4_Expr<A,i,j,k,l>,
+//      const Tensor4_Expr<B,i,l,k,j>,i,j,k,l> TensorExpr;
+//    return Tensor4_Riemann_Expr<TensorExpr,k,i,j,l>(TensorExpr(a,b));
+//  }
diff -r 000000000000 -r 34fc4fd9248b Tensor4/Tensor4_plus_Tensor4.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4/Tensor4_plus_Tensor4.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,70 @@
+/* Adds Tensor4+Tensor4 -> Tensor4 */
+
+/* A(i,j,k,l)+B(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor4_plus_Tensor4
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> iterA;
+  const Tensor4_Expr<B,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+		    const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)+iterB(N1,N2,N3,N4);
+  }
+
+  Tensor4_plus_Tensor4(const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+		       const Tensor4_Expr<B,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor4_Expr
+<const Tensor4_plus_Tensor4<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+operator+(const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+	  const Tensor4_Expr<B,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &b)
+{
+  typedef const Tensor4_plus_Tensor4<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)+B(l,k,i,j) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor4_plus_Tensor4_3201
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> iterA;
+  const Tensor4_Expr<B,U,Dim2,Dim3,Dim0,Dim1,l,k,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+		    const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)+iterB(N4,N3,N1,N2);
+  }
+
+  Tensor4_plus_Tensor4_3201
+  (const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+   const Tensor4_Expr<B,U,Dim2,Dim3,Dim0,Dim1,l,k,i,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor4_Expr
+<const Tensor4_plus_Tensor4_3201<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+operator+(const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+	  const Tensor4_Expr<B,U,Dim2,Dim3,Dim0,Dim1,l,k,i,j> &b)
+{
+  typedef const Tensor4_plus_Tensor4_3201<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,Dim2,Dim3,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4/Tensor4_times_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4/Tensor4_times_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,296 @@
+/* This file has all of the declarations for expressions like
+   Tensor4*Tensor2 and Tensor2*Tensor4, yielding a
+   Tensor2. */
+
+/* A(i,j,k,l)*B(k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor4_times_Tensor2_23
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> iterA;
+  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim2>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,N2,0,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim2>(),Number<Dim3>());
+  }
+
+  Tensor4_times_Tensor2_23
+  (const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+   const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_23<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+	  const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b)
+{
+  typedef const Tensor4_times_Tensor2_23
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_23<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor2_Expr<B,U,Dim2,Dim3,k,l> &b,
+	  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_23
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(l,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor4_times_Tensor2_32
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> iterA;
+  const Tensor2_Expr<B,U,Dim3,Dim2,l,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,0,Current_Dim1-1)*iterB(Current_Dim1-1,0)
+      + eval(N1,N2,Number<Dim2>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,N2,0,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim2>(),Number<Dim3>());
+  }
+
+  Tensor4_times_Tensor2_32
+  (const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+   const Tensor2_Expr<B,U,Dim3,Dim2,l,k> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_32<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+	  const Tensor2_Expr<B,U,Dim3,Dim2,l,k> &b)
+{
+  typedef const Tensor4_times_Tensor2_32
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(l,k)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_32<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor2_Expr<B,U,Dim3,Dim2,l,k> &b,
+	  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_32
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(i,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor4_times_Tensor2_03
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> iterA;
+  const Tensor2_Expr<B,U,Dim0,Dim3,i,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,N2,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,N2,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim0>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,N2,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim0>(),Number<Dim3>());
+  }
+
+  Tensor4_times_Tensor2_03
+  (const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+   const Tensor2_Expr<B,U,Dim0,Dim3,i,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_03<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+	  const Tensor2_Expr<B,U,Dim0,Dim3,i,l> &b)
+{
+  typedef const Tensor4_times_Tensor2_03
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(i,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_03<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor2_Expr<B,U,Dim0,Dim3,i,l> &b,
+	  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_03
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(l,i) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+class Tensor4_times_Tensor2_30
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> iterA;
+  const Tensor2_Expr<B,U,Dim3,Dim0,l,i> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,N2,Current_Dim1-1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,N2,Current_Dim1-1)*iterB(Current_Dim1-1,0)
+      + eval(N1,N2,Number<Dim0>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,N2,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim0>(),Number<Dim3>());
+  }
+
+  Tensor4_times_Tensor2_30
+  (const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+   const Tensor2_Expr<B,U,Dim3,Dim0,l,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_30<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a,
+	  const Tensor2_Expr<B,U,Dim3,Dim0,l,i> &b)
+{
+  typedef const Tensor4_times_Tensor2_30
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(l,i)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim2,
+  int Dim3, char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_30<A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor2_Expr<B,U,Dim3,Dim0,l,i> &b,
+	  const Tensor4_Expr<A,T,Dim0,Dim1,Dim2,Dim3,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_30
+    <A,B,T,U,Dim0,Dim1,Dim2,Dim3,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4/Tensor4_times_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4/Tensor4_times_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,371 @@
+/* This file has all of the declarations for expressions like
+   Tensor4*Tensor2_symmetric and Tensor2_symmetric*Tensor4, yielding a
+   Tensor2. */
+
+/* A(i,j,k,l)*B(k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_times_Tensor2_symmetric_23
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,k,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,N2,0,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+
+  Tensor4_times_Tensor2_symmetric_23
+  (const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,k,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_23<A,B,T,U,Dim0,Dim1,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,k,l> &b)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_23
+    <A,B,T,U,Dim0,Dim1,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_23<A,B,T,U,Dim0,Dim1,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,k,l> &b,
+	  const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_23
+    <A,B,T,U,Dim0,Dim1,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(l,k) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_times_Tensor2_symmetric_32
+{
+  const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,l,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,N2,0,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+
+  Tensor4_times_Tensor2_symmetric_32
+  (const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,l,k> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_32<A,B,T,U,Dim0,Dim1,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,l,k> &b)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_32
+    <A,B,T,U,Dim0,Dim1,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(l,k)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim0, int Dim1, int Dim,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_32<A,B,T,U,Dim0,Dim1,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim0,Dim1,i,j>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,l,k> &b,
+	  const Tensor4_Expr<A,T,Dim0,Dim1,Dim,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_32
+    <A,B,T,U,Dim0,Dim1,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim0,Dim1,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(i,l) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+class Tensor4_times_Tensor2_symmetric_03
+{
+  const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,i,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,N2,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,N2,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,N2,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+
+  Tensor4_times_Tensor2_symmetric_03
+  (const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,i,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_03<A,B,T,U,Dim1,Dim2,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,i,l> &b)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_03
+    <A,B,T,U,Dim1,Dim2,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(i,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_03<A,B,T,U,Dim1,Dim2,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,i,l> &b,
+	  const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_03
+    <A,B,T,U,Dim1,Dim2,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(l,i) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+class Tensor4_times_Tensor2_symmetric_30
+{
+  const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,l,i> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,N2,Current_Dim1-1)
+      *iterB(Current_Dim1-1,Current_Dim0-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,N2,Current_Dim1-1)*iterB(Current_Dim1-1,0)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,N2,0)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+
+  Tensor4_times_Tensor2_symmetric_30
+  (const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,l,i> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_30<A,B,T,U,Dim1,Dim2,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,l,i> &b)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_30
+    <A,B,T,U,Dim1,Dim2,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(l,i)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_30<A,B,T,U,Dim1,Dim2,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,k>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,l,i> &b,
+	  const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_30
+    <A,B,T,U,Dim1,Dim2,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,k>
+    (TensorExpr(a,b));
+}
+
+
+
+
+/* A(i,j,k,l)*B(i,k) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+class Tensor4_times_Tensor2_symmetric_02
+{
+  const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,i,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1,N2)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1,N2)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0,N2)*iterB(0,0);
+  }
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+
+  Tensor4_times_Tensor2_symmetric_02
+  (const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,i,k> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_02<A,B,T,U,Dim1,Dim2,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,l>
+operator*(const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,i,k> &b)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_02
+    <A,B,T,U,Dim1,Dim2,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(i,k)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim, int Dim1, int Dim2,
+  char i, char j, char k, char l>
+inline Tensor2_Expr
+<const Tensor4_times_Tensor2_symmetric_02<A,B,T,U,Dim1,Dim2,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim1,Dim2,j,l>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,i,k> &b,
+	  const Tensor4_Expr<A,T,Dim,Dim1,Dim2,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_times_Tensor2_symmetric_02
+    <A,B,T,U,Dim1,Dim2,Dim,i,j,k,l> TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim1,Dim2,j,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,132 @@
+/* Declaration for Tensor4_Riemann, which has the symmetries of the
+   Riemann tensor.  Antisymmetric on the first two indices and the
+   last two indices, and symmetric on a cyclic permutation of the last
+   three indices. */
+
+template <class T, int Dim>
+class Tensor4_Riemann
+{};
+
+template <class T>
+class Tensor4_Riemann<T,3>
+{
+  /* The zero variable is because some of the components of a tensor
+     with these symmetries are identically zero. */
+
+  T zero;
+  T data0101,data0102,data0112,data0202,data0212,data1212;
+public:
+  Tensor4_Riemann():zero(0.0) {}
+
+  /* There are two operator(int,int,int,int)'s, one for non-consts
+     that lets you change the value, and one for consts that doesn't.
+     The non-const one will give you a wrong answer if you aren't
+     careful.  The problem is that we only store the minimal set of
+     components, but some have different signs.  We can't return the
+     negative of a component, and assign something to it, because that
+     would assign something to a temporary.  To get the correct answer
+     if you don't want to change the value, use eval instead. */
+
+  T operator()(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+    return 
+      N1==0 ?
+      (N2==0 ? zero
+       : (N2==1 ?
+	  (N3==0 ?
+	   (N4==0 ? zero : (N4==1 ? data0101 : data0102))
+	   : (N3==1 ? (N4==0 ? -data0101 : (N4==1 ? zero : data0112))
+	      : (N4==0 ? -data0102 : (N4==1 ? -data0112 : zero))))
+	  : (N3==0 ?
+	   (N4==0 ? zero : (N4==1 ? data0102 : data0202))
+	   : (N3==1 ? (N4==0 ? -data0102 : (N4==1 ? zero : data0212))
+	      : (N4==0 ? -data0202 : (N4==1 ? -data0212 : zero))))))
+      : (N1==1 ?
+	 (N2==0 ?
+	  (N3==0 ?
+	   (N4==0 ? zero : (N4==1 ? -data0101 : -data0102))
+	   : (N3==1 ? (N4==0 ? data0101 : (N4==1 ? zero : -data0112))
+	      : (N4==0 ? data0102 : (N4==1 ? data0112 : zero))))
+	  : (N2==1 ? zero
+	     : (N3==0 ?
+		(N4==0 ? zero : (N4==1 ? data0112 : data0212))
+		: (N3==1 ? (N4==0 ? -data0112 : (N4==1 ? zero : data1212))
+		   : (N4==0 ? -data0212 : (N4==1 ? -data1212 : zero))))))
+	 : (N2==0 ?
+	    (N3==0 ?
+	     (N4==0 ? zero : (N4==1 ? -data0102 : -data0202))
+	     : (N3==1 ? (N4==0 ? data0102 : (N4==1 ? zero : -data0212))
+		: (N4==0 ? data0202 : (N4==1 ? data0212 : zero))))
+	    : (N2==1 ?
+	       (N3==0 ?
+		(N4==0 ? zero : (N4==1 ? -data0112 : -data0212))
+		: (N3==1 ? (N4==0 ? data0112 : (N4==1 ? zero : -data1212))
+		   : (N4==0 ? data0212 : (N4==1 ? data1212 : zero))))
+	       : zero)));
+  }
+
+  T eval(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+    return 
+      N1==0 ?
+      (N2==0 ? zero
+       : (N2==1 ?
+	  (N3==0 ?
+	   (N4==0 ? zero : (N4==1 ? data0101 : data0102))
+	   : (N3==1 ? (N4==0 ? -data0101 : (N4==1 ? zero : data0112))
+	      : (N4==0 ? -data0102 : (N4==1 ? -data0112 : zero))))
+	  : (N3==0 ?
+	   (N4==0 ? zero : (N4==1 ? data0102 : data0202))
+	   : (N3==1 ? (N4==0 ? -data0102 : (N4==1 ? zero : data0212))
+	      : (N4==0 ? -data0202 : (N4==1 ? -data0212 : zero))))))
+      : (N1==1 ?
+	 (N2==0 ?
+	  (N3==0 ?
+	   (N4==0 ? zero : (N4==1 ? -data0101 : -data0102))
+	   : (N3==1 ? (N4==0 ? data0101 : (N4==1 ? zero : -data0112))
+	      : (N4==0 ? data0102 : (N4==1 ? data0112 : zero))))
+	  : (N2==1 ? zero
+	     : (N3==0 ?
+		(N4==0 ? zero : (N4==1 ? data0112 : data0212))
+		: (N3==1 ? (N4==0 ? -data0112 : (N4==1 ? zero : data1212))
+		   : (N4==0 ? -data0212 : (N4==1 ? -data1212 : zero))))))
+	 : (N2==0 ?
+	    (N3==0 ?
+	     (N4==0 ? zero : (N4==1 ? -data0102 : -data0202))
+	     : (N3==1 ? (N4==0 ? data0102 : (N4==1 ? zero : -data0212))
+		: (N4==0 ? data0202 : (N4==1 ? data0212 : zero))))
+	    : (N2==1 ?
+	       (N3==0 ?
+		(N4==0 ? zero : (N4==1 ? -data0112 : -data0212))
+		: (N3==1 ? (N4==0 ? data0112 : (N4==1 ? zero : -data1212))
+		   : (N4==0 ? data0212 : (N4==1 ? data1212 : zero))))
+	       : zero)));
+  }
+
+  T & operator()(const int N1, const int N2, const int N3, const int N4)
+  {
+    return
+      (N1==0 && N2==1 && N3==0 && N4==1) ? data0101
+      : ((N1==0 && N2==1 && N3==0 && N4==2) ? data0102
+	 : ((N1==0 && N2==1 && N3==1 && N4==2) ? data0112
+	    : ((N1==0 && N2==2 && N3==1 && N4==2) ? data0212
+	       : ((N1==0 && N2==2 && N3==0 && N4==2) ? data0202
+		  : ((N1==1 && N2==2 && N3==1 && N4==2) ? data1212
+		     : zero)))));
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions. */
+
+  template<char i, char j, char k, char l>
+  Tensor4_Riemann_Expr<Tensor4_Riemann<T,3>,T,3,i,j,k,l> operator()
+    (const Index<i,3> index1, const Index<j,3> index2, const Index<k,3> index3,
+     const Index<l,3> index4)
+  {
+    return Tensor4_Riemann_Expr<Tensor4_Riemann<T,3>,T,3,i,j,k,l>(*this);
+  }
+};
+
+#include "Tensor4_Riemann/Tensor4_Riemann_Expr.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann/Tensor4_Riemann_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann/Tensor4_Riemann_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,88 @@
+/* Declares a wrapper class for rank 4 Tensor expressions with Riemann
+   symmetries.  */
+
+#include "Tensor4_Riemann_times_Tensor2_symmetric.h"
+#include "Tensor4_Riemann_plus_Tensor4_Riemann.h"
+#include "Tensor4_Riemann_minus_Tensor4_Riemann.h"
+#include "Tensor4_Riemann_times_Tensor1.h"
+#include "Tensor4_Riemann_times_Tensor4_ddg.h"
+
+template<class A, class T, int Dim, char i, char j, char k, char l>
+class Tensor4_Riemann_Expr
+{
+  A iter;
+public:
+  Tensor4_Riemann_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+    return iter(N1,N2,N3,N4);
+  }
+};
+
+
+template<class A, class T, int Dim, char i, char j, char k, char l>
+class Tensor4_Riemann_Expr<Tensor4_Riemann<A,Dim>,T,Dim,i,j,k,l>
+{
+  Tensor4_Riemann<A,Dim> &iter;
+public:
+  Tensor4_Riemann_Expr(Tensor4_Riemann<A,Dim> &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+    return iter.eval(N1,N2,N3,N4);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor4_Riemann_Expr<Tensor4_Riemann<A,Dim>,T,Dim,i,j,k,l> &
+  operator=(const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> &result)
+  {
+    iter(0,1,0,1)=result(0,1,0,1);
+    iter(0,1,0,2)=result(0,1,0,2);
+    iter(0,2,0,2)=result(0,2,0,2);
+    iter(0,1,1,2)=result(0,1,1,2);
+    iter(0,2,1,2)=result(0,2,1,2);
+    iter(1,2,1,2)=result(1,2,1,2);
+    return *this;
+  }
+
+  const Tensor4_Riemann_Expr<Tensor4_Riemann<A,Dim>,T,Dim,i,j,k,l> &
+  operator=(const Tensor4_Riemann_Expr<Tensor4_Riemann<A,Dim>,T,Dim,i,j,k,l>
+	    &result)
+  {
+    return operator=<Tensor4_Riemann<A,Dim>,T>(result);
+  }
+  template<class B, class U>
+  const Tensor4_Riemann_Expr<Tensor4_Riemann<A,Dim>,T,Dim,i,j,k,l> &
+  operator+=(const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> &result)
+  {
+    iter(0,1,0,1)+=result(0,1,0,1);
+    iter(0,1,0,2)+=result(0,1,0,2);
+    iter(0,2,0,2)+=result(0,2,0,2);
+    iter(0,1,1,2)+=result(0,1,1,2);
+    iter(0,2,1,2)+=result(0,2,1,2);
+    iter(1,2,1,2)+=result(1,2,1,2);
+    return *this;
+  }
+
+  /* Add a Tensor4_Riemann with the indices switched, making it a
+     subtraction. */
+
+  template<class B, class U>
+  const Tensor4_Riemann_Expr<Tensor4_Riemann<A,Dim>,T,Dim,i,j,k,l> &
+  operator+=(const Tensor4_Riemann_Expr<B,U,Dim,j,i,k,l> &result)
+  {
+    iter(0,1,0,1)-=result(0,1,0,1);
+    iter(0,1,0,2)-=result(0,1,0,2);
+    iter(0,2,0,2)-=result(0,2,0,2);
+    iter(0,1,1,2)-=result(0,1,1,2);
+    iter(0,2,1,2)-=result(0,2,1,2);
+    iter(1,2,1,2)-=result(1,2,1,2);
+    return *this;
+  }
+
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann/Tensor4_Riemann_minus_Tensor4_Riemann.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann/Tensor4_Riemann_minus_Tensor4_Riemann.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* Subtracts a Tensor4_Riemann from a Tensor4_Riemann, yielding a
+   Tensor4_Riemann. */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_Riemann_minus_Tensor4_Riemann
+{
+  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> iterA;
+  const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)-iterB(N1,N2,N3,N4);
+  }
+
+  Tensor4_Riemann_minus_Tensor4_Riemann
+  (const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+   const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_Riemann_Expr
+<const Tensor4_Riemann_minus_Tensor4_Riemann<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,j,k,l>
+operator-(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> &b)
+{
+  typedef const Tensor4_Riemann_minus_Tensor4_Riemann<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Riemann_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann/Tensor4_Riemann_plus_Tensor4_Riemann.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann/Tensor4_Riemann_plus_Tensor4_Riemann.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* Adds a Tensor4_Riemann to a Tensor4_Riemann, yielding a
+   Tensor4_Riemann. */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_Riemann_plus_Tensor4_Riemann
+{
+  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> iterA;
+  const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)+iterB(N1,N2,N3,N4);
+  }
+
+  Tensor4_Riemann_plus_Tensor4_Riemann
+  (const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+   const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_Riemann_Expr
+<const Tensor4_Riemann_plus_Tensor4_Riemann<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,j,k,l>
+operator+(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor4_Riemann_Expr<B,U,Dim,i,j,k,l> &b)
+{
+  typedef const Tensor4_Riemann_plus_Tensor4_Riemann<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Riemann_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann/Tensor4_Riemann_times_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann/Tensor4_Riemann_times_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,199 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_Riemann*Tensor1, yielding a Tensor3_antisymmetric. */
+
+/* A(i,j,k,l)*B(i) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_Riemann_times_Tensor1_0
+{
+  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> iterA;
+  const Tensor1_Expr<B,U,Dim,i> iterB;
+public:
+  Tensor4_Riemann_times_Tensor1_0
+  (const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+   const Tensor1_Expr<B,U,Dim,i> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(0,N1,N2,N3)*iterB(0) + iterA(1,N1,N2,N3)*iterB(1)
+      + iterA(2,N1,N2,N3)*iterB(2);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_0<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,j,k,l>
+operator*(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor1_Expr<B,U,Dim,i> &b)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_0<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(i)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_0<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,j,k,l>
+operator*(const Tensor1_Expr<B,U,Dim,i> &b,
+	  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_0<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_Riemann_times_Tensor1_1
+{
+  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> iterA;
+  const Tensor1_Expr<B,U,Dim,j> iterB;
+public:
+  Tensor4_Riemann_times_Tensor1_1
+  (const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+   const Tensor1_Expr<B,U,Dim,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,0,N2,N3)*iterB(0) + iterA(N1,1,N2,N3)*iterB(1)
+      + iterA(N1,2,N2,N3)*iterB(2);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_1<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,k,l>
+operator*(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor1_Expr<B,U,Dim,j> &b)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_1<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(j)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_1<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,k,l>
+operator*(const Tensor1_Expr<B,U,Dim,j> &b,
+	  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_1<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(k) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_Riemann_times_Tensor1_2
+{
+  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> iterA;
+  const Tensor1_Expr<B,U,Dim,k> iterB;
+public:
+  Tensor4_Riemann_times_Tensor1_2
+  (const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+   const Tensor1_Expr<B,U,Dim,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,0,N3)*iterB(0) + iterA(N1,N2,1,N3)*iterB(1)
+      + iterA(N1,N2,2,N3)*iterB(2);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_2<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,j,l>
+operator*(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor1_Expr<B,U,Dim,k> &b)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_2<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_2<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,j,l>
+operator*(const Tensor1_Expr<B,U,Dim,k> &b,
+	  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_2<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_Riemann_times_Tensor1_3
+{
+  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> iterA;
+  const Tensor1_Expr<B,U,Dim,l> iterB;
+public:
+  Tensor4_Riemann_times_Tensor1_3
+  (const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+   const Tensor1_Expr<B,U,Dim,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return iterA(N1,N2,N3,0)*iterB(0) + iterA(N1,N2,N3,1)*iterB(1)
+      + iterA(N1,N2,N3,2)*iterB(2);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_3<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,j,k>
+operator*(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor1_Expr<B,U,Dim,l> &b)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_3<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,k>
+    (TensorExpr(a,b));
+}
+
+/* B(l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor3_antisymmetric_Expr
+<const Tensor4_Riemann_times_Tensor1_3<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,j,k>
+operator*(const Tensor1_Expr<B,U,Dim,l> &b,
+	  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_Riemann_times_Tensor1_3<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor3_antisymmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,k>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann/Tensor4_Riemann_times_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann/Tensor4_Riemann_times_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,55 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_Riemann*Tensor2_symmetric and
+   Tensor2_symmetric*Tensor4_Riemann, yielding a Tensor2_symmetric. */
+
+/* A(i,j,k,l)*B(i,k) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_Riemann_times_Tensor2_symmetric_0
+{
+  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,i,k> iterB;
+public:
+  Tensor4_Riemann_times_Tensor2_symmetric_0
+  (const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,i,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return iterA(0,N1,0,N2)*iterB(0,0) + iterA(0,N1,1,N2)*iterB(0,1)
+      + iterA(0,N1,2,N2)*iterB(0,2) + iterA(1,N1,0,N2)*iterB(1,0)
+      + iterA(1,N1,1,N2)*iterB(1,1) + iterA(1,N1,2,N2)*iterB(1,2)
+      + iterA(2,N1,0,N2)*iterB(2,0) + iterA(2,N1,1,N2)*iterB(2,1)
+      + iterA(2,N1,2,N2)*iterB(2,2);
+  }
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_Riemann_times_Tensor2_symmetric_0<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,j,l>
+operator*(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,i,k> &b)
+{
+  typedef const Tensor4_Riemann_times_Tensor2_symmetric_0<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(i,k)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_Riemann_times_Tensor2_symmetric_0<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,j,l>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,i,k> &b,
+	  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_Riemann_times_Tensor2_symmetric_0<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,j,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann/Tensor4_Riemann_times_Tensor4.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann/Tensor4_Riemann_times_Tensor4.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,65 @@
+/* This file has the declaration for Tensor4_Riemann*Tensor4 yielding
+   a double.  I simplify the expression by removing the identically
+   zero components of Riemann. */
+
+/* A(i,j,k,l)*B(i,j,k,l) */
+
+template<class A, class B, char i, char j, char k, char l>
+inline double operator*(const Tensor4_Riemann_Expr<A,i,j,k,l> &a,
+			const Tensor4_Expr<B,i,j,k,l> &b)
+{
+  return a(1,0,0,1)*b(1,0,0,1) + a(2,0,0,1)*b(2,0,0,1)
+    + a(0,1,0,1)*b(0,1,0,1) + a(2,1,0,1)*b(2,1,0,1)
+    + a(0,2,0,1)*b(0,2,0,1) + a(1,2,0,1)*b(1,2,0,1)
+    + a(1,0,0,2)*b(1,0,0,2) + a(2,0,0,2)*b(2,0,0,2)
+    + a(0,1,0,2)*b(0,1,0,2) + a(2,1,0,2)*b(2,1,0,2)
+    + a(0,2,0,2)*b(0,2,0,2) + a(1,2,0,2)*b(1,2,0,2)
+    + a(1,0,1,0)*b(1,0,1,0) + a(2,0,1,0)*b(2,0,1,0)
+    + a(0,1,1,0)*b(0,1,1,0) + a(2,1,1,0)*b(2,1,1,0)
+    + a(0,2,1,0)*b(0,2,1,0) + a(1,2,1,0)*b(1,2,1,0)
+    + a(1,0,1,2)*b(1,0,1,2) + a(2,0,1,2)*b(2,0,1,2)
+    + a(0,1,1,2)*b(0,1,1,2) + a(2,1,1,2)*b(2,1,1,2)
+    + a(0,2,1,2)*b(0,2,1,2) + a(1,2,1,2)*b(1,2,1,2)
+    + a(1,0,2,0)*b(1,0,2,0) + a(2,0,2,0)*b(2,0,2,0)
+    + a(0,1,2,0)*b(0,1,2,0) + a(2,1,2,0)*b(2,1,2,0)
+    + a(0,2,2,0)*b(0,2,2,0) + a(1,2,2,0)*b(1,2,2,0)
+    + a(1,0,2,1)*b(1,0,2,1) + a(2,0,2,1)*b(2,0,2,1)
+    + a(0,1,2,1)*b(0,1,2,1) + a(2,1,2,1)*b(2,1,2,1)
+    + a(0,2,2,1)*b(0,2,2,1) + a(1,2,2,1)*b(1,2,2,1);
+
+//    return a(0,0,0,0)*b(0,0,0,0) + a(1,0,0,0)*b(1,0,0,0) + a(2,0,0,0)*b(2,0,0,0)
+//      + a(0,1,0,0)*b(0,1,0,0) + a(1,1,0,0)*b(1,1,0,0) + a(2,1,0,0)*b(2,1,0,0)
+//      + a(0,2,0,0)*b(0,2,0,0) + a(1,2,0,0)*b(1,2,0,0) + a(2,2,0,0)*b(2,2,0,0)
+//      + a(0,0,0,1)*b(0,0,0,1) + a(1,0,0,1)*b(1,0,0,1) + a(2,0,0,1)*b(2,0,0,1)
+//      + a(0,1,0,1)*b(0,1,0,1) + a(1,1,0,1)*b(1,1,0,1) + a(2,1,0,1)*b(2,1,0,1)
+//      + a(0,2,0,1)*b(0,2,0,1) + a(1,2,0,1)*b(1,2,0,1) + a(2,2,0,1)*b(2,2,0,1)
+//      + a(0,0,0,2)*b(0,0,0,2) + a(1,0,0,2)*b(1,0,0,2) + a(2,0,0,2)*b(2,0,0,2)
+//      + a(0,1,0,2)*b(0,1,0,2) + a(1,1,0,2)*b(1,1,0,2) + a(2,1,0,2)*b(2,1,0,2)
+//      + a(0,2,0,2)*b(0,2,0,2) + a(1,2,0,2)*b(1,2,0,2) + a(2,2,0,2)*b(2,2,0,2)
+//      + a(0,0,1,0)*b(0,0,1,0) + a(1,0,1,0)*b(1,0,1,0) + a(2,0,1,0)*b(2,0,1,0)
+//      + a(0,1,1,0)*b(0,1,1,0) + a(1,1,1,0)*b(1,1,1,0) + a(2,1,1,0)*b(2,1,1,0)
+//      + a(0,2,1,0)*b(0,2,1,0) + a(1,2,1,0)*b(1,2,1,0) + a(2,2,1,0)*b(2,2,1,0)
+//      + a(0,0,1,1)*b(0,0,1,1) + a(1,0,1,1)*b(1,0,1,1) + a(2,0,1,1)*b(2,0,1,1)
+//      + a(0,1,1,1)*b(0,1,1,1) + a(1,1,1,1)*b(1,1,1,1) + a(2,1,1,1)*b(2,1,1,1)
+//      + a(0,2,1,1)*b(0,2,1,1) + a(1,2,1,1)*b(1,2,1,1) + a(2,2,1,1)*b(2,2,1,1)
+//      + a(0,0,1,2)*b(0,0,1,2) + a(1,0,1,2)*b(1,0,1,2) + a(2,0,1,2)*b(2,0,1,2)
+//      + a(0,1,1,2)*b(0,1,1,2) + a(1,1,1,2)*b(1,1,1,2) + a(2,1,1,2)*b(2,1,1,2)
+//      + a(0,2,1,2)*b(0,2,1,2) + a(1,2,1,2)*b(1,2,1,2) + a(2,2,1,2)*b(2,2,1,2)
+//      + a(0,0,2,0)*b(0,0,2,0) + a(1,0,2,0)*b(1,0,2,0) + a(2,0,2,0)*b(2,0,2,0)
+//      + a(0,1,2,0)*b(0,1,2,0) + a(1,1,2,0)*b(1,1,2,0) + a(2,1,2,0)*b(2,1,2,0)
+//      + a(0,2,2,0)*b(0,2,2,0) + a(1,2,2,0)*b(1,2,2,0) + a(2,2,2,0)*b(2,2,2,0)
+//      + a(0,0,2,1)*b(0,0,2,1) + a(1,0,2,1)*b(1,0,2,1) + a(2,0,2,1)*b(2,0,2,1)
+//      + a(0,1,2,1)*b(0,1,2,1) + a(1,1,2,1)*b(1,1,2,1) + a(2,1,2,1)*b(2,1,2,1)
+//      + a(0,2,2,1)*b(0,2,2,1) + a(1,2,2,1)*b(1,2,2,1) + a(2,2,2,1)*b(2,2,2,1)
+//      + a(0,0,2,2)*b(0,0,2,2) + a(1,0,2,2)*b(1,0,2,2) + a(2,0,2,2)*b(2,0,2,2)
+//      + a(0,1,2,2)*b(0,1,2,2) + a(1,1,2,2)*b(1,1,2,2) + a(2,1,2,2)*b(2,1,2,2)
+//      + a(0,2,2,2)*b(0,2,2,2) + a(1,2,2,2)*b(1,2,2,2) + a(2,2,2,2)*b(2,2,2,2);
+}
+
+template<class A, class B, char i, char j, char k, char l>
+inline double operator*(const Tensor4_Expr<B,i,j,k,l> &b,
+			const Tensor4_Riemann_Expr<A,i,j,k,l> &a)
+			
+{
+  return operator*(a,b);
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_Riemann/Tensor4_Riemann_times_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_Riemann/Tensor4_Riemann_times_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,79 @@
+/* This file has the declaration for Tensor4_Riemann*Tensor4_ddg yielding
+   a typename promote<T,U>::V.  I simplify the expression by removing the identically
+   zero components of Riemann. */
+
+/* A(i,j,k,l)*B(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const typename promote<T,U>::V
+operator*(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,j,k,l> &b)
+{
+  return a(1,0,0,1)*b(1,0,0,1) + a(2,0,0,1)*b(2,0,0,1)
+    + a(0,1,0,1)*b(0,1,0,1) + a(2,1,0,1)*b(2,1,0,1)
+    + a(0,2,0,1)*b(0,2,0,1) + a(1,2,0,1)*b(1,2,0,1)
+    + a(1,0,0,2)*b(1,0,0,2) + a(2,0,0,2)*b(2,0,0,2)
+    + a(0,1,0,2)*b(0,1,0,2) + a(2,1,0,2)*b(2,1,0,2)
+    + a(0,2,0,2)*b(0,2,0,2) + a(1,2,0,2)*b(1,2,0,2)
+    + a(1,0,1,0)*b(1,0,1,0) + a(2,0,1,0)*b(2,0,1,0)
+    + a(0,1,1,0)*b(0,1,1,0) + a(2,1,1,0)*b(2,1,1,0)
+    + a(0,2,1,0)*b(0,2,1,0) + a(1,2,1,0)*b(1,2,1,0)
+    + a(1,0,1,2)*b(1,0,1,2) + a(2,0,1,2)*b(2,0,1,2)
+    + a(0,1,1,2)*b(0,1,1,2) + a(2,1,1,2)*b(2,1,1,2)
+    + a(0,2,1,2)*b(0,2,1,2) + a(1,2,1,2)*b(1,2,1,2)
+    + a(1,0,2,0)*b(1,0,2,0) + a(2,0,2,0)*b(2,0,2,0)
+    + a(0,1,2,0)*b(0,1,2,0) + a(2,1,2,0)*b(2,1,2,0)
+    + a(0,2,2,0)*b(0,2,2,0) + a(1,2,2,0)*b(1,2,2,0)
+    + a(1,0,2,1)*b(1,0,2,1) + a(2,0,2,1)*b(2,0,2,1)
+    + a(0,1,2,1)*b(0,1,2,1) + a(2,1,2,1)*b(2,1,2,1)
+    + a(0,2,2,1)*b(0,2,2,1) + a(1,2,2,1)*b(1,2,2,1);
+}
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const typename promote<T,U>::V
+operator*(const Tensor4_ddg_Expr<B,U,Dim,Dim,i,j,k,l> &b,
+	  const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a)
+			
+{
+  return operator*(a,b);
+}
+
+/* A(i,j,k,l)*B(i,k,j,l) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const typename promote<T,U>::V
+operator*(const Tensor4_Riemann_Expr<A,T,Dim,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,k,j,l> &b)
+{
+  return a(1,0,0,1)*b(1,0,0,1) + a(2,0,0,1)*b(2,0,0,1)
+    + a(0,1,0,1)*b(0,0,1,1) + a(2,1,0,1)*b(2,0,1,1)
+    + a(0,2,0,1)*b(0,0,2,1) + a(1,2,0,1)*b(1,0,2,1)
+    + a(1,0,0,2)*b(1,0,0,2) + a(2,0,0,2)*b(2,0,0,2)
+    + a(0,1,0,2)*b(0,0,1,2) + a(2,1,0,2)*b(2,0,1,2)
+    + a(0,2,0,2)*b(0,0,2,2) + a(1,2,0,2)*b(1,0,2,2)
+    + a(1,0,1,0)*b(1,1,0,0) + a(2,0,1,0)*b(2,1,0,0)
+    + a(0,1,1,0)*b(0,1,1,0) + a(2,1,1,0)*b(2,1,1,0)
+    + a(0,2,1,0)*b(0,1,2,0) + a(1,2,1,0)*b(1,1,2,0)
+    + a(1,0,1,2)*b(1,1,0,2) + a(2,0,1,2)*b(2,1,0,2)
+    + a(0,1,1,2)*b(0,1,1,2) + a(2,1,1,2)*b(2,1,1,2)
+    + a(0,2,1,2)*b(0,1,2,2) + a(1,2,1,2)*b(1,1,2,2)
+    + a(1,0,2,0)*b(1,2,0,0) + a(2,0,2,0)*b(2,2,0,0)
+    + a(0,1,2,0)*b(0,2,1,0) + a(2,1,2,0)*b(2,2,1,0)
+    + a(0,2,2,0)*b(0,2,2,0) + a(1,2,2,0)*b(1,2,2,0)
+    + a(1,0,2,1)*b(1,2,0,1) + a(2,0,2,1)*b(2,2,0,1)
+    + a(0,1,2,1)*b(0,2,1,1) + a(2,1,2,1)*b(2,2,1,1)
+    + a(0,2,2,1)*b(0,2,2,1) + a(1,2,2,1)*b(1,2,2,1);
+}
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const typename promote<T,U>::V
+ operator*(const Tensor4_ddg_Expr<B,U,Dim,Dim,i,j,k,l> &b,
+	   const Tensor4_Riemann_Expr<A,T,Dim,i,k,j,l> &a)
+			
+{
+  return operator*(a,b);
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,13 @@
+/* Declaration for Tensor4_ddg, which is separately symmetric on the
+   first two and last two indices. */
+
+#include "Tensor4_ddg/Tensor4_ddg_number.h"
+#include "Tensor4_ddg/Tensor4_ddg_numeral.h"
+
+#include "Tensor4_ddg/Tensor4_ddg_value.h"
+#include "Tensor4_ddg/Tensor4_ddg_pointer.h"
+
+/* The Expression files which define the generic intermediate template
+   as well as a place where assignment gets done. */
+
+#include "Tensor4_ddg/Tensor4_ddg_Expr.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_Expr.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_Expr.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,59 @@
+/* Declares a wrapper class for rank 4 Tensor expressions symmetric on
+   the first two and last two indices. */
+					 
+#include "Tensor4_ddg_times_Tensor2_symmetric.h"
+#include "Tensor4_ddg_carat_Tensor2_symmetric.h"
+#include "Tensor4_ddg_and_Tensor2_symmetric.h"
+#include "Tensor4_ddg_mod_Tensor2_symmetric.h"
+#include "Tensor4_ddg_times_Tensor2.h"
+#include "Tensor4_ddg_times_Tensor1.h"
+#include "Tensor4_ddg_times_generic.h"
+#include "Tensor4_ddg_times_Tensor4_ddg.h"
+#include "Tensor4_ddg_plus_Tensor4_ddg.h"
+#include "Tensor4_ddg_minus_Tensor4_ddg.h"
+#include "Tensor4_ddg_or_Tensor4_ddg.h"
+#include "Tensor4_ddg_and_Tensor4_ddg.h"
+#include "Tensor4_ddg_carat_Tensor4_ddg.h"
+#include "minus_Tensor4_ddg.h"
+//  #include "Tensor4_ddg_mod_Tensor4_ddg.h"
+
+template<class A, class T, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_Expr
+{
+  A iter;
+public:
+  Tensor4_ddg_Expr(A &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+    return iter(N1,N2,N3,N4);
+  }
+};
+
+template<class A, class T, int Tensor_Dim01, int Tensor_Dim23,
+  int Dim01, int Dim23, char i, char j, char k, char l>
+class Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,T,Dim01,Dim23,i,j,k,l>
+{
+  Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23> &iter;
+public:
+  Tensor4_ddg_Expr(Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23> &a): iter(a) {}
+  T operator()(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+    return iter(N1,N2,N3,N4);
+  }
+
+  /* Various assignment operators.  I have to explicitly declare the
+     second operator= because otherwise the compiler will generate its
+     own and not use the template code. */
+
+  template<class B, class U>
+  const Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,T,Dim01,Dim23,i,j,k,l> &
+  operator=(const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &result);
+
+  const Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,T,Dim01,Dim23,i,j,k,l> &
+  operator=(const Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,T,Dim01,Dim23,i,j,k,l> &result);
+};
+
+#include "Tensor4_ddg_Expr_equals.h"
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_Expr_equals.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_Expr_equals.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,108 @@
+/* Various assignment operators.  I have to explicitly declare the
+   second operator= because otherwise the compiler will generate its
+   own and not use the template code. */
+
+template<class A, class B, class U, int Current_Dim0, int Current_Dim1,
+  int Current_Dim2, int Current_Dim3, int Dim01, int Dim23, char i, char j,
+  char k, char l>
+inline void
+T4ddg_equals_T4ddg(A &iter,
+		   const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &result,
+		   const Number<Current_Dim0> &ND0,
+		   const Number<Current_Dim1> &ND1,
+		   const Number<Current_Dim2> &ND2,
+		   const Number<Current_Dim3> &ND3)
+{
+  iter(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1,Current_Dim3-1)=
+    result(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1,Current_Dim3-1);
+  T4ddg_equals_T4ddg(iter,result,Number<Current_Dim0-1>(),
+		     Number<Current_Dim1>(),Number<Current_Dim2>(),
+		     Number<Current_Dim3>());
+}
+
+template<class A, class B, class U, int Current_Dim1, int Current_Dim2,
+  int Current_Dim3, int Dim01, int Dim23, char i, char j, char k, char l>
+inline void
+T4ddg_equals_T4ddg(A &iter,
+		   const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &result,
+		   const Number<1> &ND0,
+		   const Number<Current_Dim1> &ND1,
+		   const Number<Current_Dim2> &ND2,
+		   const Number<Current_Dim3> &ND3)
+{
+  iter(0,Current_Dim1-1,Current_Dim2-1,Current_Dim3-1)=
+    result(0,Current_Dim1-1,Current_Dim2-1,Current_Dim3-1);
+  T4ddg_equals_T4ddg(iter,result,Number<Current_Dim1-1>(),
+		     Number<Current_Dim1-1>(),Number<Current_Dim2>(),
+		     Number<Current_Dim3>());
+}
+
+template<class A, class B, class U, int Current_Dim2, int Current_Dim3,
+  int Dim01, int Dim23, char i, char j, char k, char l>
+inline void
+T4ddg_equals_T4ddg(A &iter,
+		   const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &result,
+		   const Number<1> &ND0,
+		   const Number<1> &ND1,
+		   const Number<Current_Dim2> &ND2,
+		   const Number<Current_Dim3> &ND3)
+{
+  iter(0,0,Current_Dim2-1,Current_Dim3-1)=
+    result(0,0,Current_Dim2-1,Current_Dim3-1);
+  T4ddg_equals_T4ddg(iter,result,Number<Dim01>(),
+		     Number<Dim01>(),Number<Current_Dim2-1>(),
+		     Number<Current_Dim3>());
+}
+
+template<class A, class B, class U, int Current_Dim3, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline void
+T4ddg_equals_T4ddg(A &iter,
+		   const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &result,
+		   const Number<1> &ND0,
+		   const Number<1> &ND1,
+		   const Number<1> &ND2,
+		   const Number<Current_Dim3> &ND3)
+{
+  iter(0,0,0,Current_Dim3-1)=result(0,0,0,Current_Dim3-1);
+  T4ddg_equals_T4ddg(iter,result,Number<Dim01>(),
+		     Number<Dim01>(),Number<Current_Dim3-1>(),
+		     Number<Current_Dim3-1>());
+}
+
+template<class A, class B, class U, int Dim01, int Dim23, char i, char j,
+  char k, char l>
+inline void
+T4ddg_equals_T4ddg(A &iter,
+		   const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &result,
+		   const Number<1> &ND0, const Number<1> &ND1,
+		   const Number<1> &ND2, const Number<1> &ND3)
+{
+  iter(0,0,0,0)=result(0,0,0,0);
+}
+
+template<class A, class T, int Tensor_Dim01, int Tensor_Dim23,
+  int Dim01, int Dim23, char i, char j, char k,char l>
+template<class B, class U> inline
+const Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,
+  T,Dim01,Dim23,i,j,k,l> &
+Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,
+  T,Dim01,Dim23,i,j,k,l>
+::operator=(const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &result)
+  {
+    T4ddg_equals_T4ddg(iter,result,Number<Dim01>(),Number<Dim01>(),
+		       Number<Dim23>(),Number<Dim23>());
+    return *this;
+  }
+
+template<class A, class T, int Tensor_Dim01, int Tensor_Dim23,
+  int Dim01, int Dim23, char i, char j, char k,char l> inline
+const Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,
+  T,Dim01,Dim23,i,j,k,l> &
+Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,
+  T,Dim01,Dim23,i,j,k,l>
+::operator=(const Tensor4_ddg_Expr<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,
+	    T,Dim01,Dim23,i,j,k,l> &result)
+  {
+    return operator=<Tensor4_ddg<A,Tensor_Dim01,Tensor_Dim23>,T>(result);
+  }
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_and_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_and_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,206 @@
+/* Multiply a Tensor2_symmetric and a Tensor4_ddg together but don't
+   contract, yielding a Tensor4_ddg. */
+
+/* A(i,j,k,l) & B(i,j) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_and_Tensor2_symmetric_01
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+		    const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)*iterB(N1,N2);
+  }
+
+  Tensor4_ddg_and_Tensor2_symmetric_01
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_and_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator&(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b)
+{
+  typedef const Tensor4_ddg_and_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(i,j) & A(i,j,k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_and_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator&(const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_and_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l) & B(k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_and_Tensor2_symmetric_23
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,k,l> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+		    const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)*iterB(N3,N4);
+  }
+
+  Tensor4_ddg_and_Tensor2_symmetric_23
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim01,k,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_and_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator&(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,k,l> &b)
+{
+  typedef const Tensor4_ddg_and_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l) & A(i,j,k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_and_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator&(const Tensor2_symmetric_Expr<B,U,Dim01,k,l> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_and_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* I originally put these declarations for unknown reasons, but they
+   won't work because the result is not a Tensor4_ddg.  The
+   multiplication messes up the symmetries. */
+
+//  /* A(i,j,k,l) & B(j,l) -> Tensor4_ddg */
+
+//  template<class A, class B, class T, class U, int Dim,
+//    char i, char j, char k, char l>
+//  class Tensor4_ddg_and_Tensor2_symmetric_13
+//  {
+//    const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+//    const Tensor2_symmetric_Expr<B,U,Dim,j,l> iterB;
+//  public:
+//    typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+//  		    const int N4) const
+//    {
+//      return iterA(N1,N2,N3,N4)*iterB(N2,N4);
+//    }
+
+//    Tensor4_ddg_and_Tensor2_symmetric_13
+//    (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+//     const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b): iterA(a), iterB(b) {}
+//  };
+
+//  template<class A, class B, class T, class U, int Dim,
+//    char i, char j, char k, char l>
+//  inline const Tensor4_ddg_Expr
+//  <const Tensor4_ddg_and_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+//    typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//  operator&(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+//  	  const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b)
+//  {
+//    typedef const Tensor4_ddg_and_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+//      TensorExpr;
+//    return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//      (TensorExpr(a,b));
+//  }
+
+//  /* B(j,l) & A(i,j,k,l) -> Tensor4_ddg */
+
+//  template<class A, class B, class T, class U, int Dim,
+//    char i, char j, char k, char l>
+//  inline const Tensor4_ddg_Expr
+//  <const Tensor4_ddg_and_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+//    typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//  operator&(const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b,
+//  	  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a)
+//  {
+//    typedef const Tensor4_ddg_and_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+//      TensorExpr;
+//    return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//      (TensorExpr(a,b));
+//  }
+
+//  /* A(i,j,k,l) & B(l,j) -> Tensor4_ddg */
+
+//  template<class A, class B, class T, class U, int Dim,
+//    char i, char j, char k, char l>
+//  class Tensor4_ddg_and_Tensor2_symmetric_31
+//  {
+//    const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+//    const Tensor2_symmetric_Expr<B,U,Dim,l,j> iterB;
+//  public:
+//    typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+//  		    const int N4) const
+//    {
+//      return iterA(N1,N2,N3,N4)*iterB(N2,N4);
+//    }
+
+//    Tensor4_ddg_and_Tensor2_symmetric_31
+//    (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+//     const Tensor2_symmetric_Expr<B,U,Dim,l,j> &b): iterA(a), iterB(b) {}
+//  };
+
+//  template<class A, class B, class T, class U, int Dim,
+//    char i, char j, char k, char l>
+//  inline const Tensor4_ddg_Expr
+//  <const Tensor4_ddg_and_Tensor2_symmetric_31<A,B,T,U,Dim,i,j,k,l>,
+//    typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//  operator&(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+//  	  const Tensor2_symmetric_Expr<B,U,Dim,l,j> &b)
+//  {
+//    typedef const Tensor4_ddg_and_Tensor2_symmetric_31<A,B,T,U,Dim,i,j,k,l>
+//      TensorExpr;
+//    return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//      (TensorExpr(a,b));
+//  }
+
+//  /* B(l,j) & A(i,j,k,l) -> Tensor4_ddg */
+
+//  template<class A, class B, class T, class U, int Dim,
+//    char i, char j, char k, char l>
+//  inline const Tensor4_ddg_Expr
+//  <const Tensor4_ddg_and_Tensor2_symmetric_31<A,B,T,U,Dim,i,j,k,l>,
+//    typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//  operator&(const Tensor2_symmetric_Expr<B,U,Dim,l,j> &b,
+//  	  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a)
+//  {
+//    typedef const Tensor4_ddg_and_Tensor2_symmetric_31<A,B,T,U,Dim,i,j,k,l>
+//      TensorExpr;
+//    return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,j,k,l>
+//      (TensorExpr(a,b));
+//  }
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_and_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_and_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,68 @@
+/* Subtracts Tensor4_ddg-Tensor4_ddg -> Tensor4_Riemann */
+
+/* A(i,j,k,l) - B(i,l,k,j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_ddg_and_Tensor4_ddg0321
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,k,j,l> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N3,N2,N4)-iterB(N1,N4,N3,N2);
+  }
+
+  Tensor4_ddg_and_Tensor4_ddg0321
+  (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,k,j,l> &a,
+   const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_Riemann_Expr
+<const Tensor4_ddg_and_Tensor4_ddg0321<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,j,k,l>
+operator&&(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,k,j,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b)
+{
+  typedef const Tensor4_ddg_and_Tensor4_ddg0321<A,B,T,U,Dim,i,j,k,l> TensorExpr;
+  return Tensor4_Riemann_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,k,l,j) - B(i,l,k,j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_ddg_and_Tensor4_ddg0213
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,k,l,j> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N3,N4,N2)-iterB(N1,N4,N3,N2);
+  }
+
+  Tensor4_ddg_and_Tensor4_ddg0213
+  (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,k,l,j> &a,
+   const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_Riemann_Expr
+<const Tensor4_ddg_and_Tensor4_ddg0213<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,j,k,l>
+operator&&(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,k,l,j> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b)
+{
+  typedef const Tensor4_ddg_and_Tensor4_ddg0213<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor4_Riemann_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_carat_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_carat_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,76 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_ddg^Tensor2_symmetric and Tensor2_symmetric^Tensor4_ddg,
+   yielding a Tensor2_symmetric. */
+
+/* A(i,j,k,l)*B(j,l) */
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+class Tensor4_ddg_carat_Tensor2_symmetric_13
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1,N2)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1,N2)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0,N2)*iterB(0,0);
+  }
+public:
+  Tensor4_ddg_carat_Tensor2_symmetric_13
+  (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_carat_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b)
+{
+  typedef const Tensor4_ddg_carat_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(j,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_carat_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,k>
+operator^(const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_carat_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_carat_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_carat_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,62 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_ddg^Tensor4_ddg, yielding a Tensor4_ddg. */
+
+/* A(i,j,k,l)*B(j,l,m,n) */
+
+template<class A, class B, class T, class U, int Dim, int Dim23,
+  char i, char j, char k, char l, char m, char n>
+class Tensor4_ddg_carat_Tensor4_ddg_13
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim,Dim23,j,l,m,n> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const int N3, const int N4,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1,N2)
+      *iterB(Current_Dim0-1,Current_Dim1-1,N3,N4)
+      + eval(N1,N2,N3,N4,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const int N3, const int N4,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1,N2)*iterB(0,Current_Dim1-1,N3,N4)
+      + eval(N1,N2,N3,N4,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const int N3, const int N4,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0,N2)*iterB(0,0,N3,N4);
+  }
+public:
+  Tensor4_ddg_carat_Tensor4_ddg_13
+  (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+   const Tensor4_ddg_Expr<B,U,Dim,Dim23,j,l,m,n> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2,
+			     const int N3, const int N4) const
+  {
+    return eval(N1,N2,N3,N4,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, int Dim23,
+  char i, char j, char k, char l, char m, char n>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_carat_Tensor4_ddg_13<A,B,T,U,Dim,Dim23,i,j,k,l,m,n>,
+  typename promote<T,U>::V,Dim,Dim23,i,k,m,n>
+operator^(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim,Dim23,j,l,m,n> &b)
+{
+  typedef const Tensor4_ddg_carat_Tensor4_ddg_13<A,B,T,U,Dim,Dim23,i,j,k,l,m,n>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim23,i,k,m,n>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_minus_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_minus_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* Subtracts Tensor4_ddg-Tensor4_ddg -> Tensor4_ddg */
+
+/* A(i,j,k,l) - B(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_minus_Tensor4_ddg
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)-iterB(N1,N2,N3,N4);
+  }
+
+  Tensor4_ddg_minus_Tensor4_ddg(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a, const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_minus_Tensor4_ddg<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator-(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &b)
+{
+  typedef const Tensor4_ddg_minus_Tensor4_ddg<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_mod_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_mod_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,102 @@
+/* Divide a Tensor4_ddg by a Tensor2_symmetric without contracting, yielding a
+   Tensor4_ddg. */
+
+/* A(i,j,k,l) % B(i,j) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_mod_Tensor2_symmetric_01
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+		    const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)/iterB(N1,N2);
+  }
+
+  Tensor4_ddg_mod_Tensor2_symmetric_01
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_mod_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator%(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b)
+{
+  typedef const Tensor4_ddg_mod_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(i,j) % A(i,j,k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_mod_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator%(const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_mod_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l) % B(k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_mod_Tensor2_symmetric_23
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,k,l> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+		    const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)/iterB(N3,N4);
+  }
+
+  Tensor4_ddg_mod_Tensor2_symmetric_23
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim01,k,l> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_mod_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator%(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,k,l> &b)
+{
+  typedef const Tensor4_ddg_mod_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l) % A(i,j,k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_mod_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator%(const Tensor2_symmetric_Expr<B,U,Dim01,k,l> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_mod_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_mod_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_mod_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* Subtracts Tensor4_ddg-Tensor4_ddg -> Tensor4_Riemann */
+
+/* A(i,j,k,l) - B(i,l,k,j) */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_ddg_mod_Tensor4_ddg
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)-iterB(N1,N4,N3,N2);
+  }
+
+  Tensor4_ddg_mod_Tensor4_ddg
+  (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+   const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_Riemann_Expr
+<const Tensor4_ddg_mod_Tensor4_ddg<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,j,k,l>
+operator%(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b)
+{
+  typedef const Tensor4_ddg_mod_Tensor4_ddg<A,B,T,U,Dim,i,j,k,l> TensorExpr;
+  return Tensor4_Riemann_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_number.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_number.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+/* This is for expressions where a number is used for one or more
+   slots, and an index for the others, yielding a
+   Tensor2_symmetric_Expr or Tensor3_dg_Expr. */
+
+/* First and second slot. */
+
+template<class A, class T, int N1, int N2>
+class Tensor4_ddg_number_01
+{
+  A iterA;
+public:
+  T operator()(const int N3, const int N4) const
+  {
+    return iterA(N1,N2,N3,N4);
+  }
+  Tensor4_ddg_number_01(const A &a):iterA(a) {}
+};
+
+template<class A, class T, int N0, int N1>
+class Tensor4_ddg_number_rhs_01
+{};
+
+/* Only first slot */
+
+template<class A, class T, int N1>
+class Tensor4_ddg_number_0
+{
+  A iterA;
+public:
+  T operator()(const int N2, const int N3, const int N4) const
+  {
+    return iterA(N1,N2,N3,N4);
+  }
+  Tensor4_ddg_number_0(const A &a):iterA(a) {}
+};
+
+template<class A, class T, int N0>
+class Tensor4_ddg_number_rhs_0
+{};
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_numeral.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_numeral.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+/* This is for expressions where a number is used for one or more
+   slots, and an index for the others, yielding a
+   Tensor2_symmetric_Expr or Tensor3_dg_Expr. */
+
+/* First and second slot. */
+
+template<class A, class T>
+class Tensor4_ddg_numeral_01
+{
+  A iterA;
+  const int N1, N2;
+public:
+  T operator()(const int N3, const int N4) const
+  {
+    return iterA(N1,N2,N3,N4);
+  }
+  Tensor4_ddg_numeral_01(const A &a, const int NN1, const int NN2)
+    :iterA(a), N1(NN1), N2(NN2) {}
+};
+
+/* Third and fourth slot. */
+
+template<class A, class T>
+class Tensor4_ddg_numeral_23
+{
+  A iterA;
+  const int N3, N4;
+public:
+  T operator()(const int N1, const int N2) const
+  {
+    return iterA(N1,N2,N3,N4);
+  }
+  Tensor4_ddg_numeral_23(const A &a, const int NN3, const int NN4)
+    :iterA(a), N3(NN3), N4(NN4) {}
+};
+
+/* First and third slot. */
+
+template<class A, class T>
+class Tensor4_ddg_numeral_02
+{
+  A iterA;
+  const int N1, N3;
+public:
+  T operator()(const int N2, const int N4) const
+  {
+    return iterA(N1,N2,N3,N4);
+  }
+  Tensor4_ddg_numeral_02(const A &a, const int NN1, const int NN3)
+    :iterA(a), N1(NN1), N3(NN3) {}
+};
+
+/* Only first slot */
+
+/* I think I have to be careful to make sure that the indices are
+   matched correctly, because the expression that calls it is a
+   Tensor3_dg. */
+
+template<class A, class T>
+class Tensor4_ddg_numeral_0
+{
+  A iterA;
+  const int N1;
+public:
+  T operator()(const int N2, const int N3, const int N4) const
+  {
+    return iterA(N1,N4,N2,N3);
+  }
+  Tensor4_ddg_numeral_0(const A &a, const int NN1):iterA(a), N1(NN1) {}
+};
+
+/* Second, third and fourth slot. */
+
+template<class A, class T>
+class Tensor4_ddg_numeral_123
+{
+  A iterA;
+  const int N1,N2,N3;
+public:
+  T operator()(const int N0) const
+  {
+    return iterA(N0,N1,N2,N3);
+  }
+  Tensor4_ddg_numeral_123(const A &a, const int NN1, const int NN2,
+			  const int NN3) : iterA(a), N1(NN1), N2(NN2), N3(NN3)
+  {}
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_or_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_or_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,76 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_ddg|Tensor2_symmetric and Tensor2_symmetric|Tensor4_ddg,
+   yielding a Tensor2_symmetric. */
+
+/* A(i,j,k,l)*B(j,l) */
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+class Tensor4_ddg_or_Tensor2_symmetric_13
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1,N2)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1,N2)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0,N2)*iterB(0,0);
+  }
+public:
+  Tensor4_ddg_or_Tensor2_symmetric_13
+  (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_or_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,k>
+operator|(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b)
+{
+  typedef const Tensor4_ddg_or_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
+/* B(j,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_or_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,i,k>
+operator|(const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_or_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim,i,k>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_or_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_or_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+/* Declares expressions of Tensor4_ddg || Tensor4_ddg.  This adds them in
+   a different way, but still ending up with a Tensor4_ddg. */
+
+/* A(i,j,k,l)+B(i,l,k,j) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+class Tensor4_ddg_or_Tensor4_ddg
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N3,N2,N4)+iterB(N1,N4,N2,N3);
+  }
+  Tensor4_ddg_or_Tensor4_ddg(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+			     const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b)
+    : iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_or_Tensor4_ddg<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,k,j,l>
+operator||(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	   const Tensor4_ddg_Expr<B,U,Dim,Dim,i,l,k,j> &b)
+{
+  typedef const Tensor4_ddg_or_Tensor4_ddg<A,B,T,U,Dim,i,j,k,l> TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k,j,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_plus_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_plus_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,68 @@
+/* Adds Tensor4_ddg+Tensor4_ddg -> Tensor4_ddg */
+
+/* A(i,j,k,l)+B(i,j,k,l) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_plus_Tensor4_ddg
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)+iterB(N1,N2,N3,N4);
+  }
+
+  Tensor4_ddg_plus_Tensor4_ddg(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a, const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &b):
+    iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_plus_Tensor4_ddg<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator+(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim01,Dim23,i,j,k,l> &b)
+{
+  typedef const Tensor4_ddg_plus_Tensor4_ddg<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)+B(k,l,i,j) -> Tensor4_ddg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_plus_Tensor4_ddg_2301
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor4_ddg_Expr<B,U,Dim23,Dim01,k,l,i,j> iterB;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)+iterB(N3,N4,N1,N2);
+  }
+
+  Tensor4_ddg_plus_Tensor4_ddg_2301
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor4_ddg_Expr<B,U,Dim23,Dim01,k,l,i,j> &b): iterA(a), iterB(b) {}
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_plus_Tensor4_ddg_2301<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator+(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim23,Dim01,k,l,i,j> &b)
+{
+  typedef const Tensor4_ddg_plus_Tensor4_ddg_2301<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_pointer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_pointer.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,236 @@
+/* A version for pointers. */
+
+template <class T, int Tensor_Dim01, int Tensor_Dim23>
+class Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>
+{
+  mutable T * restrict data[(Tensor_Dim01*(Tensor_Dim01+1))/2][(Tensor_Dim23*(Tensor_Dim23+1))/2];
+public:
+  /* There are two operator(int,int,int,int)'s, one for non-consts
+     that lets you change the value, and one for consts that
+     doesn't. */
+
+  T & operator()(const int N1, const int N2, const int N3, const int N4)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0 || N2>=Tensor_Dim01 || N2<0
+       || N3>=Tensor_Dim23 || N3<0 || N4>=Tensor_Dim23 || N4<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T*,"
+		  << Tensor_Dim01 << "," << Tensor_Dim23 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << "," << N4 << ")"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? (N3>N4 ? *data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+		    : *data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N4+(N3*(2*Tensor_Dim23-N3-1))/2])
+      : (N3>N4 ? *data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+	 : *data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N4+(N3*(2*Tensor_Dim23-N3-1))/2]);
+  }
+
+  T operator()(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0 || N2>=Tensor_Dim01 || N2<0
+       || N3>=Tensor_Dim23 || N3<0 || N4>=Tensor_Dim23 || N4<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T*,"
+		  << Tensor_Dim01 << "," << Tensor_Dim23 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << "," << N4 << ") const"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? (N3>N4 ? *data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+		    : *data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N4+(N3*(2*Tensor_Dim23-N3-1))/2])
+      : (N3>N4 ? *data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+	 : *data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N4+(N3*(2*Tensor_Dim23-N3-1))/2]);
+  }
+
+  T* ptr(const int N1, const int N2, const int N3, const int N4) const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0 || N2>=Tensor_Dim01 || N2<0
+       || N3>=Tensor_Dim23 || N3<0 || N4>=Tensor_Dim23 || N4<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T,"
+		  << Tensor_Dim01 << "," << Tensor_Dim23 << ">.ptr("
+		  << N1 << "," << N2 << "," << N3 << "," << N4 << ")"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? (N3>N4 ? data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+		    : data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N4+(N3*(2*Tensor_Dim23-N3-1))/2])
+      : (N3>N4 ? data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+	 : data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N4+(N3*(2*Tensor_Dim23-N3-1))/2]);
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  template<char i, char j, char k, char l, int Dim01, int Dim23>
+  Tensor4_ddg_Expr<Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,
+    T,Dim01,Dim23,i,j,k,l> operator()
+    (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+     const Index<k,Dim23> index3, const Index<l,Dim23> index4)
+  {
+    return Tensor4_ddg_Expr<Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,
+      T,Dim01,Dim23,i,j,k,l> (*this);
+  }
+
+
+  template<char i, char j, char k, char l, int Dim01, int Dim23>
+  const Tensor4_ddg_Expr<const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,
+    T,Dim01,Dim23,i,j,k,l> operator()
+    (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+     const Index<k,Dim23> index3, const Index<l,Dim23> index4) const
+  {
+    return Tensor4_ddg_Expr<const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,
+      T,Dim01,Dim23,i,j,k,l> (*this);
+  }
+
+  /* This is for expressions where a number is used for two slots, and
+     an index for the other two, yielding a Tensor2_symmetric_Expr. */
+
+  template<char i, char j, int N0, int N1, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor4_ddg_number_01
+  <const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,T,N0,N1>,T,Dim,i,j>
+  operator()(const Number<N0> n1, const Number<N1> n2,
+	     const Index<i,Dim> index1, const Index<j,Dim> index2) const
+  {
+    typedef const Tensor4_ddg_number_01<const Tensor4_ddg
+      <T*,Tensor_Dim01,Tensor_Dim23>,T,N0,N1> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int N0, int N1, int Dim>
+  Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01
+  <Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,T,N0,N1>,T,Dim,i,j>
+  operator()(const Number<N0> n1, const Number<N1> n2,
+	     const Index<i,Dim> index1, const Index<j,Dim> index2)
+  {
+    typedef Tensor4_ddg_number_rhs_01<Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,
+      T,N0,N1> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(*this);
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     an index for the other three, yielding a Tensor3_dg_Expr. */
+
+  template<char i, char j, char k, int N0, int Dim1, int Dim23>
+  const Tensor3_dg_Expr<const Tensor4_ddg_number_0
+  <const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,T,N0>,T,Dim23,Dim1,i,j,k>
+  operator()(const Number<N0> n1, const Index<k,Dim1> index3,
+	     const Index<i,Dim23> index1, const Index<j,Dim23> index2) const
+  {
+    typedef const Tensor4_ddg_number_0<const Tensor4_ddg
+      <T*,Tensor_Dim01,Tensor_Dim23>,T,N0> TensorExpr;
+    return Tensor3_dg_Expr<TensorExpr,T,Dim23,Dim1,i,j,k>(TensorExpr(*this));
+  }
+
+  template<char i, char j, char k, int N0, int Dim1, int Dim23>
+  Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0
+  <Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,T,N0>,T,Dim23,Dim1,i,j,k>
+  operator()(const Number<N0> n1, const Index<k,Dim1> index3,
+	     const Index<i,Dim23> index1, const Index<j,Dim23> index2)
+  {
+    typedef Tensor4_ddg_number_rhs_0<Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,
+      T,N0> TensorExpr;
+    return Tensor3_dg_Expr<TensorExpr,T,Dim23,Dim1,i,j,k>(*this);
+  }
+
+  /* This is for expressions where an int (not a Number) is used for
+     two slots, and an index for the other two, yielding a
+     Tensor2_symmetric_Expr. */
+
+  template<char i, char j, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor4_ddg_numeral_01
+  <const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i,j>
+  operator()(const int N0, const int N1,
+	     const Index<i,Dim> index1, const Index<j,Dim> index2) const
+  {
+    typedef const Tensor4_ddg_numeral_01<const Tensor4_ddg
+      <T*,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>
+      (TensorExpr(*this,N0,N1));
+  }
+
+  template<char i, char j, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor4_ddg_numeral_23
+  <const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const int N2, const int N3) const
+  {
+    typedef const Tensor4_ddg_numeral_23<const Tensor4_ddg
+      <T*,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>
+      (TensorExpr(*this,N2,N3));
+  }
+
+  /* int in three slots, Index in the other yielding a Tensor1_Expr. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor4_ddg_numeral_123<const Tensor4_ddg
+  <T*,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const int N1, const int N2,
+	     const int N3)
+  {
+    typedef const Tensor4_ddg_numeral_123<const Tensor4_ddg
+      <T*,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2,N3));
+  }
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor4_ddg_numeral_123<const Tensor4_ddg
+  <T*,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i>
+  operator()(const int N1, const Index<i,Dim> index1, const int N2,
+	     const int N3)
+  {
+    typedef const Tensor4_ddg_numeral_123<const Tensor4_ddg
+      <T*,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2,N3));
+  }
+
+  /* This is for expressions where an int (not a Number) is used for
+     one slot, and an index for the other three, yielding a
+     Tensor3_dg_Expr. */
+
+  template<char i, char j, char k, int Dim1, int Dim23>
+  const Tensor3_dg_Expr<const Tensor4_ddg_numeral_0
+  <const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim23,Dim1,i,j,k>
+  operator()(const int N0, const Index<k,Dim1> index3,
+	     const Index<i,Dim23> index1, const Index<j,Dim23> index2) const
+  {
+    typedef const Tensor4_ddg_numeral_0<const Tensor4_ddg
+      <T*,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor3_dg_Expr<TensorExpr,T,Dim23,Dim1,i,j,k>
+      (TensorExpr(*this,N0));
+  }
+
+  /* The ++ operator increments the pointer, not the number that the
+     pointer points to.  This allows iterating over a grid. */
+  
+  const Tensor4_ddg<T*,Tensor_Dim01,Tensor_Dim23> & operator++() const
+  {
+    for(int i=0;i<(Tensor_Dim01*(Tensor_Dim01+1))/2;++i)
+      for(int j=0;j<(Tensor_Dim01*(Tensor_Dim01+1))/2;++j)
+	++data[i][j];
+    return *this;
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_times_Tensor1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_times_Tensor1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,65 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_ddg*Tensor1 and Tensor1*Tensor4_ddg, yielding a
+   Tensor3_dg. */
+
+/* A(i,j,k,l)*B(k)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23, 
+  char i, char j, char k, char l>
+class Tensor4_ddg_times_Tensor1_2
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor1_Expr<B,U,Dim23,k> iterB;
+
+  template<int Current_Dim>
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<Current_Dim> &N)  const
+  {
+    return iterA(N1,N2,Current_Dim-1,N3)*iterB(Current_Dim-1)
+      + eval(N1,N2,N3,Number<Current_Dim-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2, const int N3,
+		       const Number<1> &N) const
+  {
+    return iterA(N1,N2,0,N3)*iterB(0);
+  }
+public:
+  Tensor4_ddg_times_Tensor1_2
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor1_Expr<B,U,Dim23,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3) const
+  {
+    return eval(N1,N2,N3,Number<Dim23>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23, 
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor4_ddg_times_Tensor1_2<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,l>
+operator*(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor1_Expr<B,U,Dim23,k> &b)
+{
+  typedef const Tensor4_ddg_times_Tensor1_2<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,l>
+    (TensorExpr(a,b));
+}
+
+/* B(k)*A(i,j,k,l)->Tensor3_dg */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23, 
+  char i, char j, char k, char l>
+inline const Tensor3_dg_Expr
+<const Tensor4_ddg_times_Tensor1_2<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,Dim23,i,j,l>
+operator*(const Tensor1_Expr<B,U,Dim23,k> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_times_Tensor1_2<A,B,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor3_dg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,l>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_times_Tensor2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_times_Tensor2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,147 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_ddg*Tensor2 and Tensor2*Tensor4_ddg, yielding a
+   Tensor2_symmetric. */
+
+/* A(i,j,k,l)*B(k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_times_Tensor2_23
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_Expr<B,U,Dim23,Dim23,k,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim23>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,N2,0,0)*iterB(0,0);
+  }
+public:
+  Tensor4_ddg_times_Tensor2_23
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_Expr<B,U,Dim23,Dim23,k,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim23>(),Number<Dim23>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_Expr<B,U,Dim23,Dim23,k,l> &b)
+{
+  typedef const Tensor4_ddg_times_Tensor2_23
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor2_Expr<B,U,Dim23,Dim23,k,l> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_times_Tensor2_23
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(l,k) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_times_Tensor2_32
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_Expr<B,U,Dim23,Dim23,l,k> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim23>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,N2,0,0)*iterB(0,0);
+  }
+public:
+  Tensor4_ddg_times_Tensor2_32
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_Expr<B,U,Dim23,Dim23,l,k> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim23>(),Number<Dim23>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_32<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_Expr<B,U,Dim23,Dim23,l,k> &b)
+{
+  typedef const Tensor4_ddg_times_Tensor2_32
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(l,k)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_32<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor2_Expr<B,U,Dim23,Dim23,l,k> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_times_Tensor2_32
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_times_Tensor2_symmetric.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_times_Tensor2_symmetric.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,218 @@
+/* This file has all of the declarations for expressions like
+   Tensor4_ddg*Tensor2_symmetric and Tensor2_symmetric*Tensor4_ddg,
+   yielding a Tensor2 or Tensor2_symmetric. */
+
+/* A(i,j,k,l)*B(j,l) */
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+class Tensor4_ddg_times_Tensor2_symmetric_13
+{
+  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim,j,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,N1,Current_Dim1-1,N2)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,N1,Current_Dim1-1,N2)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,N1,0,N2)*iterB(0,0);
+  }
+public:
+  Tensor4_ddg_times_Tensor2_symmetric_13
+  (const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim>(),Number<Dim>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+inline const Tensor2_Expr
+<const Tensor4_ddg_times_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,k>
+operator*(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b)
+{
+  typedef const Tensor4_ddg_times_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k>(TensorExpr(a,b));
+}
+
+/* B(j,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim, 
+  char i, char j, char k, char l>
+inline const Tensor2_Expr
+<const Tensor4_ddg_times_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>,
+  typename promote<T,U>::V,Dim,Dim,i,k>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim,j,l> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_times_Tensor2_symmetric_13<A,B,T,U,Dim,i,j,k,l>
+    TensorExpr;
+  return Tensor2_Expr<TensorExpr,typename promote<T,U>::V,Dim,Dim,i,k>(TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(i,j) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_times_Tensor2_symmetric_01
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(Current_Dim0-1,Current_Dim1-1,N1,N2)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(0,Current_Dim1-1,N1,N2)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim01>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(0,0,N1,N2)*iterB(0,0);
+  }
+public:
+  Tensor4_ddg_times_Tensor2_symmetric_01
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim01>(),Number<Dim01>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim23,k,l>
+operator*(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b)
+{
+  typedef const Tensor4_ddg_times_Tensor2_symmetric_01
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim23,k,l>
+    (TensorExpr(a,b));
+}
+
+/* B(i,j)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_symmetric_01<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim23,k,l>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim01,i,j> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_times_Tensor2_symmetric_01
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim23,k,l>
+    (TensorExpr(a,b));
+}
+
+/* A(i,j,k,l)*B(k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_times_Tensor2_symmetric_23
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const Tensor2_symmetric_Expr<B,U,Dim23,k,l> iterB;
+
+  template<int Current_Dim0, int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<Current_Dim0> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,Current_Dim0-1,Current_Dim1-1)
+      *iterB(Current_Dim0-1,Current_Dim1-1)
+      + eval(N1,N2,Number<Current_Dim0-1>(),Number<Current_Dim1>());
+  }
+  template<int Current_Dim1>
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<Current_Dim1> &ND1)  const
+  {
+    return iterA(N1,N2,0,Current_Dim1-1)*iterB(0,Current_Dim1-1)
+      + eval(N1,N2,Number<Dim23>(),Number<Current_Dim1-1>());
+  }
+  typename promote<T,U>::V eval(const int N1, const int N2,
+		       const Number<1> &ND0,
+		       const Number<1> &ND1)  const
+  {
+    return iterA(N1,N2,0,0)*iterB(0,0);
+  }
+public:
+  Tensor4_ddg_times_Tensor2_symmetric_23
+  (const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+   const Tensor2_symmetric_Expr<B,U,Dim23,k,l> &b): iterA(a), iterB(b) {}
+  typename promote<T,U>::V operator()(const int N1, const int N2) const
+  {
+    return eval(N1,N2,Number<Dim23>(),Number<Dim23>());
+  }
+};
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+	  const Tensor2_symmetric_Expr<B,U,Dim23,k,l> &b)
+{
+  typedef const Tensor4_ddg_times_Tensor2_symmetric_23
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
+
+/* B(k,l)*A(i,j,k,l) */
+
+template<class A, class B, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor2_symmetric_Expr
+<const Tensor4_ddg_times_Tensor2_symmetric_23<A,B,T,U,Dim01,Dim23,i,j,k,l>,
+  typename promote<T,U>::V,Dim01,i,j>
+operator*(const Tensor2_symmetric_Expr<B,U,Dim23,k,l> &b,
+	  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_times_Tensor2_symmetric_23
+    <A,B,T,U,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor2_symmetric_Expr<TensorExpr,typename promote<T,U>::V,Dim01,i,j>
+    (TensorExpr(a,b));
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_times_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_times_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,96 @@
+/* Fully contract a Tensor4_ddg with a Tensor4_ddg. */
+
+/* A(i,j,k,l)*B(i,k,j,l) */
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  char k, char l,
+  int Current_Dim0, int Current_Dim1, int Current_Dim2, int Current_Dim3>
+inline const typename promote<T,U>::V
+T4ddg_times_T4ddg_0213(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	      const Tensor4_ddg_Expr<B,U,Dim,Dim,i,k,j,l> &b,
+	      const Number<Current_Dim0> &N0,
+	      const Number<Current_Dim1> &N1,
+	      const Number<Current_Dim2> &N2,
+	      const Number<Current_Dim3> &N3)
+{
+  return a(Current_Dim0-1,Current_Dim1-1,Current_Dim2-1,Current_Dim3-1)
+    *b(Current_Dim0-1,Current_Dim2-1,Current_Dim1-1,Current_Dim3-1)
+    + T4ddg_times_T4ddg_0213(a,b,Number<Current_Dim0-1>(),
+			     Number<Current_Dim1>(),Number<Current_Dim2>(),
+			     Number<Current_Dim3>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  char k, char l, int Current_Dim1, int Current_Dim2, int Current_Dim3>
+inline const typename promote<T,U>::V
+T4ddg_times_T4ddg_0213(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	      const Tensor4_ddg_Expr<B,U,Dim,Dim,i,k,j,l> &b,
+	      const Number<1> &N0,
+	      const Number<Current_Dim1> &N1,
+	      const Number<Current_Dim2> &N2,
+	      const Number<Current_Dim3> &N3)
+{
+  return a(0,Current_Dim1-1,Current_Dim2-1,Current_Dim3-1)
+    *b(0,Current_Dim2-1,Current_Dim1-1,Current_Dim3-1)
+    + T4ddg_times_T4ddg_0213(a,b,Number<Dim>(),
+			     Number<Current_Dim1-1>(),Number<Current_Dim2>(),
+			     Number<Current_Dim3>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  char k, char l, int Current_Dim2, int Current_Dim3>
+inline const typename promote<T,U>::V
+T4ddg_times_T4ddg_0213(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+		       const Tensor4_ddg_Expr<B,U,Dim,Dim,i,k,j,l> &b,
+		       const Number<1> &N0,
+		       const Number<1> &N1,
+		       const Number<Current_Dim2> &N2,
+		       const Number<Current_Dim3> &N3)
+{
+  return a(0,0,Current_Dim2-1,Current_Dim3-1)
+    *b(0,Current_Dim2-1,0,Current_Dim3-1)
+    + T4ddg_times_T4ddg_0213(a,b,Number<Dim>(),
+			     Number<Dim>(),Number<Current_Dim2-1>(),
+			     Number<Current_Dim3>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  char k, char l, int Current_Dim3>
+inline const typename promote<T,U>::V
+T4ddg_times_T4ddg_0213(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+		       const Tensor4_ddg_Expr<B,U,Dim,Dim,i,k,j,l> &b,
+		       const Number<1> &N0,
+		       const Number<1> &N1,
+		       const Number<1> &N2,
+		       const Number<Current_Dim3> &N3)
+{
+  return a(0,0,0,Current_Dim3-1)
+    *b(0,0,0,Current_Dim3-1)
+    + T4ddg_times_T4ddg_0213(a,b,Number<Dim>(),
+			     Number<Dim>(),Number<Dim>(),
+			     Number<Current_Dim3-1>());
+}
+
+template<class A, class B, class T, class U, int Dim, char i, char j,
+  char k, char l>
+inline const typename promote<T,U>::V
+T4ddg_times_T4ddg_0213(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+		       const Tensor4_ddg_Expr<B,U,Dim,Dim,i,k,j,l> &b,
+		       const Number<1> &N0,
+		       const Number<1> &N1,
+		       const Number<1> &N2,
+		       const Number<1> &N3)
+{
+  return a(0,0,0,0)*b(0,0,0,0);
+}
+
+template<class A, class B, class T, class U, int Dim,
+  char i, char j, char k, char l>
+inline const typename promote<T,U>::V
+operator*(const Tensor4_ddg_Expr<A,T,Dim,Dim,i,j,k,l> &a,
+	  const Tensor4_ddg_Expr<B,U,Dim,Dim,i,k,j,l> &b)
+{
+  return T4ddg_times_T4ddg_0213(a,b,Number<Dim>(),Number<Dim>(),Number<Dim>(),
+				Number<Dim>());
+}
+
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_times_generic.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_times_generic.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,43 @@
+/* Multiplies a Tensor4_ddg with a generic, yielding a
+   Tensor4_ddg. */
+
+template<class A, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+class Tensor4_ddg_times_generic
+{
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+  const U d;
+public:
+  typename promote<T,U>::V operator()(const int N1, const int N2, const int N3,
+			     const int N4) const
+  {
+    return iterA(N1,N2,N3,N4)*d;
+  }
+
+  Tensor4_ddg_times_generic(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a,
+				  const U &d0): iterA(a), d(d0) {}
+};
+
+template<class A, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_times_generic<A,T,U,Dim01,Dim23,i,j,k,l>,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator*(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a, const U &d0)
+{
+  typedef const Tensor4_ddg_times_generic<A,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,d0));
+}
+
+template<class A, class T, class U, int Dim01, int Dim23,
+  char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr
+<const Tensor4_ddg_times_generic<A,T,U,Dim01,Dim23,i,j,k,l>,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+operator*(const U &d0, const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const Tensor4_ddg_times_generic<A,T,U,Dim01,Dim23,i,j,k,l>
+    TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,typename promote<T,U>::V,Dim01,Dim23,i,j,k,l>
+    (TensorExpr(a,d0));
+}
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/Tensor4_ddg_value.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/Tensor4_ddg_value.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,216 @@
+/* A general version, not for pointers. */
+
+template <class T, int Tensor_Dim01, int Tensor_Dim23>
+class Tensor4_ddg
+{
+  T data[(Tensor_Dim01*(Tensor_Dim01+1))/2][(Tensor_Dim23*(Tensor_Dim23+1))/2];
+public:
+  /* There are two operator(int,int,int,int)'s, one for non-consts
+     that lets you change the value, and one for consts that
+     doesn't. */
+
+  T & operator()(const int N1, const int N2, const int N3, const int N4)
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0 || N2>=Tensor_Dim01 || N2<0
+       || N3>=Tensor_Dim23 || N3<0 || N4>=Tensor_Dim23 || N4<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T,"
+		  << Tensor_Dim01 << "," << Tensor_Dim23 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << "," << N4 << ")"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? (N3>N4 ? data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+		    : data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N4+(N3*(2*Tensor_Dim23-N3-1))/2])
+      : (N3>N4 ? data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+	 : data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N4+(N3*(2*Tensor_Dim23-N3-1))/2]);
+  }
+
+  T operator()(const int N1, const int N2, const int N3, const int N4)
+    const
+  {
+#ifdef FTENSOR_DEBUG
+    if(N1>=Tensor_Dim01 || N1<0 || N2>=Tensor_Dim01 || N2<0
+       || N3>=Tensor_Dim23 || N3<0 || N4>=Tensor_Dim23 || N4<0)
+      {
+	std::cerr << "Bad index in Tensor3_dg<T,"
+		  << Tensor_Dim01 << "," << Tensor_Dim23 << ">.operator("
+		  << N1 << "," << N2 << "," << N3 << "," << N4 << ") const"
+		  << std::endl;
+	abort();
+      }
+#endif
+    return N1>N2 ? (N3>N4 ? data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+		    : data[N1+(N2*(2*Tensor_Dim01-N2-1))/2]
+		    [N4+(N3*(2*Tensor_Dim23-N3-1))/2])
+      : (N3>N4 ? data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N3+(N4*(2*Tensor_Dim23-N4-1))/2]
+	 : data[N2+(N1*(2*Tensor_Dim01-N1-1))/2]
+	 [N4+(N3*(2*Tensor_Dim23-N3-1))/2]);
+  }
+
+  /* These operator()'s are the first part in constructing template
+     expressions.  They can be used to slice off lower dimensional
+     parts. They are not entirely safe, since you can accidently use a
+     higher dimension than what is really allowed (like Dim=5). */
+
+  template<char i, char j, char k, char l, int Dim01, int Dim23>
+  Tensor4_ddg_Expr<Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,
+    T,Dim01,Dim23,i,j,k,l> operator()
+    (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+     const Index<k,Dim23> index3, const Index<l,Dim23> index4)
+  {
+    return Tensor4_ddg_Expr<Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,
+      T,Dim01,Dim23,i,j,k,l> (*this);
+  }
+
+
+  template<char i, char j, char k, char l, int Dim01, int Dim23>
+  const Tensor4_ddg_Expr<const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,
+    T,Dim01,Dim23,i,j,k,l> operator()
+    (const Index<i,Dim01> index1, const Index<j,Dim01> index2,
+     const Index<k,Dim23> index3, const Index<l,Dim23> index4) const
+  {
+    return Tensor4_ddg_Expr<const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,
+      T,Dim01,Dim23,i,j,k,l> (*this);
+  }
+
+  /* This is for expressions where a number is used for two slots, and
+     an index for the other two, yielding a Tensor2_symmetric_Expr. */
+
+  template<char i, char j, int N0, int N1, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor4_ddg_number_01
+  <const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T,N0,N1>,T,Dim,i,j>
+  operator()(const Number<N0> n1, const Number<N1> n2,
+	     const Index<i,Dim> index1, const Index<j,Dim> index2) const
+  {
+    typedef const Tensor4_ddg_number_01<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T,N0,N1> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(TensorExpr(*this));
+  }
+
+  template<char i, char j, int N0, int N1, int Dim>
+  Tensor2_symmetric_Expr<Tensor4_ddg_number_rhs_01
+  <Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T,N0,N1>,T,Dim,i,j>
+  operator()(const Number<N0> n1, const Number<N1> n2,
+	     const Index<i,Dim> index1, const Index<j,Dim> index2)
+  {
+    typedef Tensor4_ddg_number_rhs_01<Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,
+      T,N0,N1> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>(*this);
+  }
+
+  /* This is for expressions where a number is used for one slot, and
+     an index for the other three, yielding a Tensor3_dg_Expr. */
+
+  template<char i, char j, char k, int N0, int Dim1, int Dim23>
+  const Tensor3_dg_Expr<const Tensor4_ddg_number_0
+  <const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T,N0>,T,Dim23,Dim1,i,j,k>
+  operator()(const Number<N0> n1, const Index<k,Dim1> index3,
+	     const Index<i,Dim23> index1, const Index<j,Dim23> index2) const
+  {
+    typedef const Tensor4_ddg_number_0<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T,N0> TensorExpr;
+    return Tensor3_dg_Expr<TensorExpr,T,Dim23,Dim1,i,j,k>(TensorExpr(*this));
+  }
+
+  template<char i, char j, char k, int N0, int Dim1, int Dim23>
+  Tensor3_dg_Expr<Tensor4_ddg_number_rhs_0
+  <Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T,N0>,T,Dim23,Dim1,i,j,k>
+  operator()(const Number<N0> n1, const Index<k,Dim1> index3,
+	     const Index<i,Dim23> index1, const Index<j,Dim23> index2)
+  {
+    typedef Tensor4_ddg_number_rhs_0<Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,
+      T,N0> TensorExpr;
+    return Tensor3_dg_Expr<TensorExpr,T,Dim23,Dim1,i,j,k>(*this);
+  }
+
+  /* This is for expressions where an int (not a Number) is used for
+     two slots, and an index for the other two, yielding a
+     Tensor2_symmetric_Expr. */
+
+  template<char i, char j, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor4_ddg_numeral_01
+  <const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i,j>
+  operator()(const int N0, const int N1,
+	     const Index<i,Dim> index1, const Index<j,Dim> index2) const
+  {
+    typedef const Tensor4_ddg_numeral_01<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>
+      (TensorExpr(*this,N0,N1));
+  }
+
+  template<char i, char j, int Dim>
+  const Tensor2_symmetric_Expr<const Tensor4_ddg_numeral_23
+  <const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i,j>
+  operator()(const Index<i,Dim> index1, const Index<j,Dim> index2,
+	     const int N2, const int N3) const
+  {
+    typedef const Tensor4_ddg_numeral_23<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor2_symmetric_Expr<TensorExpr,T,Dim,i,j>
+      (TensorExpr(*this,N2,N3));
+  }
+
+  /* int in two slots but yielding a Tensor2 */
+
+  template<char i, char j, int Dim1, int Dim3>
+  const Tensor2_Expr<const Tensor4_ddg_numeral_02
+  <const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim1,Dim3,i,j>
+  operator()(const int N0, const Index<i,Dim1> index1,
+	     const int N2, const Index<j,Dim3> index3) const
+  {
+    typedef const Tensor4_ddg_numeral_02<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor2_Expr<TensorExpr,T,Dim1,Dim3,i,j>
+      (TensorExpr(*this,N0,N2));
+  }
+
+  /* int in three slots, Index in the other yielding a Tensor1_Expr. */
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor4_ddg_numeral_123<const Tensor4_ddg
+  <T,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i>
+  operator()(const Index<i,Dim> index1, const int N1, const int N2,
+	     const int N3)
+  {
+    typedef const Tensor4_ddg_numeral_123<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2,N3));
+  }
+
+  template<char i, int Dim>
+  const Tensor1_Expr<const Tensor4_ddg_numeral_123<const Tensor4_ddg
+  <T,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim,i>
+  operator()(const int N1, const Index<i,Dim> index1, const int N2,
+	     const int N3)
+  {
+    typedef const Tensor4_ddg_numeral_123<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor1_Expr<TensorExpr,T,Dim,i>(TensorExpr(*this,N1,N2,N3));
+  }
+
+  /* This is for expressions where an int (not a Number) is used for
+     one slot, and an index for the other three, yielding a
+     Tensor3_dg_Expr. */
+
+  template<char i, char j, char k, int Dim1, int Dim23>
+  const Tensor3_dg_Expr<const Tensor4_ddg_numeral_0
+  <const Tensor4_ddg<T,Tensor_Dim01,Tensor_Dim23>,T>,T,Dim23,Dim1,i,j,k>
+  operator()(const int N0, const Index<k,Dim1> index3,
+	     const Index<i,Dim23> index1, const Index<j,Dim23> index2) const
+  {
+    typedef const Tensor4_ddg_numeral_0<const Tensor4_ddg
+      <T,Tensor_Dim01,Tensor_Dim23>,T> TensorExpr;
+    return Tensor3_dg_Expr<TensorExpr,T,Dim23,Dim1,i,j,k>
+      (TensorExpr(*this,N0));
+  }
+};
diff -r 000000000000 -r 34fc4fd9248b Tensor4_ddg/minus_Tensor4_ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Tensor4_ddg/minus_Tensor4_ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,24 @@
+/* Unary minus operator. */
+
+template<class A, class T, int Dim01, int Dim23, char i, char j, char k, char l>
+class minus_Tensor4_ddg
+{
+public:
+  const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> iterA;
+public:
+  T operator()(const int N1, const int N2, const int N3, const int N4) const
+  {
+    return -iterA(N1,N2,N3,N4);
+  }
+  minus_Tensor4_ddg(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a):
+    iterA(a) {}
+};
+
+template<class A, class T, int Dim01, int Dim23, char i, char j, char k, char l>
+inline const Tensor4_ddg_Expr<const minus_Tensor4_ddg<A,T,Dim01,Dim23,i,j,k,l>,
+  T,Dim01,Dim23,i,j,k,l>
+operator-(const Tensor4_ddg_Expr<A,T,Dim01,Dim23,i,j,k,l> &a)
+{
+  typedef const minus_Tensor4_ddg<A,T,Dim01,Dim23,i,j,k,l> TensorExpr;
+  return Tensor4_ddg_Expr<TensorExpr,T,Dim01,Dim23,i,j,k,l>(TensorExpr(a));
+}
diff -r 000000000000 -r 34fc4fd9248b derivative_delta.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/derivative_delta.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,16 @@
+template <int Dim>
+class derivative_delta
+{
+public:
+  Tensor1<int,Dim> d_ijk_plus, d_ijk_minus;
+  Tensor1<double,Dim> d_xyz;
+  
+  derivative_delta(double dx, double dy, double dz, int di, int dj, int dk)
+    : d_ijk_plus(di,dj,dk), d_ijk_minus(di,dj,dk), d_xyz(dx,dy,dz) {}
+
+  derivative_delta(double dx, double dy, double dz,
+		   int di_plus, int dj_plus, int dk_plus,
+		   int di_minus, int dj_minus, int dk_minus)
+    : d_ijk_plus(di_plus,dj_plus,dk_plus),
+      d_ijk_minus(di_minus,dj_minus,dk_minus), d_xyz(dx,dy,dz) {}
+};
diff -r 000000000000 -r 34fc4fd9248b promote.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/promote.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,26 @@
+/* Traits that allow auto-promotion of int's to double's, double's to
+   complex, etc.  Shamelessly stolen from
+   
+   http://extreme.indiana.edu/~tveldhui/papers/techniques/
+   
+   For now, only int, double, and complex<double> are covered.  If you
+   want more, just insert a DECLARE_PROMOTE(A,B,C), where A and B are
+   the two types, and C is what they should be coerced to.  */
+
+template<class T1, class T2>
+class promote {
+public:
+  typedef T1 V;
+};
+
+#define DECLARE_PROMOTE(A,B,C) \
+template<> class promote<A,B > { public: typedef C V; }
+
+DECLARE_PROMOTE(int,double,double);
+DECLARE_PROMOTE(double,int,double);
+DECLARE_PROMOTE(int,std::complex<double>,std::complex<double>);
+DECLARE_PROMOTE(std::complex<double>,int,std::complex<double>);
+DECLARE_PROMOTE(double,std::complex<double>,std::complex<double>);
+DECLARE_PROMOTE(std::complex<double>,double,std::complex<double>);
+
+#undef DECLARE_PROMOTE
diff -r 000000000000 -r 34fc4fd9248b tests/README
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/README	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,83 @@
+There are two kinds of tests in these directories.  The tests in
+conformance exercise almost all of the possible operations (it doesn't
+fully exercise the Tensor4_Riemann class, but that class has other
+problems, such as not being dimension-independent).  The tests in
+speed compare how fast the FTensor's are compared to ordinary arrays.
+
+You may have to edit the Makefile's in each of the directories to set
+the compiler (CXX) and its flags (CXXFLAGS).  You can set optimization
+options only by changing (CXXOPTIMIZE).  Alternately, you can specify
+them on the command line, as in
+
+	make CXX=<compiler> CXXOPTIMIZE="<flags>" test_compiler
+
+The default compiler is g++.  I believe that GNU make is required.
+
+------------------
+
+Once the Makefile is set to your pleasure, running the tests in
+conformance should be as simple as typing
+
+	make
+	test_all > test_results
+
+The file "test_results" will contain thousands of lines which should
+say
+
+PASS: (unique name of test)
+
+If a test fails, it will print out
+
+FAIL: (unique name of test)
+
+None of the tests should fail.
+
+------------------
+
+Running the tests in speed should just be
+
+	one_over_script
+
+This will compile all of the programs and then run them.  It will time
+each one, with the output looking like
+
+	fast 1
+	
+	real    0m9.866s
+	user    0m9.720s
+	sys     0m0.000s
+	Tensor 1
+	
+	real    0m19.891s
+	user    0m19.740s
+	sys     0m0.040s
+	.
+	.
+	.
+
+and then followed by a series of lines that say PASS: (unique name) or
+FAIL:(unique name).
+
+This is timing two different implementations of an equation.  One uses
+ordinary arrays, and the other uses FTensor's.  As you can see, the
+FTensor implementation can be much slower than the ordinary array.  It
+depends on the compiler.  The PASS and FAIL messages are calculated by
+comparing the final results of the two computations.  All of the tests
+should pass.
+
+---------------------------
+
+The conformance tests check almost all of the possible operations to
+make sure that they are coded correctly and the compiler didn't do
+anything funny.  If you're just interested in testing your compiler, a
+quick and dirty method is to make just the "little" and "littlefast"
+executables in the speed directory.  If it compiles, they should
+output the same thing:
+
+	7e+08 9e+08 1.1e+09
+
+A more complete test is to make "test_compiler" in the conformance
+directory.  This will make a subset of the complete conformance test,
+enough to check every construct that is used in the code.  It should
+compile much faster, especially with optimizations.
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/Makefile	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+all: test_all
+VPATH=T2:T2s:T3:T3as:T3dg:T4ddg
+
+CXX = g++-3.2
+CXXOPTIMIZE =
+CXXFLAGS=-ftemplate-depth-100 -Drestrict= -DFTENSOR_DEBUG $(CXXOPTIMIZE)
+# CXXFLAGS=-O3 -ftemplate-depth-100 -Drestrict=__restrict__
+
+# CXX = /home/boo/foreign_compilers/usr/local/KAI/KCC.pu-4.0d-1/KCC_BASE/bin/KCC
+# # CXXFLAGS=+K3 --restrict --no_exceptions --inline_auto_space_time=750000000000000 --inline_implicit_space_time=200000000000000 --inline_generated_space_time=40000000000000.0 --inline_auto_space_time=100000000000000.0 --max_pending_instantiations 100
+# CXXFLAGS= -g --restrict --no_exceptions --max_pending_instantiations 100 -DFTENSOR_DEBUG
+# # CXXFLAGS= --restrict --no_exceptions --max_pending_instantiations 100
+# # CXXFLAGS= -Drestrict=
+
+# CXX = icc
+# CXXFLAGS= -restrict -O0 -g -DFTENSOR_DEBUG -lcprts -lcxa -lguide -limf -lirc -lircmt -lsvml 
+
+# CXX = pgCC
+# CXXFLAGS = -Drestrict= -DFTENSOR_DEBUG
+
+# CXX = /home/boo/Compilers/Intel/opt/intel/compiler60/ia32/bin/icc
+# CXXFLAGS = -restrict -DFTENSOR_DEBUG
+
+
+TENSOR0=test_T0.o
+TENSOR1=test_T1.o
+
+TENSOR2=test_T2.o test_T2I.o test_T2II.o test_T2III.o test_T2IV.o test_T2V.o test_T2VI.o test_T2VII.o test_T2VIII.o test_T2IX.o test_T2X.o test_T2XI.o test_T2XII.o test_T2XIII.o test_T2XIV.o test_T2XV.o test_T2XVI.o test_T2XVII.o test_T2XVIII.o test_T2XIX.o test_T2XX.o test_T2XXI.o test_T2XXII.o test_T2XXIII.o test_T2XXIV.o test_T2XXV.o test_T2XXVI.o test_T2XXVII.o test_T2XXVIII.o test_T2XXIX.o test_T2XXX.o test_T2XXXI.o test_T2XXXII.o test_T2XXXIII.o test_T2XXXIV.o test_T2XXXV.o test_T2XXXVI.o test_T2XXXVII.o test_T2XXXVIII.o
+TENSOR2S=test_T2s.o test_T2sI.o test_T2sII.o test_T2sIII.o test_T2sIV.o test_T2sV.o test_T2sVI.o test_T2sVII.o test_T2sVIII.o test_T2sIX.o test_T2sX.o test_T2sXI.o test_T2sXII.o test_T2sXIII.o test_T2sXIV.o test_T2sXV.o test_T2sXVI.o test_T2sXVII.o test_T2sXVIII.o test_T2sXIX.o test_T2sXX.o test_T2sXXI.o test_T2sXXII.o test_T2sXXIII.o test_T2sXXIV.o test_T2sXXV.o test_T2sXXVI.o test_T2sXXVII.o test_T2sXXVIII.o test_T2sXXIX.o test_T2sXXX.o test_T2sXXXI.o test_T2sXXXII.o test_T2sXXXIII.o test_T2sXXXIV.o test_T2sXXXV.o test_T2sXXXVI.o test_T2sXXXVII.o test_T2sXXXVIII.o test_T2sXXXIX.o test_T2sXL.o test_T2sXLI.o test_T2sXLII.o test_T2sXLIII.o test_T2sXLIV.o
+
+TENSOR3=test_T3.o test_T3II.o
+TENSOR3AS=test_T3as.o test_T3asI.o test_T3asII.o test_T3asIII.o test_T3asIV.o test_T3asV.o test_T3asVI.o test_T3asVII.o test_T3asVIII.o test_T3asIX.o test_T3asX.o test_T3asXI.o test_T3asXII.o test_T3asXIII.o test_T3asXIV.o
+TENSOR3CH=test_T3ch.o
+TENSOR3DG=test_T3dg.o test_T3dgI.o test_T3dgII.o test_T3dgIII.o test_T3dgIV.o test_T3dgV.o test_T3dgVI.o test_T3dgVII.o test_T3dgVIII.o test_T3dgIX.o test_T3dgX.o test_T3dgXI.o test_T3dgXII.o test_T3dgXIII.o test_T3dgXIV.o test_T3dgXV.o test_T3dgXVI.o test_T3dgXVII.o test_T3dgXVIII.o test_T3dgXIX.o  test_T3dgXX.o test_T3dgXXI.o test_T3dgXXII.o test_T3dgXXIII.o test_T3dgXXIV.o test_T3dgXXV.o test_T3dgXXVI.o test_T3dgXXVII.o test_T3dgXXVIII.o test_T3dgXXIX.o test_T3dgXXX.o test_T3dgXXXI.o test_T3dgXXXII.o test_T3dgXXXIII.o test_T3dgXXXIV.o test_T3dgXXXV.o test_T3dgCII.o test_T3dgCIII.o
+TENSOR4DDG=test_T4ddg.o test_T4ddgII.o test_T4ddgIII.o test_T4ddgIV.o test_T4ddgV.o
+TENSOR4R=test_T4R.o
+
+testing_files=$(TENSOR0) $(TENSOR1) $(TENSOR2) $(TENSOR2S) $(TENSOR3) $(TENSOR3AS) $(TENSOR3CH) $(TENSOR3DG) $(TENSOR4DDG) $(TENSOR4R) testcases.o
+
+test_all: $(testing_files)
+	$(CXX) $(CXXFLAGS) -o test_all $(testing_files)
+
+compiler_files=$(TENSOR0) $(TENSOR1) $(TENSOR2) $(TENSOR2S) $(TENSOR3AS) $(TENSOR3CH) testcases_compiler.o
+
+test_compiler: $(compiler_files)
+	$(CXX) $(CXXFLAGS) -o test_compiler $(compiler_files)
+
+clean:
+	rm -f *.o test_all test_compiler
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,415 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+extern
+void test_T2I(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2II(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2III(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2IV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2V(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2VI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2VII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2VIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2IX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2X(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2XXXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2IXL(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
+
+void test_T2(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  test_T2I(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2II(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2III(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2IV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2V(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2VI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2VII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2VIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2IX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2X(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2XXXVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+//   test_T2XXXIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+//   test_T2XL(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2I.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2I.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,38 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2I(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,j)=t1_1(i)*t1_2(j);
+  test_for_zero(t2_1(0,0)-t1_1(0)*t1_2(0),"T2(i,j)=T1(i)*T1(j)(0,0)");
+  test_for_zero(t2_1(0,1)-t1_1(0)*t1_2(1),"T2(i,j)=T1(i)*T1(j)(0,1)");
+  test_for_zero(t2_1(0,2)-t1_1(0)*t1_2(2),"T2(i,j)=T1(i)*T1(j)(0,2)");
+  test_for_zero(t2_1(1,0)-t1_1(1)*t1_2(0),"T2(i,j)=T1(i)*T1(j)(1,0)");
+  test_for_zero(t2_1(1,1)-t1_1(1)*t1_2(1),"T2(i,j)=T1(i)*T1(j)(1,1)");
+  test_for_zero(t2_1(1,2)-t1_1(1)*t1_2(2),"T2(i,j)=T1(i)*T1(j)(1,2)");
+  test_for_zero(t2_1(2,0)-t1_1(2)*t1_2(0),"T2(i,j)=T1(i)*T1(j)(2,0)");
+  test_for_zero(t2_1(2,1)-t1_1(2)*t1_2(1),"T2(i,j)=T1(i)*T1(j)(2,1)");
+  test_for_zero(t2_1(2,2)-t1_1(2)*t1_2(2),"T2(i,j)=T1(i)*T1(j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2II.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2II.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2II(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(N0,i)=t1_1(i);
+  t2_1(N1,i)=t1_1(i);
+  t2_1(N2,i)=t1_1(i);
+  test_for_zero(t2_1(0,0)-t1_1(0),"T2(N,i)=T1(i)(0,0)");
+  test_for_zero(t2_1(0,1)-t1_1(1),"T2(N,i)=T1(i)(0,1)");
+  test_for_zero(t2_1(0,2)-t1_1(2),"T2(N,i)=T1(i)(0,2)");
+  test_for_zero(t2_1(1,0)-t1_1(0),"T2(N,i)=T1(i)(1,0)");
+  test_for_zero(t2_1(1,1)-t1_1(1),"T2(N,i)=T1(i)(1,1)");
+  test_for_zero(t2_1(1,2)-t1_1(2),"T2(N,i)=T1(i)(1,2)");
+  test_for_zero(t2_1(2,0)-t1_1(0),"T2(N,i)=T1(i)(2,0)");
+  test_for_zero(t2_1(2,1)-t1_1(1),"T2(N,i)=T1(i)(2,1)");
+  test_for_zero(t2_1(2,2)-t1_1(2),"T2(N,i)=T1(i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2III.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2III.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2III(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(N0,i)=10;
+  t2_1(N1,i)=11;
+  t2_1(N2,i)=12;
+  test_for_zero(t2_1(0,0)-10,"T2(N,i)=T(0,0)");
+  test_for_zero(t2_1(0,1)-10,"T2(N,i)=T(0,1)");
+  test_for_zero(t2_1(0,2)-10,"T2(N,i)=T(0,2)");
+  test_for_zero(t2_1(1,0)-11,"T2(N,i)=T(1,0)");
+  test_for_zero(t2_1(1,1)-11,"T2(N,i)=T(1,1)");
+  test_for_zero(t2_1(1,2)-11,"T2(N,i)=T(1,2)");
+  test_for_zero(t2_1(2,0)-12,"T2(N,i)=T(2,0)");
+  test_for_zero(t2_1(2,1)-12,"T2(N,i)=T(2,1)");
+  test_for_zero(t2_1(2,2)-12,"T2(N,i)=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2IV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2IV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2IV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(N0,i)+=10;
+  t2_1(N1,i)+=29;
+  t2_1(N2,i)+=48;
+  test_for_zero(t2_1(0,0)-20,"T2(N,i)+=T(0,0)");
+  test_for_zero(t2_1(0,1)-20,"T2(N,i)+=T(0,1)");
+  test_for_zero(t2_1(0,2)-20,"T2(N,i)+=T(0,2)");
+  test_for_zero(t2_1(1,0)-40,"T2(N,i)+=T(1,0)");
+  test_for_zero(t2_1(1,1)-40,"T2(N,i)+=T(1,1)");
+  test_for_zero(t2_1(1,2)-40,"T2(N,i)+=T(1,2)");
+  test_for_zero(t2_1(2,0)-60,"T2(N,i)+=T(2,0)");
+  test_for_zero(t2_1(2,1)-60,"T2(N,i)+=T(2,1)");
+  test_for_zero(t2_1(2,2)-60,"T2(N,i)+=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2IX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2IX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2IX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,N0)=10;
+  t2_1(i,N1)=11;
+  t2_1(i,N2)=12;
+  test_for_zero(t2_1(0,0)-10,"T2(i,N)=T(0,0)");
+  test_for_zero(t2_1(1,0)-10,"T2(i,N)=T(1,0)");
+  test_for_zero(t2_1(2,0)-10,"T2(i,N)=T(2,0)");
+  test_for_zero(t2_1(0,1)-11,"T2(i,N)=T(0,1)");
+  test_for_zero(t2_1(1,1)-11,"T2(i,N)=T(1,1)");
+  test_for_zero(t2_1(2,1)-11,"T2(i,N)=T(2,1)");
+  test_for_zero(t2_1(0,2)-12,"T2(i,N)=T(0,2)");
+  test_for_zero(t2_1(1,2)-12,"T2(i,N)=T(1,2)");
+  test_for_zero(t2_1(2,2)-12,"T2(i,N)=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2V.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2V.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2V(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(N0,i)-=10;
+  t2_1(N1,i)-=29;
+  t2_1(N2,i)-=48;
+  test_for_zero(t2_1(0,0)-10,"T2(N,i)-=T(0,0)");
+  test_for_zero(t2_1(0,1)-10,"T2(N,i)-=T(0,1)");
+  test_for_zero(t2_1(0,2)-10,"T2(N,i)-=T(0,2)");
+  test_for_zero(t2_1(1,0)-11,"T2(N,i)-=T(1,0)");
+  test_for_zero(t2_1(1,1)-11,"T2(N,i)-=T(1,1)");
+  test_for_zero(t2_1(1,2)-11,"T2(N,i)-=T(1,2)");
+  test_for_zero(t2_1(2,0)-12,"T2(N,i)-=T(2,0)");
+  test_for_zero(t2_1(2,1)-12,"T2(N,i)-=T(2,1)");
+  test_for_zero(t2_1(2,2)-12,"T2(N,i)-=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2VI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2VI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2VI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(N0,i)*=4;
+  t2_1(N1,i)*=6;
+  t2_1(N2,i)*=8;
+  test_for_zero(t2_1(0,0)-40,"T2(N,i)*=T(0,0)");
+  test_for_zero(t2_1(0,1)-40,"T2(N,i)*=T(0,1)");
+  test_for_zero(t2_1(0,2)-40,"T2(N,i)*=T(0,2)");
+  test_for_zero(t2_1(1,0)-66,"T2(N,i)*=T(1,0)");
+  test_for_zero(t2_1(1,1)-66,"T2(N,i)*=T(1,1)");
+  test_for_zero(t2_1(1,2)-66,"T2(N,i)*=T(1,2)");
+  test_for_zero(t2_1(2,0)-96,"T2(N,i)*=T(2,0)");
+  test_for_zero(t2_1(2,1)-96,"T2(N,i)*=T(2,1)");
+  test_for_zero(t2_1(2,2)-96,"T2(N,i)*=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2VII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2VII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2VII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(N0,i)/=2;
+  t2_1(N1,i)/=3;
+  t2_1(N2,i)/=4;
+  test_for_zero(t2_1(0,0)-20,"T2(N,i)/=T(0,0)");
+  test_for_zero(t2_1(0,1)-20,"T2(N,i)/=T(0,1)");
+  test_for_zero(t2_1(0,2)-20,"T2(N,i)/=T(0,2)");
+  test_for_zero(t2_1(1,0)-22,"T2(N,i)/=T(1,0)");
+  test_for_zero(t2_1(1,1)-22,"T2(N,i)/=T(1,1)");
+  test_for_zero(t2_1(1,2)-22,"T2(N,i)/=T(1,2)");
+  test_for_zero(t2_1(2,0)-24,"T2(N,i)/=T(2,0)");
+  test_for_zero(t2_1(2,1)-24,"T2(N,i)/=T(2,1)");
+  test_for_zero(t2_1(2,2)-24,"T2(N,i)/=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2VIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2VIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2VIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,N0)=t1_2(i);
+  t2_1(i,N1)=t1_2(i);
+  t2_1(i,N2)=t1_2(i);
+  test_for_zero(t2_1(0,0)-t1_2(0),"T2(i,N)=T1(i)(0,0)");
+  test_for_zero(t2_1(0,1)-t1_2(0),"T2(i,N)=T1(i)(0,1)");
+  test_for_zero(t2_1(0,2)-t1_2(0),"T2(i,N)=T1(i)(0,2)");
+  test_for_zero(t2_1(1,0)-t1_2(1),"T2(i,N)=T1(i)(1,0)");
+  test_for_zero(t2_1(1,1)-t1_2(1),"T2(i,N)=T1(i)(1,1)");
+  test_for_zero(t2_1(1,2)-t1_2(1),"T2(i,N)=T1(i)(1,2)");
+  test_for_zero(t2_1(2,0)-t1_2(2),"T2(i,N)=T1(i)(2,0)");
+  test_for_zero(t2_1(2,1)-t1_2(2),"T2(i,N)=T1(i)(2,1)");
+  test_for_zero(t2_1(2,2)-t1_2(2),"T2(i,N)=T1(i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2X.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2X.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2X(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,N0)+=10;
+  t2_1(i,N1)+=29;
+  t2_1(i,N2)+=48;
+  test_for_zero(t2_1(0,0)-20,"T2(i,N)+=T(0,0)");
+  test_for_zero(t2_1(1,0)-20,"T2(i,N)+=T(1,0)");
+  test_for_zero(t2_1(2,0)-20,"T2(i,N)+=T(2,0)");
+  test_for_zero(t2_1(0,1)-40,"T2(i,N)+=T(0,1)");
+  test_for_zero(t2_1(1,1)-40,"T2(i,N)+=T(1,1)");
+  test_for_zero(t2_1(2,1)-40,"T2(i,N)+=T(2,1)");
+  test_for_zero(t2_1(0,2)-60,"T2(i,N)+=T(0,2)");
+  test_for_zero(t2_1(1,2)-60,"T2(i,N)+=T(1,2)");
+  test_for_zero(t2_1(2,2)-60,"T2(i,N)+=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,N0)-=10;
+  t2_1(i,N1)-=29;
+  t2_1(i,N2)-=48;
+  test_for_zero(t2_1(0,0)-10,"T2(i,N)-=T(0,0)");
+  test_for_zero(t2_1(1,0)-10,"T2(i,N)-=T(1,0)");
+  test_for_zero(t2_1(2,0)-10,"T2(i,N)-=T(2,0)");
+  test_for_zero(t2_1(0,1)-11,"T2(i,N)-=T(0,1)");
+  test_for_zero(t2_1(1,1)-11,"T2(i,N)-=T(1,1)");
+  test_for_zero(t2_1(2,1)-11,"T2(i,N)-=T(2,1)");
+  test_for_zero(t2_1(0,2)-12,"T2(i,N)-=T(0,2)");
+  test_for_zero(t2_1(1,2)-12,"T2(i,N)-=T(1,2)");
+  test_for_zero(t2_1(2,2)-12,"T2(i,N)-=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,54 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,N0)*=4;
+  t2_1(i,N1)*=6;
+  t2_1(i,N2)*=8;
+  test_for_zero(t2_1(0,0)-40,"T2(i,N)*=T(0,0)");
+  test_for_zero(t2_1(1,0)-40,"T2(i,N)*=T(1,0)");
+  test_for_zero(t2_1(2,0)-40,"T2(i,N)*=T(2,0)");
+  test_for_zero(t2_1(0,1)-66,"T2(i,N)*=T(0,1)");
+  test_for_zero(t2_1(1,1)-66,"T2(i,N)*=T(1,1)");
+  test_for_zero(t2_1(2,1)-66,"T2(i,N)*=T(2,1)");
+  test_for_zero(t2_1(0,2)-96,"T2(i,N)*=T(0,2)");
+  test_for_zero(t2_1(1,2)-96,"T2(i,N)*=T(1,2)");
+  test_for_zero(t2_1(2,2)-96,"T2(i,N)*=T(2,2)");
+
+  t2_1(i,N0)/=2;
+  t2_1(i,N1)/=3;
+  t2_1(i,N2)/=4;
+  test_for_zero(t2_1(0,0)-20,"T2(i,N)/=T(0,0)");
+  test_for_zero(t2_1(1,0)-20,"T2(i,N)/=T(1,0)");
+  test_for_zero(t2_1(2,0)-20,"T2(i,N)/=T(2,0)");
+  test_for_zero(t2_1(0,1)-22,"T2(i,N)/=T(0,1)");
+  test_for_zero(t2_1(1,1)-22,"T2(i,N)/=T(1,1)");
+  test_for_zero(t2_1(2,1)-22,"T2(i,N)/=T(2,1)");
+  test_for_zero(t2_1(0,2)-24,"T2(i,N)/=T(0,2)");
+  test_for_zero(t2_1(1,2)-24,"T2(i,N)/=T(1,2)");
+  test_for_zero(t2_1(2,2)-24,"T2(i,N)/=T(2,2)");
+  test_for_zero(t2_1(i,i)-(20+22+24),"T2(i,i)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,55 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Test of actual numerals as an index. */
+
+  t1_1(i)=t2_1(0,i);
+  test_for_zero(t2_1(0,0)-t1_1(0),"T1(i)=T2(Num,i)(0,0)");
+  test_for_zero(t2_1(0,1)-t1_1(1),"T1(i)=T2(Num,i)(0,1)");
+  test_for_zero(t2_1(0,2)-t1_1(2),"T1(i)=T2(Num,i)(0,2)");
+  t1_1(i)=t2_1(1,i);
+  test_for_zero(t2_1(1,0)-t1_1(0),"T1(i)=T2(Num,i)(1,0)");
+  test_for_zero(t2_1(1,1)-t1_1(1),"T1(i)=T2(Num,i)(1,1)");
+  test_for_zero(t2_1(1,2)-t1_1(2),"T1(i)=T2(Num,i)(1,2)");
+  t1_1(i)=t2_1(2,i);
+  test_for_zero(t2_1(2,0)-t1_1(0),"T1(i)=T2(Num,i)(2,0)");
+  test_for_zero(t2_1(2,1)-t1_1(1),"T1(i)=T2(Num,i)(2,1)");
+  test_for_zero(t2_1(2,2)-t1_1(2),"T1(i)=T2(Num,i)(2,2)");
+
+  t1_1(i)=t2_1(i,0);
+  test_for_zero(t2_1(0,0)-t1_1(0),"T1(i)=T2(i,Num)(0,0)");
+  test_for_zero(t2_1(1,0)-t1_1(1),"T1(i)=T2(i,Num)(1,0)");
+  test_for_zero(t2_1(2,0)-t1_1(2),"T1(i)=T2(i,Num)(2,0)");
+  t1_1(i)=t2_1(i,1);
+  test_for_zero(t2_1(0,1)-t1_1(0),"T1(i)=T2(i,Num)(0,1)");
+  test_for_zero(t2_1(1,1)-t1_1(1),"T1(i)=T2(i,Num)(1,1)");
+  test_for_zero(t2_1(2,1)-t1_1(2),"T1(i)=T2(i,Num)(2,1)");
+  t1_1(i)=t2_1(i,2);
+  test_for_zero(t2_1(0,2)-t1_1(0),"T1(i)=T2(i,Num)(0,2)");
+  test_for_zero(t2_1(1,2)-t1_1(1),"T1(i)=T2(i,Num)(1,2)");
+  test_for_zero(t2_1(2,2)-t1_1(2),"T1(i)=T2(i,Num)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* add/subtract */
+  
+  t2_1(i,j)=t2_2(i,j)-t1_1(i)*t1_2(j);
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)-t1_1(0)*t1_2(0)),"T2(i,j)-T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)-t1_1(0)*t1_2(1)),"T2(i,j)-T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)-t1_1(0)*t1_2(2)),"T2(i,j)-T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)-t1_1(1)*t1_2(0)),"T2(i,j)-T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)-t1_1(1)*t1_2(1)),"T2(i,j)-T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)-t1_1(1)*t1_2(2)),"T2(i,j)-T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)-t1_1(2)*t1_2(0)),"T2(i,j)-T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)-t1_1(2)*t1_2(1)),"T2(i,j)-T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)-t1_1(2)*t1_2(2)),"T2(i,j)-T2(i,j)(2,2)");
+
+  t2_1(i,j)=t2_2(i,j)-t1_1(j)*t1_2(i);
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)-t1_2(0)*t1_1(0)),"T2(i,j)-T2(j,i)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)-t1_2(0)*t1_1(1)),"T2(i,j)-T2(j,i)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)-t1_2(0)*t1_1(2)),"T2(i,j)-T2(j,i)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)-t1_2(1)*t1_1(0)),"T2(i,j)-T2(j,i)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)-t1_2(1)*t1_1(1)),"T2(i,j)-T2(j,i)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)-t1_2(1)*t1_1(2)),"T2(i,j)-T2(j,i)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)-t1_2(2)*t1_1(0)),"T2(i,j)-T2(j,i)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)-t1_2(2)*t1_1(1)),"T2(i,j)-T2(j,i)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)-t1_2(2)*t1_1(2)),"T2(i,j)-T2(j,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Equals */
+
+  /* Switch indices */
+
+  t2_1(j,i)=t2_2(i,j)+t1_1(j)*t1_2(i);
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)+t1_2(0)*t1_1(0)),
+		"T2(j,i)=T2(i,j)(0,0)");
+  test_for_zero(t2_1(1,0)-(t2_2(0,1)+t1_2(0)*t1_1(1)),
+		"T2(j,i)=T2(i,j)(0,1)");
+  test_for_zero(t2_1(2,0)-(t2_2(0,2)+t1_2(0)*t1_1(2)),
+		"T2(j,i)=T2(i,j)(0,2)");
+  test_for_zero(t2_1(0,1)-(t2_2(1,0)+t1_2(1)*t1_1(0)),
+		"T2(j,i)=T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)+t1_2(1)*t1_1(1)),
+		"T2(j,i)=T2(i,j)(1,1)");
+  test_for_zero(t2_1(2,1)-(t2_2(1,2)+t1_2(1)*t1_1(2)),
+		"T2(j,i)=T2(i,j)(1,2)");
+  test_for_zero(t2_1(0,2)-(t2_2(2,0)+t1_2(2)*t1_1(0)),
+		"T2(j,i)=T2(i,j)(2,0)");
+  test_for_zero(t2_1(1,2)-(t2_2(2,1)+t1_2(2)*t1_1(1)),
+		"T2(j,i)=T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)+t1_2(2)*t1_1(2)),
+		"T2(j,i)=T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* add/subtract */
+
+  t2_1(i,j)=t2_2(i,j)+t1_1(i)*t1_2(j);
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)+t1_1(0)*t1_2(0)),"T2(i,j)+T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)+t1_1(0)*t1_2(1)),"T2(i,j)+T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)+t1_1(0)*t1_2(2)),"T2(i,j)+T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)+t1_1(1)*t1_2(0)),"T2(i,j)+T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)+t1_1(1)*t1_2(1)),"T2(i,j)+T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)+t1_1(1)*t1_2(2)),"T2(i,j)+T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)+t1_1(2)*t1_2(0)),"T2(i,j)+T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)+t1_1(2)*t1_2(1)),"T2(i,j)+T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)+t1_1(2)*t1_2(2)),"T2(i,j)+T2(i,j)(2,2)");
+
+  t2_1(i,j)=t2_2(i,j)+t1_1(j)*t1_2(i);
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)+t1_1(0)*t1_2(0)),"T2(i,j)+T2(j,i)(0,0)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)+t1_1(0)*t1_2(1)),"T2(i,j)+T2(j,i)(0,1)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)+t1_1(0)*t1_2(2)),"T2(i,j)+T2(j,i)(0,2)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)+t1_1(1)*t1_2(0)),"T2(i,j)+T2(j,i)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)+t1_1(1)*t1_2(1)),"T2(i,j)+T2(j,i)(1,1)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)+t1_1(1)*t1_2(2)),"T2(i,j)+T2(j,i)(1,2)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)+t1_1(2)*t1_2(0)),"T2(i,j)+T2(j,i)(2,0)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)+t1_1(2)*t1_2(1)),"T2(i,j)+T2(j,i)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)+t1_1(2)*t1_2(2)),"T2(i,j)+T2(j,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Equals */
+
+  t2_1(i,j)=t2_2(i,j)+t1_1(j)*t1_2(i);
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)+t1_2(0)*t1_1(0)),"T2(i,j)=T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)+t1_2(0)*t1_1(1)),"T2(i,j)=T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)+t1_2(0)*t1_1(2)),"T2(i,j)=T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)+t1_2(1)*t1_1(0)),"T2(i,j)=T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)+t1_2(1)*t1_1(1)),"T2(i,j)=T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)+t1_2(1)*t1_1(2)),"T2(i,j)=T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)+t1_2(2)*t1_1(0)),"T2(i,j)=T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)+t1_2(2)*t1_1(1)),"T2(i,j)=T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)+t1_2(2)*t1_1(2)),"T2(i,j)=T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Equals */
+
+  t2_1(i,j)+=t2_2(i,j);
+  test_for_zero(t2_1(0,0)-(2*t2_2(0,0)+t1_2(0)*t1_1(0)),"T2(i,j)+=T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(2*t2_2(0,1)+t1_2(0)*t1_1(1)),"T2(i,j)+=T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(2*t2_2(0,2)+t1_2(0)*t1_1(2)),"T2(i,j)+=T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(2*t2_2(1,0)+t1_2(1)*t1_1(0)),"T2(i,j)+=T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(2*t2_2(1,1)+t1_2(1)*t1_1(1)),"T2(i,j)+=T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(2*t2_2(1,2)+t1_2(1)*t1_1(2)),"T2(i,j)+=T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(2*t2_2(2,0)+t1_2(2)*t1_1(0)),"T2(i,j)+=T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(2*t2_2(2,1)+t1_2(2)*t1_1(1)),"T2(i,j)+=T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(2*t2_2(2,2)+t1_2(2)*t1_1(2)),"T2(i,j)+=T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Equals */
+
+  t2_1(i,j)-=5*t2_2(i,j);
+  test_for_zero(t2_1(0,0)-(-3*t2_2(0,0)+t1_2(0)*t1_1(0)),"T2(i,j)-=T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(-3*t2_2(0,1)+t1_2(0)*t1_1(1)),"T2(i,j)-=T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(-3*t2_2(0,2)+t1_2(0)*t1_1(2)),"T2(i,j)-=T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(-3*t2_2(1,0)+t1_2(1)*t1_1(0)),"T2(i,j)-=T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(-3*t2_2(1,1)+t1_2(1)*t1_1(1)),"T2(i,j)-=T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(-3*t2_2(1,2)+t1_2(1)*t1_1(2)),"T2(i,j)-=T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(-3*t2_2(2,0)+t1_2(2)*t1_1(0)),"T2(i,j)-=T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(-3*t2_2(2,1)+t1_2(2)*t1_1(1)),"T2(i,j)-=T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(-3*t2_2(2,2)+t1_2(2)*t1_1(2)),"T2(i,j)-=T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Equals */
+
+  /* Switch indices */
+
+  t2_1(j,i)+=t2_2(i,j);
+  test_for_zero(t2_1(0,0)-(2*t2_2(0,0)+t1_2(0)*t1_1(0)),
+		"T2(j,i)+=T2(i,j)(0,0)");
+  test_for_zero(t2_1(1,0)-(2*t2_2(0,1)+t1_2(0)*t1_1(1)),
+		"T2(j,i)+=T2(i,j)(0,1)");
+  test_for_zero(t2_1(2,0)-(2*t2_2(0,2)+t1_2(0)*t1_1(2)),
+		"T2(j,i)+=T2(i,j)(0,2)");
+  test_for_zero(t2_1(0,1)-(2*t2_2(1,0)+t1_2(1)*t1_1(0)),
+		"T2(j,i)+=T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(2*t2_2(1,1)+t1_2(1)*t1_1(1)),
+		"T2(j,i)+=T2(i,j)(1,1)");
+  test_for_zero(t2_1(2,1)-(2*t2_2(1,2)+t1_2(1)*t1_1(2)),
+		"T2(j,i)+=T2(i,j)(1,2)");
+  test_for_zero(t2_1(0,2)-(2*t2_2(2,0)+t1_2(2)*t1_1(0)),
+		"T2(j,i)+=T2(i,j)(2,0)");
+  test_for_zero(t2_1(1,2)-(2*t2_2(2,1)+t1_2(2)*t1_1(1)),
+		"T2(j,i)+=T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(2*t2_2(2,2)+t1_2(2)*t1_1(2)),
+		"T2(j,i)+=T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Equals */
+
+  /* Switch indices */
+
+  t2_1(j,i)-=5*t2_2(i,j);
+  test_for_zero(t2_1(0,0)-(-3*t2_2(0,0)+t1_2(0)*t1_1(0)),
+		"T2(j,i)-=T2(i,j)(0,0)");
+  test_for_zero(t2_1(1,0)-(-3*t2_2(0,1)+t1_2(0)*t1_1(1)),
+		"T2(j,i)-=T2(i,j)(0,1)");
+  test_for_zero(t2_1(2,0)-(-3*t2_2(0,2)+t1_2(0)*t1_1(2)),
+		"T2(j,i)-=T2(i,j)(0,2)");
+  test_for_zero(t2_1(0,1)-(-3*t2_2(1,0)+t1_2(1)*t1_1(0)),
+		"T2(j,i)-=T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(-3*t2_2(1,1)+t1_2(1)*t1_1(1)),
+		"T2(j,i)-=T2(i,j)(1,1)");
+  test_for_zero(t2_1(2,1)-(-3*t2_2(1,2)+t1_2(1)*t1_1(2)),
+		"T2(j,i)-=T2(i,j)(1,2)");
+  test_for_zero(t2_1(0,2)-(-3*t2_2(2,0)+t1_2(2)*t1_1(0)),
+		"T2(j,i)-=T2(i,j)(2,0)");
+  test_for_zero(t2_1(1,2)-(-3*t2_2(2,1)+t1_2(2)*t1_1(1)),
+		"T2(j,i)-=T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(-3*t2_2(2,2)+t1_2(2)*t1_1(2)),
+		"T2(j,i)-=T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,73 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Equals */
+
+  t2_1(i,j)+=10;
+  test_for_zero(t2_1(0,0)-(-3*t2_2(0,0)+t1_2(0)*t1_1(0)+10),"T2+=T(0,0)");
+  test_for_zero(t2_1(1,0)-(-3*t2_2(0,1)+t1_2(0)*t1_1(1)+10),"T2+=T(0,1)");
+  test_for_zero(t2_1(2,0)-(-3*t2_2(0,2)+t1_2(0)*t1_1(2)+10),"T2+=T(0,2)");
+  test_for_zero(t2_1(0,1)-(-3*t2_2(1,0)+t1_2(1)*t1_1(0)+10),"T2+=T(1,0)");
+  test_for_zero(t2_1(1,1)-(-3*t2_2(1,1)+t1_2(1)*t1_1(1)+10),"T2+=T(1,1)");
+  test_for_zero(t2_1(2,1)-(-3*t2_2(1,2)+t1_2(1)*t1_1(2)+10),"T2+=T(1,2)");
+  test_for_zero(t2_1(0,2)-(-3*t2_2(2,0)+t1_2(2)*t1_1(0)+10),"T2+=T(2,0)");
+  test_for_zero(t2_1(1,2)-(-3*t2_2(2,1)+t1_2(2)*t1_1(1)+10),"T2+=T(2,1)");
+  test_for_zero(t2_1(2,2)-(-3*t2_2(2,2)+t1_2(2)*t1_1(2)+10),"T2+=T(2,2)");
+
+  t2_1(i,j)-=7;
+  test_for_zero(t2_1(0,0)-(-3*t2_2(0,0)+t1_2(0)*t1_1(0)+3),"T2-=T(0,0)");
+  test_for_zero(t2_1(1,0)-(-3*t2_2(0,1)+t1_2(0)*t1_1(1)+3),"T2-=T(0,1)");
+  test_for_zero(t2_1(2,0)-(-3*t2_2(0,2)+t1_2(0)*t1_1(2)+3),"T2-=T(0,2)");
+  test_for_zero(t2_1(0,1)-(-3*t2_2(1,0)+t1_2(1)*t1_1(0)+3),"T2-=T(1,0)");
+  test_for_zero(t2_1(1,1)-(-3*t2_2(1,1)+t1_2(1)*t1_1(1)+3),"T2-=T(1,1)");
+  test_for_zero(t2_1(2,1)-(-3*t2_2(1,2)+t1_2(1)*t1_1(2)+3),"T2-=T(1,2)");
+  test_for_zero(t2_1(0,2)-(-3*t2_2(2,0)+t1_2(2)*t1_1(0)+3),"T2-=T(2,0)");
+  test_for_zero(t2_1(1,2)-(-3*t2_2(2,1)+t1_2(2)*t1_1(1)+3),"T2-=T(2,1)");
+  test_for_zero(t2_1(2,2)-(-3*t2_2(2,2)+t1_2(2)*t1_1(2)+3),"T2-=T(2,2)");
+
+  t2_1(i,j)*=12;
+  test_for_zero(t2_1(0,0)-(-3*t2_2(0,0)+t1_2(0)*t1_1(0)+3)*12,"T2*=T(0,0)");
+  test_for_zero(t2_1(1,0)-(-3*t2_2(0,1)+t1_2(0)*t1_1(1)+3)*12,"T2*=T(0,1)");
+  test_for_zero(t2_1(2,0)-(-3*t2_2(0,2)+t1_2(0)*t1_1(2)+3)*12,"T2*=T(0,2)");
+  test_for_zero(t2_1(0,1)-(-3*t2_2(1,0)+t1_2(1)*t1_1(0)+3)*12,"T2*=T(1,0)");
+  test_for_zero(t2_1(1,1)-(-3*t2_2(1,1)+t1_2(1)*t1_1(1)+3)*12,"T2*=T(1,1)");
+  test_for_zero(t2_1(2,1)-(-3*t2_2(1,2)+t1_2(1)*t1_1(2)+3)*12,"T2*=T(1,2)");
+  test_for_zero(t2_1(0,2)-(-3*t2_2(2,0)+t1_2(2)*t1_1(0)+3)*12,"T2*=T(2,0)");
+  test_for_zero(t2_1(1,2)-(-3*t2_2(2,1)+t1_2(2)*t1_1(1)+3)*12,"T2*=T(2,1)");
+  test_for_zero(t2_1(2,2)-(-3*t2_2(2,2)+t1_2(2)*t1_1(2)+3)*12,"T2*=T(2,2)");
+
+  t2_1(i,j)/=4;
+  test_for_zero(t2_1(0,0)-(-3*t2_2(0,0)+t1_2(0)*t1_1(0)+3)*3,"T2/=T(0,0)");
+  test_for_zero(t2_1(1,0)-(-3*t2_2(0,1)+t1_2(0)*t1_1(1)+3)*3,"T2/=T(0,1)");
+  test_for_zero(t2_1(2,0)-(-3*t2_2(0,2)+t1_2(0)*t1_1(2)+3)*3,"T2/=T(0,2)");
+  test_for_zero(t2_1(0,1)-(-3*t2_2(1,0)+t1_2(1)*t1_1(0)+3)*3,"T2/=T(1,0)");
+  test_for_zero(t2_1(1,1)-(-3*t2_2(1,1)+t1_2(1)*t1_1(1)+3)*3,"T2/=T(1,1)");
+  test_for_zero(t2_1(2,1)-(-3*t2_2(1,2)+t1_2(1)*t1_1(2)+3)*3,"T2/=T(1,2)");
+  test_for_zero(t2_1(0,2)-(-3*t2_2(2,0)+t1_2(2)*t1_1(0)+3)*3,"T2/=T(2,0)");
+  test_for_zero(t2_1(1,2)-(-3*t2_2(2,1)+t1_2(2)*t1_1(1)+3)*3,"T2/=T(2,1)");
+  test_for_zero(t2_1(2,2)-(-3*t2_2(2,2)+t1_2(2)*t1_1(2)+3)*3,"T2/=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,61 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*Tensor1 */
+
+  t1_1(i)=t2_2(i,j)*t1_2(j);
+  test_for_zero(t1_1(0)-(t2_2(0,0)*t1_2(0) + t2_2(0,1)*t1_2(1)
+			 + t2_2(0,2)*t1_2(2)),"T2(i,j)*T1(j)(0)");
+  test_for_zero(t1_1(1)-(t2_2(1,0)*t1_2(0) + t2_2(1,1)*t1_2(1)
+			 + t2_2(1,2)*t1_2(2)),"T2(i,j)*T1(j)(1)");
+  test_for_zero(t1_1(2)-(t2_2(2,0)*t1_2(0) + t2_2(2,1)*t1_2(1)
+			 + t2_2(2,2)*t1_2(2)),"T2(i,j)*T1(j)(2)");
+
+  t1_1(i)=t1_2(j)*t2_2(i,j);
+  test_for_zero(t1_1(0)-(t2_2(0,0)*t1_2(0) + t2_2(0,1)*t1_2(1)
+			 + t2_2(0,2)*t1_2(2)),"T1(j)*T2(i,j)(0)");
+  test_for_zero(t1_1(1)-(t2_2(1,0)*t1_2(0) + t2_2(1,1)*t1_2(1)
+			 + t2_2(1,2)*t1_2(2)),"T1(j)*T2(i,j)(1)");
+  test_for_zero(t1_1(2)-(t2_2(2,0)*t1_2(0) + t2_2(2,1)*t1_2(1)
+			 + t2_2(2,2)*t1_2(2)),"T1(j)*T2(i,j)(2)");
+
+  t1_1(j)=t2_2(i,j)*t1_2(i);
+  test_for_zero(t1_1(0)-(t2_2(0,0)*t1_2(0) + t2_2(1,0)*t1_2(1)
+			 + t2_2(2,0)*t1_2(2)),"T2(i,j)*T1(i)(0)");
+  test_for_zero(t1_1(1)-(t2_2(0,1)*t1_2(0) + t2_2(1,1)*t1_2(1)
+			 + t2_2(2,1)*t1_2(2)),"T2(i,j)*T1(i)(1)");
+  test_for_zero(t1_1(2)-(t2_2(0,2)*t1_2(0) + t2_2(1,2)*t1_2(1)
+			 + t2_2(2,2)*t1_2(2)),"T2(i,j)*T1(i)(2)");
+
+  t1_1(j)=t1_2(i)*t2_2(i,j);
+  test_for_zero(t1_1(0)-(t2_2(0,0)*t1_2(0) + t2_2(1,0)*t1_2(1)
+			 + t2_2(2,0)*t1_2(2)),"T1(i)*T2(i,j)(0)");
+  test_for_zero(t1_1(1)-(t2_2(0,1)*t1_2(0) + t2_2(1,1)*t1_2(1)
+			 + t2_2(2,1)*t1_2(2)),"T1(i)*T2(i,j)(1)");
+  test_for_zero(t1_1(2)-(t2_2(0,2)*t1_2(0) + t2_2(1,2)*t1_2(1)
+			 + t2_2(2,2)*t1_2(2)),"T1(i)*T2(i,j)(2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,139 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*Tensor1 */
+
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,0,0) - t2_2(0,0)*t1_2(0),
+		"T2(i,j)*T1(k)(0,0,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,0,1) - t2_2(0,0)*t1_2(1),
+		"T2(i,j)*T1(k)(0,0,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,0,2) - t2_2(0,0)*t1_2(2),
+		"T2(i,j)*T1(k)(0,0,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,1,0) - t2_2(0,1)*t1_2(0),
+		"T2(i,j)*T1(k)(0,1,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,1,1) - t2_2(0,1)*t1_2(1),
+		"T2(i,j)*T1(k)(0,1,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,1,2) - t2_2(0,1)*t1_2(2),
+		"T2(i,j)*T1(k)(0,1,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,2,0) - t2_2(0,2)*t1_2(0),
+		"T2(i,j)*T1(k)(0,2,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,2,1) - t2_2(0,2)*t1_2(1),
+		"T2(i,j)*T1(k)(0,2,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(0,2,2) - t2_2(0,2)*t1_2(2),
+		"T2(i,j)*T1(k)(0,2,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,0,0) - t2_2(1,0)*t1_2(0),
+		"T2(i,j)*T1(k)(1,0,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,0,1) - t2_2(1,0)*t1_2(1),
+		"T2(i,j)*T1(k)(1,0,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,0,2) - t2_2(1,0)*t1_2(2),
+		"T2(i,j)*T1(k)(1,0,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,1,0) - t2_2(1,1)*t1_2(0),
+		"T2(i,j)*T1(k)(1,1,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,1,1) - t2_2(1,1)*t1_2(1),
+		"T2(i,j)*T1(k)(1,1,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,1,2) - t2_2(1,1)*t1_2(2),
+		"T2(i,j)*T1(k)(1,1,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,2,0) - t2_2(1,2)*t1_2(0),
+		"T2(i,j)*T1(k)(1,2,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,2,1) - t2_2(1,2)*t1_2(1),
+		"T2(i,j)*T1(k)(1,2,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(1,2,2) - t2_2(1,2)*t1_2(2),
+		"T2(i,j)*T1(k)(1,2,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,0,0) - t2_2(2,0)*t1_2(0),
+		"T2(i,j)*T1(k)(2,0,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,0,1) - t2_2(2,0)*t1_2(1),
+		"T2(i,j)*T1(k)(2,0,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,0,2) - t2_2(2,0)*t1_2(2),
+		"T2(i,j)*T1(k)(2,0,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,1,0) - t2_2(2,1)*t1_2(0),
+		"T2(i,j)*T1(k)(2,1,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,1,1) - t2_2(2,1)*t1_2(1),
+		"T2(i,j)*T1(k)(2,1,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,1,2) - t2_2(2,1)*t1_2(2),
+		"T2(i,j)*T1(k)(2,1,2)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,2,0) - t2_2(2,2)*t1_2(0),
+		"T2(i,j)*T1(k)(2,2,0)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,2,1) - t2_2(2,2)*t1_2(1),
+		"T2(i,j)*T1(k)(2,2,1)");
+  test_for_zero((t2_2(i,j)*t1_2(k))(2,2,2) - t2_2(2,2)*t1_2(2),
+		"T2(i,j)*T1(k)(2,2,2)");
+
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,0,0) - t2_2(0,0)*t1_2(0),
+		"T1(k)*T2(i,j)(0,0,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,0,1) - t2_2(0,0)*t1_2(1),
+		"T1(k)*T2(i,j)(0,0,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,0,2) - t2_2(0,0)*t1_2(2),
+		"T1(k)*T2(i,j)(0,0,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,1,0) - t2_2(0,1)*t1_2(0),
+		"T1(k)*T2(i,j)(0,1,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,1,1) - t2_2(0,1)*t1_2(1),
+		"T1(k)*T2(i,j)(0,1,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,1,2) - t2_2(0,1)*t1_2(2),
+		"T1(k)*T2(i,j)(0,1,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,2,0) - t2_2(0,2)*t1_2(0),
+		"T1(k)*T2(i,j)(0,2,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,2,1) - t2_2(0,2)*t1_2(1),
+		"T1(k)*T2(i,j)(0,2,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(0,2,2) - t2_2(0,2)*t1_2(2),
+		"T1(k)*T2(i,j)(0,2,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,0,0) - t2_2(1,0)*t1_2(0),
+		"T1(k)*T2(i,j)(1,0,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,0,1) - t2_2(1,0)*t1_2(1),
+		"T1(k)*T2(i,j)(1,0,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,0,2) - t2_2(1,0)*t1_2(2),
+		"T1(k)*T2(i,j)(1,0,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,1,0) - t2_2(1,1)*t1_2(0),
+		"T1(k)*T2(i,j)(1,1,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,1,1) - t2_2(1,1)*t1_2(1),
+		"T1(k)*T2(i,j)(1,1,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,1,2) - t2_2(1,1)*t1_2(2),
+		"T1(k)*T2(i,j)(1,1,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,2,0) - t2_2(1,2)*t1_2(0),
+		"T1(k)*T2(i,j)(1,2,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,2,1) - t2_2(1,2)*t1_2(1),
+		"T1(k)*T2(i,j)(1,2,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(1,2,2) - t2_2(1,2)*t1_2(2),
+		"T1(k)*T2(i,j)(1,2,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,0,0) - t2_2(2,0)*t1_2(0),
+		"T1(k)*T2(i,j)(2,0,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,0,1) - t2_2(2,0)*t1_2(1),
+		"T1(k)*T2(i,j)(2,0,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,0,2) - t2_2(2,0)*t1_2(2),
+		"T1(k)*T2(i,j)(2,0,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,1,0) - t2_2(2,1)*t1_2(0),
+		"T1(k)*T2(i,j)(2,1,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,1,1) - t2_2(2,1)*t1_2(1),
+		"T1(k)*T2(i,j)(2,1,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,1,2) - t2_2(2,1)*t1_2(2),
+		"T1(k)*T2(i,j)(2,1,2)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,2,0) - t2_2(2,2)*t1_2(0),
+		"T1(k)*T2(i,j)(2,2,0)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,2,1) - t2_2(2,2)*t1_2(1),
+		"T1(k)*T2(i,j)(2,2,1)");
+  test_for_zero((t1_2(k)*t2_2(i,j))(2,2,2) - t2_2(2,2)*t1_2(2),
+		"T1(k)*T2(i,j)(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*Tensor2 */
+
+  t2_1(j,k)=t2_2(i,j)*t2_3(k,i);
+  test_for_zero(t2_1(0,0) - (t2_2(0,0)*t2_3(0,0) + t2_2(1,0)*t2_3(0,1)
+			     + t2_2(2,0)*t2_3(0,2)),"T2(i,j)*T2(k,i)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2_2(0,0)*t2_3(1,0) + t2_2(1,0)*t2_3(1,1)
+			     + t2_2(2,0)*t2_3(1,2)),"T2(i,j)*T2(k,i)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2_2(0,0)*t2_3(2,0) + t2_2(1,0)*t2_3(2,1)
+			     + t2_2(2,0)*t2_3(2,2)),"T2(i,j)*T2(k,i)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2_2(0,1)*t2_3(0,0) + t2_2(1,1)*t2_3(0,1)
+			     + t2_2(2,1)*t2_3(0,2)),"T2(i,j)*T2(k,i)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2_2(0,1)*t2_3(1,0) + t2_2(1,1)*t2_3(1,1)
+			     + t2_2(2,1)*t2_3(1,2)),"T2(i,j)*T2(k,i)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2_2(0,1)*t2_3(2,0) + t2_2(1,1)*t2_3(2,1)
+			     + t2_2(2,1)*t2_3(2,2)),"T2(i,j)*T2(k,i)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2_2(0,2)*t2_3(0,0) + t2_2(1,2)*t2_3(0,1)
+			     + t2_2(2,2)*t2_3(0,2)),"T2(i,j)*T2(k,i)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2_2(0,2)*t2_3(1,0) + t2_2(1,2)*t2_3(1,1)
+			     + t2_2(2,2)*t2_3(1,2)),"T2(i,j)*T2(k,i)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2_2(0,2)*t2_3(2,0) + t2_2(1,2)*t2_3(2,1)
+			     + t2_2(2,2)*t2_3(2,2)),"T2(i,j)*T2(k,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,43 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*Tensor2 */
+
+  test_for_zero
+    (t2_1(i,j)*t2_2(i,j)
+     -(t2_1(0,0)*t2_2(0,0) + t2_1(0,1)*t2_2(0,1) + t2_1(0,2)*t2_2(0,2)
+       + t2_1(1,0)*t2_2(1,0) + t2_1(1,1)*t2_2(1,1) + t2_1(1,2)*t2_2(1,2)
+       + t2_1(2,0)*t2_2(2,0) + t2_1(2,1)*t2_2(2,1) + t2_1(2,2)*t2_2(2,2)),
+     "T2(i,j)*T2(i,j)");
+  
+  test_for_zero
+    (t2_1(i,j)*t2_2(j,i)
+     -(t2_1(0,0)*t2_2(0,0) + t2_1(0,1)*t2_2(1,0) + t2_1(0,2)*t2_2(2,0)
+       + t2_1(1,0)*t2_2(0,1) + t2_1(1,1)*t2_2(1,1) + t2_1(1,2)*t2_2(2,1)
+       + t2_1(2,0)*t2_2(0,2) + t2_1(2,1)*t2_2(1,2) + t2_1(2,2)*t2_2(2,2)),
+     "T2(i,j)*T2(j,i)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*Tensor2 */
+
+  t2_1(i,k)=t2_2(i,j)*t2_3(j,k);
+  test_for_zero(t2_1(0,0) - (t2_2(0,0)*t2_3(0,0) + t2_2(0,1)*t2_3(1,0)
+			     + t2_2(0,2)*t2_3(2,0)),"T2(i,j)*T2(j,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2_2(0,0)*t2_3(0,1) + t2_2(0,1)*t2_3(1,1)
+			     + t2_2(0,2)*t2_3(2,1)),"T2(i,j)*T2(j,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2_2(0,0)*t2_3(0,2) + t2_2(0,1)*t2_3(1,2)
+			     + t2_2(0,2)*t2_3(2,2)),"T2(i,j)*T2(j,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2_2(1,0)*t2_3(0,0) + t2_2(1,1)*t2_3(1,0)
+			     + t2_2(1,2)*t2_3(2,0)),"T2(i,j)*T2(j,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2_2(1,0)*t2_3(0,1) + t2_2(1,1)*t2_3(1,1)
+			     + t2_2(1,2)*t2_3(2,1)),"T2(i,j)*T2(j,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2_2(1,0)*t2_3(0,2) + t2_2(1,1)*t2_3(1,2)
+			     + t2_2(1,2)*t2_3(2,2)),"T2(i,j)*T2(j,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2_2(2,0)*t2_3(0,0) + t2_2(2,1)*t2_3(1,0)
+			     + t2_2(2,2)*t2_3(2,0)),"T2(i,j)*T2(j,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2_2(2,0)*t2_3(0,1) + t2_2(2,1)*t2_3(1,1)
+			     + t2_2(2,2)*t2_3(2,1)),"T2(i,j)*T2(j,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2_2(2,0)*t2_3(0,2) + t2_2(2,1)*t2_3(1,2)
+			     + t2_2(2,2)*t2_3(2,2)),"T2(i,j)*T2(j,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*Tensor2 */
+
+  t2_1(i,k)=t2_2(i,j)*t2_3(k,j);
+  test_for_zero(t2_1(0,0) - (t2_2(0,0)*t2_3(0,0) + t2_2(0,1)*t2_3(0,1)
+			     + t2_2(0,2)*t2_3(0,2)),"T2(i,j)*T2(k,j)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2_2(0,0)*t2_3(1,0) + t2_2(0,1)*t2_3(1,1)
+			     + t2_2(0,2)*t2_3(1,2)),"T2(i,j)*T2(k,j)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2_2(0,0)*t2_3(2,0) + t2_2(0,1)*t2_3(2,1)
+			     + t2_2(0,2)*t2_3(2,2)),"T2(i,j)*T2(k,j)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2_2(1,0)*t2_3(0,0) + t2_2(1,1)*t2_3(0,1)
+			     + t2_2(1,2)*t2_3(0,2)),"T2(i,j)*T2(k,j)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2_2(1,0)*t2_3(1,0) + t2_2(1,1)*t2_3(1,1)
+			     + t2_2(1,2)*t2_3(1,2)),"T2(i,j)*T2(k,j)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2_2(1,0)*t2_3(2,0) + t2_2(1,1)*t2_3(2,1)
+			     + t2_2(1,2)*t2_3(2,2)),"T2(i,j)*T2(k,j)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2_2(2,0)*t2_3(0,0) + t2_2(2,1)*t2_3(0,1)
+			     + t2_2(2,2)*t2_3(0,2)),"T2(i,j)*T2(k,j)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2_2(2,0)*t2_3(1,0) + t2_2(2,1)*t2_3(1,1)
+			     + t2_2(2,2)*t2_3(1,2)),"T2(i,j)*T2(k,j)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2_2(2,0)*t2_3(2,0) + t2_2(2,1)*t2_3(2,1)
+			     + t2_2(2,2)*t2_3(2,2)),"T2(i,j)*T2(k,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*Tensor2 */
+
+  t2_1(j,k)=t2_2(i,j)*t2_3(i,k);
+  test_for_zero(t2_1(0,0) - (t2_2(0,0)*t2_3(0,0) + t2_2(1,0)*t2_3(1,0)
+			     + t2_2(2,0)*t2_3(2,0)),"T2(i,j)*T2(i,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2_2(0,0)*t2_3(0,1) + t2_2(1,0)*t2_3(1,1)
+			     + t2_2(2,0)*t2_3(2,1)),"T2(i,j)*T2(i,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2_2(0,0)*t2_3(0,2) + t2_2(1,0)*t2_3(1,2)
+			     + t2_2(2,0)*t2_3(2,2)),"T2(i,j)*T2(i,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2_2(0,1)*t2_3(0,0) + t2_2(1,1)*t2_3(1,0)
+			     + t2_2(2,1)*t2_3(2,0)),"T2(i,j)*T2(i,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2_2(0,1)*t2_3(0,1) + t2_2(1,1)*t2_3(1,1)
+			     + t2_2(2,1)*t2_3(2,1)),"T2(i,j)*T2(i,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2_2(0,1)*t2_3(0,2) + t2_2(1,1)*t2_3(1,2)
+			     + t2_2(2,1)*t2_3(2,2)),"T2(i,j)*T2(i,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2_2(0,2)*t2_3(0,0) + t2_2(1,2)*t2_3(1,0)
+			     + t2_2(2,2)*t2_3(2,0)),"T2(i,j)*T2(i,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2_2(0,2)*t2_3(0,1) + t2_2(1,2)*t2_3(1,1)
+			     + t2_2(2,2)*t2_3(2,1)),"T2(i,j)*T2(i,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2_2(0,2)*t2_3(0,2) + t2_2(1,2)*t2_3(1,2)
+			     + t2_2(2,2)*t2_3(2,2)),"T2(i,j)*T2(i,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+  
+  /* Tensor2&Tensor1 */
+
+  t2_1(i,j)=(t2_2(i,j)&t1_2(j));
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)*t1_2(0)),"T2(i,j)&T2(j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)*t1_2(1)),"T2(i,j)&T2(j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)*t1_2(2)),"T2(i,j)&T2(j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)*t1_2(0)),"T2(i,j)&T2(j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)*t1_2(1)),"T2(i,j)&T2(j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)*t1_2(2)),"T2(i,j)&T2(j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)*t1_2(0)),"T2(i,j)&T2(j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)*t1_2(1)),"T2(i,j)&T2(j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)*t1_2(2)),"T2(i,j)&T2(j)(2,2)");
+
+  t2_1(i,j)=(t1_2(j)&t2_2(i,j));
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)*t1_2(0)),"T2(j)&T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)*t1_2(1)),"T2(j)&T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)*t1_2(2)),"T2(j)&T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)*t1_2(0)),"T2(j)&T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)*t1_2(1)),"T2(j)&T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)*t1_2(2)),"T2(j)&T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)*t1_2(0)),"T2(j)&T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)*t1_2(1)),"T2(j)&T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)*t1_2(2)),"T2(j)&T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,51 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+  
+  /* Tensor2&Tensor1 */
+	     
+  t2_1(i,j)=(t2_2(i,j)&t1_2(i));
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)*t1_2(0)),"T2(i,j)&T2(i)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)*t1_2(0)),"T2(i,j)&T2(i)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)*t1_2(0)),"T2(i,j)&T2(i)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)*t1_2(1)),"T2(i,j)&T2(i)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)*t1_2(1)),"T2(i,j)&T2(i)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)*t1_2(1)),"T2(i,j)&T2(i)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)*t1_2(2)),"T2(i,j)&T2(i)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)*t1_2(2)),"T2(i,j)&T2(i)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)*t1_2(2)),"T2(i,j)&T2(i)(2,2)");
+
+  t2_1(i,j)=(t1_2(i)&t2_2(i,j));
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)*t1_2(0)),"T2(i)&T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)*t1_2(0)),"T2(i)&T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)*t1_2(0)),"T2(i)&T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)*t1_2(1)),"T2(i)&T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)*t1_2(1)),"T2(i)&T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)*t1_2(1)),"T2(i)&T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)*t1_2(2)),"T2(i)&T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)*t1_2(2)),"T2(i)&T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)*t1_2(2)),"T2(i)&T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,62 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Tensor2*T or /T */
+  
+  t2_1(i,j)=t2_2(i,j)*10;
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)*10),"T2(i,j)*T(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)*10),"T2(i,j)*T(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)*10),"T2(i,j)*T(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)*10),"T2(i,j)*T(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)*10),"T2(i,j)*T(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)*10),"T2(i,j)*T(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)*10),"T2(i,j)*T(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)*10),"T2(i,j)*T(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)*10),"T2(i,j)*T(2,2)");
+
+  t2_1(i,j)=10*t2_2(i,j);
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)*10),"T*T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)*10),"T*T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)*10),"T*T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)*10),"T*T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)*10),"T*T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)*10),"T*T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)*10),"T*T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)*10),"T*T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)*10),"T*T2(i,j)(2,2)");
+  
+  t2_1(i,j)=t2_2(i,j)/10;
+  test_for_zero(t2_1(0,0)-(t2_2(0,0)/10),"T2(i,j)/T(0,0)");
+  test_for_zero(t2_1(0,1)-(t2_2(0,1)/10),"T2(i,j)/T(0,1)");
+  test_for_zero(t2_1(0,2)-(t2_2(0,2)/10),"T2(i,j)/T(0,2)");
+  test_for_zero(t2_1(1,0)-(t2_2(1,0)/10),"T2(i,j)/T(1,0)");
+  test_for_zero(t2_1(1,1)-(t2_2(1,1)/10),"T2(i,j)/T(1,1)");
+  test_for_zero(t2_1(1,2)-(t2_2(1,2)/10),"T2(i,j)/T(1,2)");
+  test_for_zero(t2_1(2,0)-(t2_2(2,0)/10),"T2(i,j)/T(2,0)");
+  test_for_zero(t2_1(2,1)-(t2_2(2,1)/10),"T2(i,j)/T(2,1)");
+  test_for_zero(t2_1(2,2)-(t2_2(2,2)/10),"T2(i,j)/T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* -Tensor2 */
+
+  t2_1(i,j)=-t2_2(i,j);
+  test_for_zero(t2_1(0,0)+(t2_2(0,0)),"-T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)+(t2_2(0,1)),"-T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)+(t2_2(0,2)),"-T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)+(t2_2(1,0)),"-T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)+(t2_2(1,1)),"-T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)+(t2_2(1,2)),"-T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)+(t2_2(2,0)),"-T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)+(t2_2(2,1)),"-T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)+(t2_2(2,2)),"-T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,48 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,j)=t2_2(i,j);
+  t2s_1(i,j)=t2_1(i,k)^t2_2(j,k);
+  test_for_zero(t2s_1(0,0) - (t2_1(0,0)*t2_2(0,0) + t2_1(0,1)*t2_2(0,1)
+			      + t2_1(0,2)*t2_2(0,2)),"T2(i,k)^T2(j,k)(0,0)");
+  test_for_zero(t2s_1(1,0) - (t2_1(1,0)*t2_2(0,0) + t2_1(1,1)*t2_2(0,1)
+			      + t2_1(1,2)*t2_2(0,2)),"T2(i,k)^T2(j,k)(1,0)");
+  test_for_zero(t2s_1(2,0) - (t2_1(2,0)*t2_2(0,0) + t2_1(2,1)*t2_2(0,1)
+			      + t2_1(2,2)*t2_2(0,2)),"T2(i,k)^T2(j,k)(2,0)");
+  test_for_zero(t2s_1(0,1) - (t2_1(0,0)*t2_2(1,0) + t2_1(0,1)*t2_2(1,1)
+			      + t2_1(0,2)*t2_2(1,2)),"T2(i,k)^T2(j,k)(0,1)");
+  test_for_zero(t2s_1(1,1) - (t2_1(1,0)*t2_2(1,0) + t2_1(1,1)*t2_2(1,1)
+			      + t2_1(1,2)*t2_2(1,2)),"T2(i,k)^T2(j,k)(1,1)");
+  test_for_zero(t2s_1(2,1) - (t2_1(2,0)*t2_2(1,0) + t2_1(2,1)*t2_2(1,1)
+			      + t2_1(2,2)*t2_2(1,2)),"T2(i,k)^T2(j,k)(2,1)");
+  test_for_zero(t2s_1(0,2) - (t2_1(0,0)*t2_2(2,0) + t2_1(0,1)*t2_2(2,1)
+			      + t2_1(0,2)*t2_2(2,2)),"T2(i,k)^T2(j,k)(0,2)");
+  test_for_zero(t2s_1(1,2) - (t2_1(1,0)*t2_2(2,0) + t2_1(1,1)*t2_2(2,1)
+			      + t2_1(1,2)*t2_2(2,2)),"T2(i,k)^T2(j,k)(1,2)");
+  test_for_zero(t2s_1(2,2) - (t2_1(2,0)*t2_2(2,0) + t2_1(2,1)*t2_2(2,1)
+			      + t2_1(2,2)*t2_2(2,2)),"T2(i,k)^T2(j,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,j)=t2_2(i,j);
+
+  t2s_1(i,j)=t2_1(k,i)^t2_2(k,j);
+  test_for_zero(t2s_1(0,0) - (t2_1(0,0)*t2_2(0,0) + t2_1(1,0)*t2_2(1,0)
+			      + t2_1(2,0)*t2_2(2,0)),"T2(k,i)^T2(k,j)(0,0)");
+  test_for_zero(t2s_1(1,0) - (t2_1(0,1)*t2_2(0,0) + t2_1(1,1)*t2_2(1,0)
+			      + t2_1(2,1)*t2_2(2,0)),"T2(k,i)^T2(k,j)(1,0)");
+  test_for_zero(t2s_1(2,0) - (t2_1(0,2)*t2_2(0,0) + t2_1(1,2)*t2_2(1,0)
+			      + t2_1(2,2)*t2_2(2,0)),"T2(k,i)^T2(k,j)(2,0)");
+  test_for_zero(t2s_1(0,1) - (t2_1(0,0)*t2_2(0,1) + t2_1(1,0)*t2_2(1,1)
+			      + t2_1(2,0)*t2_2(2,1)),"T2(k,i)^T2(k,j)(0,1)");
+  test_for_zero(t2s_1(1,1) - (t2_1(0,1)*t2_2(0,1) + t2_1(1,1)*t2_2(1,1)
+			      + t2_1(2,1)*t2_2(2,1)),"T2(k,i)^T2(k,j)(1,1)");
+  test_for_zero(t2s_1(2,1) - (t2_1(0,2)*t2_2(0,1) + t2_1(1,2)*t2_2(1,1)
+			      + t2_1(2,2)*t2_2(2,1)),"T2(k,i)^T2(k,j)(2,1)");
+  test_for_zero(t2s_1(0,2) - (t2_1(0,0)*t2_2(0,2) + t2_1(1,0)*t2_2(1,2)
+			      + t2_1(2,0)*t2_2(2,2)),"T2(k,i)^T2(k,j)(0,2)");
+  test_for_zero(t2s_1(1,2) - (t2_1(0,1)*t2_2(0,2) + t2_1(1,1)*t2_2(1,2)
+			      + t2_1(2,1)*t2_2(2,2)),"T2(k,i)^T2(k,j)(1,2)");
+  test_for_zero(t2s_1(2,2) - (t2_1(0,2)*t2_2(0,2) + t2_1(1,2)*t2_2(1,2)
+			      + t2_1(2,2)*t2_2(2,2)),"T2(k,i)^T2(k,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,48 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,j)=t2_2(j,i);
+  t2s_1(i,j)=t2_1(k,i)^t2_2(j,k);
+  test_for_zero(t2s_1(0,0) - (t2_1(0,0)*t2_2(0,0) + t2_1(1,0)*t2_2(0,1)
+			      + t2_1(2,0)*t2_2(0,2)),"T2(k,i)^T2(j,k)(0,0)");
+  test_for_zero(t2s_1(1,0) - (t2_1(0,1)*t2_2(0,0) + t2_1(1,1)*t2_2(0,1)
+			      + t2_1(2,1)*t2_2(0,2)),"T2(k,i)^T2(j,k)(1,0)");
+  test_for_zero(t2s_1(2,0) - (t2_1(0,2)*t2_2(0,0) + t2_1(1,2)*t2_2(0,1)
+			      + t2_1(2,2)*t2_2(0,2)),"T2(k,i)^T2(j,k)(2,0)");
+  test_for_zero(t2s_1(0,1) - (t2_1(0,0)*t2_2(1,0) + t2_1(1,0)*t2_2(1,1)
+			      + t2_1(2,0)*t2_2(1,2)),"T2(k,i)^T2(j,k)(0,1)");
+  test_for_zero(t2s_1(1,1) - (t2_1(0,1)*t2_2(1,0) + t2_1(1,1)*t2_2(1,1)
+			      + t2_1(2,1)*t2_2(1,2)),"T2(k,i)^T2(j,k)(1,1)");
+  test_for_zero(t2s_1(2,1) - (t2_1(0,2)*t2_2(1,0) + t2_1(1,2)*t2_2(1,1)
+			      + t2_1(2,2)*t2_2(1,2)),"T2(k,i)^T2(j,k)(2,1)");
+  test_for_zero(t2s_1(0,2) - (t2_1(0,0)*t2_2(2,0) + t2_1(1,0)*t2_2(2,1)
+			      + t2_1(2,0)*t2_2(2,2)),"T2(k,i)^T2(j,k)(0,2)");
+  test_for_zero(t2s_1(1,2) - (t2_1(0,1)*t2_2(2,0) + t2_1(1,1)*t2_2(2,1)
+			      + t2_1(2,1)*t2_2(2,2)),"T2(k,i)^T2(j,k)(1,2)");
+  test_for_zero(t2s_1(2,2) - (t2_1(0,2)*t2_2(2,0) + t2_1(1,2)*t2_2(2,1)
+			      + t2_1(2,2)*t2_2(2,2)),"T2(k,i)^T2(j,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  t2_1(i,j)=t2_2(j,i);
+
+  t2s_1(i,j)=t2_1(i,k)^t2_2(k,j);
+  test_for_zero(t2s_1(0,0) - (t2_1(0,0)*t2_2(0,0) + t2_1(0,1)*t2_2(1,0)
+			      + t2_1(0,2)*t2_2(2,0)),"T2(i,k)^T2(k,j)(0,0)");
+  test_for_zero(t2s_1(1,0) - (t2_1(1,0)*t2_2(0,0) + t2_1(1,1)*t2_2(1,0)
+			      + t2_1(1,2)*t2_2(2,0)),"T2(i,k)^T2(k,j)(1,0)");
+  test_for_zero(t2s_1(2,0) - (t2_1(2,0)*t2_2(0,0) + t2_1(2,1)*t2_2(1,0)
+			      + t2_1(2,2)*t2_2(2,0)),"T2(i,k)^T2(k,j)(2,0)");
+  test_for_zero(t2s_1(0,1) - (t2_1(0,0)*t2_2(0,1) + t2_1(0,1)*t2_2(1,1)
+			      + t2_1(0,2)*t2_2(2,1)),"T2(i,k)^T2(k,j)(0,1)");
+  test_for_zero(t2s_1(1,1) - (t2_1(1,0)*t2_2(0,1) + t2_1(1,1)*t2_2(1,1)
+			      + t2_1(1,2)*t2_2(2,1)),"T2(i,k)^T2(k,j)(1,1)");
+  test_for_zero(t2s_1(2,1) - (t2_1(2,0)*t2_2(0,1) + t2_1(2,1)*t2_2(1,1)
+			      + t2_1(2,2)*t2_2(2,1)),"T2(i,k)^T2(k,j)(2,1)");
+  test_for_zero(t2s_1(0,2) - (t2_1(0,0)*t2_2(0,2) + t2_1(0,1)*t2_2(1,2)
+			      + t2_1(0,2)*t2_2(2,2)),"T2(i,k)^T2(k,j)(0,2)");
+  test_for_zero(t2s_1(1,2) - (t2_1(1,0)*t2_2(0,2) + t2_1(1,1)*t2_2(1,2)
+			      + t2_1(1,2)*t2_2(2,2)),"T2(i,k)^T2(k,j)(1,2)");
+  test_for_zero(t2s_1(2,2) - (t2_1(2,0)*t2_2(0,2) + t2_1(2,1)*t2_2(1,2)
+			      + t2_1(2,2)*t2_2(2,2)),"T2(i,k)^T2(k,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2/test_T2XXXVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2/test_T2XXXVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,73 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2XXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+  
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2 tests */
+
+  /* Checking whether functors work */
+
+  Tensor2<complex<double>,2,2> t1(complex<double>(1,2),complex<double>(3,4),
+				  complex<double>(5,6),complex<double>(7,8));
+  
+  Index<'a',2> a;
+  Index<'b',2> b;
+
+  /* I have this function pointer defined here because I can't seem to
+     make the compiler understand what kind of function I have.
+     Unless I do casts, which are ugly. It seems to have something to
+     do with conj being a templated function. */
+
+  complex<double> (*cj)(const complex<double> &);
+  cj=&(conj<double>);
+
+  test_for_zero(conj(t1(0,0))-transform(t1(a,b),static_cast<complex<double>
+					(*)(const complex<double> &)>
+					(&(conj<double>)))(0,0),
+		"transform(T2)(0,0) cast");
+  test_for_zero(conj(t1(0,1))-transform(t1(a,b),static_cast<complex<double>
+				  (*)(const complex<double> &)>
+					(&(conj<double>)))(0,1),
+		"transform(T2)(0,1) cast");
+  test_for_zero(conj(t1(1,0))-transform(t1(a,b),static_cast<complex<double>
+					(*)(const complex<double> &)>
+					(&(conj<double>)))(1,0),
+		"transform(T2)(1,0) cast");
+  test_for_zero(conj(t1(1,1))-transform(t1(a,b),static_cast<complex<double>
+					(*)(const complex<double> &)>
+					(&(conj<double>)))(1,1),
+		"transform(T2)(1,1) cast");
+  test_for_zero(conj(t1(0,0))-transform(t1(a,b),cj)(0,0),"transform(T2)(0,0)");
+  test_for_zero(conj(t1(0,1))-transform(t1(a,b),cj)(0,1),"transform(T2)(0,1)");
+  test_for_zero(conj(t1(1,0))-transform(t1(a,b),cj)(1,0),"transform(T2)(1,0)");
+  test_for_zero(conj(t1(1,1))-transform(t1(a,b),cj)(1,1),"transform(T2)(1,1)");
+
+  /* Check plain old conj */
+
+  test_for_zero(conj(t1(0,0))-conj(t1(a,b))(0,0),"conj(T2)(0,0)");
+  test_for_zero(conj(t1(0,1))-conj(t1(a,b))(0,1),"conj(T2)(0,1)");
+  test_for_zero(conj(t1(1,0))-conj(t1(a,b))(1,0),"conj(T2)(1,0)");
+  test_for_zero(conj(t1(1,1))-conj(t1(a,b))(1,1),"conj(T2)(1,1)");
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2s.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2s.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,457 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+extern
+void test_T2sI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXXXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXL(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXLI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXLII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXLIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+extern
+void test_T2sXLIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
+
+void test_T2s(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  test_T2sI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXXXIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXL(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXLI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXLII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXLIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2sXLIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,38 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2s_1(i,j)=t1_2(i) || t1_2(j);
+  test_for_zero(t2s_1(0,0)-(t1_2(0)+t1_2(0)),"T1 || T1(0,0)");
+  test_for_zero(t2s_1(0,1)-(t1_2(0)+t1_2(1)),"T1 || T1(0,1)");
+  test_for_zero(t2s_1(0,2)-(t1_2(0)+t1_2(2)),"T1 || T1(0,2)");
+  test_for_zero(t2s_1(1,0)-(t1_2(1)+t1_2(0)),"T1 || T1(1,0)");
+  test_for_zero(t2s_1(1,1)-(t1_2(1)+t1_2(1)),"T1 || T1(1,1)");
+  test_for_zero(t2s_1(1,2)-(t1_2(1)+t1_2(2)),"T1 || T1(1,2)");
+  test_for_zero(t2s_1(2,0)-(t1_2(2)+t1_2(0)),"T1 || T1(2,0)");
+  test_for_zero(t2s_1(2,1)-(t1_2(2)+t1_2(1)),"T1 || T1(2,1)");
+  test_for_zero(t2s_1(2,2)-(t1_2(2)+t1_2(2)),"T1 || T1(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,39 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+
+  t2s_1(i,j)=t1_2(i)^t1_2(j);
+  test_for_zero(t2s_1(0,0)-t1_2(0)*t1_2(0),"T1^T1(0,0)");
+  test_for_zero(t2s_1(0,1)-t1_2(0)*t1_2(1),"T1^T1(0,1)");
+  test_for_zero(t2s_1(0,2)-t1_2(0)*t1_2(2),"T1^T1(0,2)");
+  test_for_zero(t2s_1(1,0)-t1_2(1)*t1_2(0),"T1^T1(1,0)");
+  test_for_zero(t2s_1(1,1)-t1_2(1)*t1_2(1),"T1^T1(1,1)");
+  test_for_zero(t2s_1(1,2)-t1_2(1)*t1_2(2),"T1^T1(1,2)");
+  test_for_zero(t2s_1(2,0)-t1_2(2)*t1_2(0),"T1^T1(2,0)");
+  test_for_zero(t2s_1(2,1)-t1_2(2)*t1_2(1),"T1^T1(2,1)");
+  test_for_zero(t2s_1(2,2)-t1_2(2)*t1_2(2),"T1^T1(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,38 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2s_1(i,j)=(t2_2(j,i) || t2_2(i,j));
+  test_for_zero(t2s_1(0,0)-(t2_2(0,0) + t2_2(0,0)),"T2(j,i)||T2(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2_2(0,1) + t2_2(1,0)),"T2(j,i)||T2(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2_2(0,2) + t2_2(2,0)),"T2(j,i)||T2(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2_2(1,0) + t2_2(0,1)),"T2(j,i)||T2(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2_2(1,1) + t2_2(1,1)),"T2(j,i)||T2(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2_2(1,2) + t2_2(2,1)),"T2(j,i)||T2(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2_2(2,0) + t2_2(0,2)),"T2(j,i)||T2(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2_2(2,1) + t2_2(1,2)),"T2(j,i)||T2(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2_2(2,2) + t2_2(2,2)),"T2(j,i)||T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,39 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2_2(j,i);
+  t2s_1(i,j)=(t2_2(i,j) || t2_1(i,j));
+  test_for_zero(t2s_1(0,0)-(t2_1(0,0) + t2_2(0,0)),"T2(i,j)||T2(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2_1(0,1) + t2_2(0,1)),"T2(i,j)||T2(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2_1(0,2) + t2_2(0,2)),"T2(i,j)||T2(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2_1(1,0) + t2_2(1,0)),"T2(i,j)||T2(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2_1(1,1) + t2_2(1,1)),"T2(i,j)||T2(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2_1(1,2) + t2_2(1,2)),"T2(i,j)||T2(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2_1(2,0) + t2_2(2,0)),"T2(i,j)||T2(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2_1(2,1) + t2_2(2,1)),"T2(i,j)||T2(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2_1(2,2) + t2_2(2,2)),"T2(i,j)||T2(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* add/subtract */
+
+  t2s_1(i,j)=t2s_2(i,j)-(t1_2(i)^t1_2(j));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)-t1_2(0)*t1_2(0)),"T2s(i,j)-T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)-t1_2(0)*t1_2(1)),"T2s(i,j)-T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)-t1_2(0)*t1_2(2)),"T2s(i,j)-T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)-t1_2(1)*t1_2(1)),"T2s(i,j)-T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)-t1_2(1)*t1_2(2)),"T2s(i,j)-T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)-t1_2(2)*t1_2(2)),"T2s(i,j)-T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Test of Number<> as an index. */
+
+  t2s_1(N0,i)=t1_2(i);
+  test_for_zero(t2s_1(0,0)-t1_2(0),"T2s(N,i)(0,0)");
+  test_for_zero(t2s_1(0,1)-t1_2(1),"T2s(N,i)(0,1)");
+  test_for_zero(t2s_1(0,2)-t1_2(2),"T2s(N,i)(0,2)");
+  t2s_1(N1,i)=t1_2(i);
+  test_for_zero(t2s_1(1,0)-t1_2(0),"T2s(N,i)(1,0)");
+  test_for_zero(t2s_1(1,1)-t1_2(1),"T2s(N,i)(1,1)");
+  test_for_zero(t2s_1(1,2)-t1_2(2),"T2s(N,i)(1,2)");
+  t2s_1(N2,i)=t1_2(i);
+  test_for_zero(t2s_1(2,0)-t1_2(0),"T2s(N,i)(2,0)");
+  test_for_zero(t2s_1(2,1)-t1_2(1),"T2s(N,i)(2,1)");
+  test_for_zero(t2s_1(2,2)-t1_2(2),"T2s(N,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Test of Number<> as an index. */
+
+  t2s_1(i,N0)=t1_2(i);
+  test_for_zero(t2s_1(0,0)-t1_2(0),"T2s(i,N)(0,0)");
+  test_for_zero(t2s_1(0,1)-t1_2(1),"T2s(i,N)(0,1)");
+  test_for_zero(t2s_1(0,2)-t1_2(2),"T2s(i,N)(0,2)");
+  t2s_1(i,N1)=t1_2(i);
+  test_for_zero(t2s_1(1,0)-t1_2(0),"T2s(i,N)(1,0)");
+  test_for_zero(t2s_1(1,1)-t1_2(1),"T2s(i,N)(1,1)");
+  test_for_zero(t2s_1(1,2)-t1_2(2),"T2s(i,N)(1,2)");
+  t2s_1(i,N2)=t1_2(i);
+  test_for_zero(t2s_1(2,0)-t1_2(0),"T2s(i,N)(2,0)");
+  test_for_zero(t2s_1(2,1)-t1_2(1),"T2s(i,N)(2,1)");
+  test_for_zero(t2s_1(2,2)-t1_2(2),"T2s(i,N)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Test of actual numerals as an index. */
+
+  t1_1(i)=t2s_1(0,i);
+  test_for_zero(t2s_1(0,0)-t1_1(0),"T2s(Num,i)(0,0)");
+  test_for_zero(t2s_1(0,1)-t1_1(1),"T2s(Num,i)(0,1)");
+  test_for_zero(t2s_1(0,2)-t1_1(2),"T2s(Num,i)(0,2)");
+  t1_1(i)=t2s_1(1,i);
+  test_for_zero(t2s_1(1,0)-t1_1(0),"T2s(Num,i)(1,0)");
+  test_for_zero(t2s_1(1,1)-t1_1(1),"T2s(Num,i)(1,1)");
+  test_for_zero(t2s_1(1,2)-t1_1(2),"T2s(Num,i)(1,2)");
+  t1_1(i)=t2s_1(2,i);
+  test_for_zero(t2s_1(2,0)-t1_1(0),"T2s(Num,i)(2,0)");
+  test_for_zero(t2s_1(2,1)-t1_1(1),"T2s(Num,i)(2,1)");
+  test_for_zero(t2s_1(2,2)-t1_1(2),"T2s(Num,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,44 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Test of actual numerals as an index. */
+
+  t1_1(i)=t2s_1(i,0);
+  test_for_zero(t2s_1(0,0)-t1_1(0),"T2s(i,Num)(0,0)");
+  test_for_zero(t2s_1(0,1)-t1_1(1),"T2s(i,Num)(0,1)");
+  test_for_zero(t2s_1(0,2)-t1_1(2),"T2s(i,Num)(0,2)");
+  t1_1(i)=t2s_1(i,1);
+  test_for_zero(t2s_1(1,0)-t1_1(0),"T2s(i,Num)(1,0)");
+  test_for_zero(t2s_1(1,1)-t1_1(1),"T2s(i,Num)(1,1)");
+  test_for_zero(t2s_1(1,2)-t1_1(2),"T2s(i,Num)(1,2)");
+  t1_1(i)=t2s_1(i,2);
+  test_for_zero(t2s_1(2,0)-t1_1(0),"T2s(i,Num)(2,0)");
+  test_for_zero(t2s_1(2,1)-t1_1(1),"T2s(i,Num)(2,1)");
+  test_for_zero(t2s_1(2,2)-t1_1(2),"T2s(i,Num)(2,2)");
+
+  test_for_zero(t2s_1(i,i)-(t1_2(0)+t1_2(1)+t1_2(2)),"T2s(i,i)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* add/subtract */
+
+  t2s_1(i,j)=t2s_2(i,j)-(t1_2(j)^t1_2(i));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)-t1_2(0)*t1_2(0)),"T2s(i,j)-T2s(j,i)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)-t1_2(1)*t1_2(0)),"T2s(i,j)-T2s(j,i)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)-t1_2(2)*t1_2(0)),"T2s(i,j)-T2s(j,i)(0,2)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)-t1_2(1)*t1_2(1)),"T2s(i,j)-T2s(j,i)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)-t1_2(2)*t1_2(1)),"T2s(i,j)-T2s(j,i)(1,2)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)-t1_2(2)*t1_2(2)),"T2s(i,j)-T2s(j,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* add/subtract */
+
+  t2s_1(i,j)=t2s_2(i,j)+(t1_2(i)^t1_2(j));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(i,j)+T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)+t1_2(0)*t1_2(1)),"T2s(i,j)+T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)+t1_2(0)*t1_2(2)),"T2s(i,j)+T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(i,j)+T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)+t1_2(1)*t1_2(2)),"T2s(i,j)+T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(i,j)+T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,37 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* add/subtract */
+
+  t2s_1(i,j)=t2s_2(i,j)+(t1_2(j)^t1_2(i));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(i,j)+T2s(j,i)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)+t1_2(1)*t1_2(0)),"T2s(i,j)+T2s(j,i)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)+t1_2(2)*t1_2(0)),"T2s(i,j)+T2s(j,i)(0,2)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(i,j)+T2s(j,i)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)+t1_2(2)*t1_2(1)),"T2s(i,j)+T2s(j,i)(1,2)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(i,j)+T2s(j,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Equals */
+
+  t2s_1(i,j)=t2s_2(i,j)+(t1_2(j)^t1_2(i));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(i,j)=T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)+t1_2(0)*t1_2(1)),"T2s(i,j)=T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)+t1_2(0)*t1_2(2)),"T2s(i,j)=T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)+t1_2(1)*t1_2(0)),"T2s(i,j)=T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(i,j)=T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)+t1_2(1)*t1_2(2)),"T2s(i,j)=T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)+t1_2(2)*t1_2(0)),"T2s(i,j)=T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)+t1_2(2)*t1_2(1)),"T2s(i,j)=T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(i,j)=T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Equals */
+
+  t2s_1(i,j)+=t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)-(2*t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(i,j)+=T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(2*t2s_2(0,1)+t1_2(0)*t1_2(1)),"T2s(i,j)+=T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(2*t2s_2(0,2)+t1_2(0)*t1_2(2)),"T2s(i,j)+=T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(2*t2s_2(1,0)+t1_2(1)*t1_2(0)),"T2s(i,j)+=T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(2*t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(i,j)+=T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(2*t2s_2(1,2)+t1_2(1)*t1_2(2)),"T2s(i,j)+=T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(2*t2s_2(2,0)+t1_2(2)*t1_2(0)),"T2s(i,j)+=T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(2*t2s_2(2,1)+t1_2(2)*t1_2(1)),"T2s(i,j)+=T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(2*t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(i,j)+=T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,84 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Equals */
+
+  t2s_1(i,j)+=10;
+  test_for_zero(t2s_1(0,0)-(-3*t2s_2(0,0)+t1_2(0)*t1_2(0)+10),"T2s+=T(0,0)");
+  test_for_zero(t2s_1(1,0)-(-3*t2s_2(0,1)+t1_2(0)*t1_2(1)+10),"T2s+=T(0,1)");
+  test_for_zero(t2s_1(2,0)-(-3*t2s_2(0,2)+t1_2(0)*t1_2(2)+10),"T2s+=T(0,2)");
+  test_for_zero(t2s_1(0,1)-(-3*t2s_2(1,0)+t1_2(1)*t1_2(0)+10),"T2s+=T(1,0)");
+  test_for_zero(t2s_1(1,1)-(-3*t2s_2(1,1)+t1_2(1)*t1_2(1)+10),"T2s+=T(1,1)");
+  test_for_zero(t2s_1(2,1)-(-3*t2s_2(1,2)+t1_2(1)*t1_2(2)+10),"T2s+=T(1,2)");
+  test_for_zero(t2s_1(0,2)-(-3*t2s_2(2,0)+t1_2(2)*t1_2(0)+10),"T2s+=T(2,0)");
+  test_for_zero(t2s_1(1,2)-(-3*t2s_2(2,1)+t1_2(2)*t1_2(1)+10),"T2s+=T(2,1)");
+  test_for_zero(t2s_1(2,2)-(-3*t2s_2(2,2)+t1_2(2)*t1_2(2)+10),"T2s+=T(2,2)");
+
+  t2s_1(i,j)-=7;
+  test_for_zero(t2s_1(0,0)-(-3*t2s_2(0,0)+t1_2(0)*t1_2(0)+3),"T2s-=T(0,0)");
+  test_for_zero(t2s_1(1,0)-(-3*t2s_2(0,1)+t1_2(0)*t1_2(1)+3),"T2s-=T(0,1)");
+  test_for_zero(t2s_1(2,0)-(-3*t2s_2(0,2)+t1_2(0)*t1_2(2)+3),"T2s-=T(0,2)");
+  test_for_zero(t2s_1(0,1)-(-3*t2s_2(1,0)+t1_2(1)*t1_2(0)+3),"T2s-=T(1,0)");
+  test_for_zero(t2s_1(1,1)-(-3*t2s_2(1,1)+t1_2(1)*t1_2(1)+3),"T2s-=T(1,1)");
+  test_for_zero(t2s_1(2,1)-(-3*t2s_2(1,2)+t1_2(1)*t1_2(2)+3),"T2s-=T(1,2)");
+  test_for_zero(t2s_1(0,2)-(-3*t2s_2(2,0)+t1_2(2)*t1_2(0)+3),"T2s-=T(2,0)");
+  test_for_zero(t2s_1(1,2)-(-3*t2s_2(2,1)+t1_2(2)*t1_2(1)+3),"T2s-=T(2,1)");
+  test_for_zero(t2s_1(2,2)-(-3*t2s_2(2,2)+t1_2(2)*t1_2(2)+3),"T2s-=T(2,2)");
+
+  t2s_1(i,j)*=12;
+  test_for_zero(t2s_1(0,0)-(-3*t2s_2(0,0)+t1_2(0)*t1_2(0)+3)*12,"T2s*=T(0,0)");
+  test_for_zero(t2s_1(1,0)-(-3*t2s_2(0,1)+t1_2(0)*t1_2(1)+3)*12,"T2s*=T(0,1)");
+  test_for_zero(t2s_1(2,0)-(-3*t2s_2(0,2)+t1_2(0)*t1_2(2)+3)*12,"T2s*=T(0,2)");
+  test_for_zero(t2s_1(0,1)-(-3*t2s_2(1,0)+t1_2(1)*t1_2(0)+3)*12,"T2s*=T(1,0)");
+  test_for_zero(t2s_1(1,1)-(-3*t2s_2(1,1)+t1_2(1)*t1_2(1)+3)*12,"T2s*=T(1,1)");
+  test_for_zero(t2s_1(2,1)-(-3*t2s_2(1,2)+t1_2(1)*t1_2(2)+3)*12,"T2s*=T(1,2)");
+  test_for_zero(t2s_1(0,2)-(-3*t2s_2(2,0)+t1_2(2)*t1_2(0)+3)*12,"T2s*=T(2,0)");
+  test_for_zero(t2s_1(1,2)-(-3*t2s_2(2,1)+t1_2(2)*t1_2(1)+3)*12,"T2s*=T(2,1)");
+  test_for_zero(t2s_1(2,2)-(-3*t2s_2(2,2)+t1_2(2)*t1_2(2)+3)*12,"T2s*=T(2,2)");
+
+  t2s_1(i,j)/=4;
+  test_for_zero(t2s_1(0,0)-(-3*t2s_2(0,0)+t1_2(0)*t1_2(0)+3)*3,"T2s/=T(0,0)");
+  test_for_zero(t2s_1(1,0)-(-3*t2s_2(0,1)+t1_2(0)*t1_2(1)+3)*3,"T2s/=T(0,1)");
+  test_for_zero(t2s_1(2,0)-(-3*t2s_2(0,2)+t1_2(0)*t1_2(2)+3)*3,"T2s/=T(0,2)");
+  test_for_zero(t2s_1(0,1)-(-3*t2s_2(1,0)+t1_2(1)*t1_2(0)+3)*3,"T2s/=T(1,0)");
+  test_for_zero(t2s_1(1,1)-(-3*t2s_2(1,1)+t1_2(1)*t1_2(1)+3)*3,"T2s/=T(1,1)");
+  test_for_zero(t2s_1(2,1)-(-3*t2s_2(1,2)+t1_2(1)*t1_2(2)+3)*3,"T2s/=T(1,2)");
+  test_for_zero(t2s_1(0,2)-(-3*t2s_2(2,0)+t1_2(2)*t1_2(0)+3)*3,"T2s/=T(2,0)");
+  test_for_zero(t2s_1(1,2)-(-3*t2s_2(2,1)+t1_2(2)*t1_2(1)+3)*3,"T2s/=T(2,1)");
+  test_for_zero(t2s_1(2,2)-(-3*t2s_2(2,2)+t1_2(2)*t1_2(2)+3)*3,"T2s/=T(2,2)");
+
+  t2s_1(i,j)=10;
+  test_for_zero(t2s_1(0,0)-10,"T2s=T(0,0)");
+  test_for_zero(t2s_1(1,0)-10,"T2s=T(0,1)");
+  test_for_zero(t2s_1(2,0)-10,"T2s=T(0,2)");
+  test_for_zero(t2s_1(0,1)-10,"T2s=T(1,0)");
+  test_for_zero(t2s_1(1,1)-10,"T2s=T(1,1)");
+  test_for_zero(t2s_1(2,1)-10,"T2s=T(1,2)");
+  test_for_zero(t2s_1(0,2)-10,"T2s=T(2,0)");
+  test_for_zero(t2s_1(1,2)-10,"T2s=T(2,1)");
+  test_for_zero(t2s_1(2,2)-10,"T2s=T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXL.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXL.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,66 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXL(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(k,i)*t2_2(j,k);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(1,0)*t2_2(0,1)
+		       + t2s_2(2,0)*t2_2(0,2)),"T2s(k,i)*T2(j,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(1,0) + t2s_2(1,0)*t2_2(1,1)
+		       + t2s_2(2,0)*t2_2(1,2)),"T2s(k,i)*T2(j,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(2,0) + t2s_2(1,0)*t2_2(2,1)
+		       + t2s_2(2,0)*t2_2(2,2)),"T2s(k,i)*T2(j,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(0,1)*t2_2(0,0) + t2s_2(1,1)*t2_2(0,1)
+		       + t2s_2(2,1)*t2_2(0,2)),"T2s(k,i)*T2(j,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(0,1)*t2_2(1,0) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(2,1)*t2_2(1,2)),"T2s(k,i)*T2(j,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(0,1)*t2_2(2,0) + t2s_2(1,1)*t2_2(2,1)
+		       + t2s_2(2,1)*t2_2(2,2)),"T2s(k,i)*T2(j,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(0,2)*t2_2(0,0) + t2s_2(1,2)*t2_2(0,1)
+		       + t2s_2(2,2)*t2_2(0,2)),"T2s(k,i)*T2(j,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(0,2)*t2_2(1,0) + t2s_2(1,2)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(1,2)),"T2s(k,i)*T2(j,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(0,2)*t2_2(2,0) + t2s_2(1,2)*t2_2(2,1)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2s(k,i)*T2(j,k)(2,2)");
+  t2_1(i,j)=t2_2(j,k)*t2s_2(k,i);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(1,0)*t2_2(0,1)
+		       + t2s_2(2,0)*t2_2(0,2)),"T2(j,k)*T2s(k,i)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(1,0) + t2s_2(1,0)*t2_2(1,1)
+		       + t2s_2(2,0)*t2_2(1,2)),"T2(j,k)*T2s(k,i)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(2,0) + t2s_2(1,0)*t2_2(2,1)
+		       + t2s_2(2,0)*t2_2(2,2)),"T2(j,k)*T2s(k,i)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(0,1)*t2_2(0,0) + t2s_2(1,1)*t2_2(0,1)
+		       + t2s_2(2,1)*t2_2(0,2)),"T2(j,k)*T2s(k,i)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(0,1)*t2_2(1,0) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(2,1)*t2_2(1,2)),"T2(j,k)*T2s(k,i)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(0,1)*t2_2(2,0) + t2s_2(1,1)*t2_2(2,1)
+		       + t2s_2(2,1)*t2_2(2,2)),"T2(j,k)*T2s(k,i)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(0,2)*t2_2(0,0) + t2s_2(1,2)*t2_2(0,1)
+		       + t2s_2(2,2)*t2_2(0,2)),"T2(j,k)*T2s(k,i)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(0,2)*t2_2(1,0) + t2s_2(1,2)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(1,2)),"T2(j,k)*T2s(k,i)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(0,2)*t2_2(2,0) + t2s_2(1,2)*t2_2(2,1)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2(j,k)*T2s(k,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXLI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXLI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,77 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXLI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(0,0)=t2s_2(0,0);
+  t2_1(0,1)=t2s_2(0,1);
+  t2_1(0,2)=t2s_2(0,2);
+  t2_1(1,0)=t2s_2(1,0);
+  t2_1(1,1)=t2s_2(1,1);
+  t2_1(1,2)=t2s_2(1,2);
+  t2_1(2,0)=t2s_2(2,0);
+  t2_1(2,1)=t2s_2(2,1);
+  t2_1(2,2)=t2s_2(2,2);
+
+  t2s_1(i,j)=t2s_2(i,k)^t2_1(k,j);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(0,1)*t2_1(1,0)
+		       + t2s_2(0,2)*t2_1(2,0)),"T2s(i,k)^T2(k,j)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(0,1) + t2s_2(0,1)*t2_1(1,1)
+		       + t2s_2(0,2)*t2_1(2,1)),"T2s(i,k)^T2(k,j)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(0,2) + t2s_2(0,1)*t2_1(1,2)
+		       + t2s_2(0,2)*t2_1(2,2)),"T2s(i,k)^T2(k,j)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(1,0)*t2_1(0,0) + t2s_2(1,1)*t2_1(1,0)
+		       + t2s_2(1,2)*t2_1(2,0)),"T2s(i,k)^T2(k,j)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(1,0)*t2_1(0,1) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(1,2)*t2_1(2,1)),"T2s(i,k)^T2(k,j)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(1,0)*t2_1(0,2) + t2s_2(1,1)*t2_1(1,2)
+		       + t2s_2(1,2)*t2_1(2,2)),"T2s(i,k)^T2(k,j)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(2,0)*t2_1(0,0) + t2s_2(2,1)*t2_1(1,0)
+		       + t2s_2(2,2)*t2_1(2,0)),"T2s(i,k)^T2(k,j)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(2,0)*t2_1(0,1) + t2s_2(2,1)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(2,1)),"T2s(i,k)^T2(k,j)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(2,0)*t2_1(0,2) + t2s_2(2,1)*t2_1(1,2)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2s(i,k)^T2(k,j)(2,2)");
+  t2s_1(i,j)=t2_1(k,j)^t2s_2(i,k);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(0,1)*t2_1(1,0)
+		       + t2s_2(0,2)*t2_1(2,0)),"T2(k,j)^T2s(i,k)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(0,1) + t2s_2(0,1)*t2_1(1,1)
+		       + t2s_2(0,2)*t2_1(2,1)),"T2(k,j)^T2s(i,k)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(0,2) + t2s_2(0,1)*t2_1(1,2)
+		       + t2s_2(0,2)*t2_1(2,2)),"T2(k,j)^T2s(i,k)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(1,0)*t2_1(0,0) + t2s_2(1,1)*t2_1(1,0)
+		       + t2s_2(1,2)*t2_1(2,0)),"T2(k,j)^T2s(i,k)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(1,0)*t2_1(0,1) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(1,2)*t2_1(2,1)),"T2(k,j)^T2s(i,k)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(1,0)*t2_1(0,2) + t2s_2(1,1)*t2_1(1,2)
+		       + t2s_2(1,2)*t2_1(2,2)),"T2(k,j)^T2s(i,k)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(2,0)*t2_1(0,0) + t2s_2(2,1)*t2_1(1,0)
+		       + t2s_2(2,2)*t2_1(2,0)),"T2(k,j)^T2s(i,k)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(2,0)*t2_1(0,1) + t2s_2(2,1)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(2,1)),"T2(k,j)^T2s(i,k)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(2,0)*t2_1(0,2) + t2s_2(2,1)*t2_1(1,2)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2(k,j)^T2s(i,k)(2,2)");
+
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXLII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXLII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,77 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXLII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(0,0)=t2s_2(0,0);
+  t2_1(0,1)=t2s_2(0,1);
+  t2_1(0,2)=t2s_2(0,2);
+  t2_1(1,0)=t2s_2(1,0);
+  t2_1(1,1)=t2s_2(1,1);
+  t2_1(1,2)=t2s_2(1,2);
+  t2_1(2,0)=t2s_2(2,0);
+  t2_1(2,1)=t2s_2(2,1);
+  t2_1(2,2)=t2s_2(2,2);
+
+  t2s_1(i,j)=t2s_2(i,k)^t2_1(j,k);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(0,1)*t2_1(0,1)
+		       + t2s_2(0,2)*t2_1(0,2)),"T2s(i,k)^T2(j,k)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(1,0) + t2s_2(0,1)*t2_1(1,1)
+		       + t2s_2(0,2)*t2_1(1,2)),"T2s(i,k)^T2(j,k)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(2,0) + t2s_2(0,1)*t2_1(2,1)
+		       + t2s_2(0,2)*t2_1(2,2)),"T2s(i,k)^T2(j,k)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(1,0)*t2_1(0,0) + t2s_2(1,1)*t2_1(0,1)
+		       + t2s_2(1,2)*t2_1(0,2)),"T2s(i,k)^T2(j,k)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(1,0)*t2_1(1,0) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(1,2)*t2_1(1,2)),"T2s(i,k)^T2(j,k)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(1,0)*t2_1(2,0) + t2s_2(1,1)*t2_1(2,1)
+		       + t2s_2(1,2)*t2_1(2,2)),"T2s(i,k)^T2(j,k)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(2,0)*t2_1(0,0) + t2s_2(2,1)*t2_1(0,1)
+		       + t2s_2(2,2)*t2_1(0,2)),"T2s(i,k)^T2(j,k)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(2,0)*t2_1(1,0) + t2s_2(2,1)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(1,2)),"T2s(i,k)^T2(j,k)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(2,0)*t2_1(2,0) + t2s_2(2,1)*t2_1(2,1)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2s(i,k)^T2(j,k)(2,2)");
+  t2s_1(i,j)=t2_1(j,k)^t2s_2(i,k);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(0,1)*t2_1(0,1)
+		       + t2s_2(0,2)*t2_1(0,2)),"T2(j,k)^T2s(i,k)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(1,0) + t2s_2(0,1)*t2_1(1,1)
+		       + t2s_2(0,2)*t2_1(1,2)),"T2(j,k)^T2s(i,k)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(2,0) + t2s_2(0,1)*t2_1(2,1)
+		       + t2s_2(0,2)*t2_1(2,2)),"T2(j,k)^T2s(i,k)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(1,0)*t2_1(0,0) + t2s_2(1,1)*t2_1(0,1)
+		       + t2s_2(1,2)*t2_1(0,2)),"T2(j,k)^T2s(i,k)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(1,0)*t2_1(1,0) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(1,2)*t2_1(1,2)),"T2(j,k)^T2s(i,k)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(1,0)*t2_1(2,0) + t2s_2(1,1)*t2_1(2,1)
+		       + t2s_2(1,2)*t2_1(2,2)),"T2(j,k)^T2s(i,k)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(2,0)*t2_1(0,0) + t2s_2(2,1)*t2_1(0,1)
+		       + t2s_2(2,2)*t2_1(0,2)),"T2(j,k)^T2s(i,k)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(2,0)*t2_1(1,0) + t2s_2(2,1)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(1,2)),"T2(j,k)^T2s(i,k)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(2,0)*t2_1(2,0) + t2s_2(2,1)*t2_1(2,1)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2(j,k)^T2s(i,k)(2,2)");
+
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXLIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXLIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,79 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXLIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(0,0)=t2s_2(0,0);
+  t2_1(0,1)=t2s_2(0,1);
+  t2_1(0,2)=t2s_2(0,2);
+  t2_1(1,0)=t2s_2(1,0);
+  t2_1(1,1)=t2s_2(1,1);
+  t2_1(1,2)=t2s_2(1,2);
+  t2_1(2,0)=t2s_2(2,0);
+  t2_1(2,1)=t2s_2(2,1);
+  t2_1(2,2)=t2s_2(2,2);
+
+
+
+  t2s_1(i,j)=t2s_2(k,i)^t2_1(k,j);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(1,0)*t2_1(1,0)
+		       + t2s_2(2,0)*t2_1(2,0)),"T2s(k,i)^T2(k,j)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(0,1) + t2s_2(1,0)*t2_1(1,1)
+		       + t2s_2(2,0)*t2_1(2,1)),"T2s(k,i)^T2(k,j)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(0,2) + t2s_2(1,0)*t2_1(1,2)
+		       + t2s_2(2,0)*t2_1(2,2)),"T2s(k,i)^T2(k,j)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(0,1)*t2_1(0,0) + t2s_2(1,1)*t2_1(1,0)
+		       + t2s_2(2,1)*t2_1(2,0)),"T2s(k,i)^T2(k,j)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(0,1)*t2_1(0,1) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(2,1)*t2_1(2,1)),"T2s(k,i)^T2(k,j)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(0,1)*t2_1(0,2) + t2s_2(1,1)*t2_1(1,2)
+		       + t2s_2(2,1)*t2_1(2,2)),"T2s(k,i)^T2(k,j)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(0,2)*t2_1(0,0) + t2s_2(1,2)*t2_1(1,0)
+		       + t2s_2(2,2)*t2_1(2,0)),"T2s(k,i)^T2(k,j)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(0,2)*t2_1(0,1) + t2s_2(1,2)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(2,1)),"T2s(k,i)^T2(k,j)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(0,2)*t2_1(0,2) + t2s_2(1,2)*t2_1(1,2)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2s(k,i)^T2(k,j)(2,2)");
+  t2s_1(i,j)=t2_1(k,j)^t2s_2(k,i);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(1,0)*t2_1(1,0)
+		       + t2s_2(2,0)*t2_1(2,0)),"T2(k,j)^T2s(k,i)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(0,1) + t2s_2(1,0)*t2_1(1,1)
+		       + t2s_2(2,0)*t2_1(2,1)),"T2(k,j)^T2s(k,i)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(0,2) + t2s_2(1,0)*t2_1(1,2)
+		       + t2s_2(2,0)*t2_1(2,2)),"T2(k,j)^T2s(k,i)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(0,1)*t2_1(0,0) + t2s_2(1,1)*t2_1(1,0)
+		       + t2s_2(2,1)*t2_1(2,0)),"T2(k,j)^T2s(k,i)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(0,1)*t2_1(0,1) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(2,1)*t2_1(2,1)),"T2(k,j)^T2s(k,i)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(0,1)*t2_1(0,2) + t2s_2(1,1)*t2_1(1,2)
+		       + t2s_2(2,1)*t2_1(2,2)),"T2(k,j)^T2s(k,i)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(0,2)*t2_1(0,0) + t2s_2(1,2)*t2_1(1,0)
+		       + t2s_2(2,2)*t2_1(2,0)),"T2(k,j)^T2s(k,i)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(0,2)*t2_1(0,1) + t2s_2(1,2)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(2,1)),"T2(k,j)^T2s(k,i)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(0,2)*t2_1(0,2) + t2s_2(1,2)*t2_1(1,2)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2(k,j)^T2s(k,i)(2,2)");
+
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXLIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXLIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,77 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXLIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(0,0)=t2s_2(0,0);
+  t2_1(0,1)=t2s_2(0,1);
+  t2_1(0,2)=t2s_2(0,2);
+  t2_1(1,0)=t2s_2(1,0);
+  t2_1(1,1)=t2s_2(1,1);
+  t2_1(1,2)=t2s_2(1,2);
+  t2_1(2,0)=t2s_2(2,0);
+  t2_1(2,1)=t2s_2(2,1);
+  t2_1(2,2)=t2s_2(2,2);
+
+  t2s_1(i,j)=t2s_2(k,i)^t2_1(j,k);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(1,0)*t2_1(0,1)
+		       + t2s_2(2,0)*t2_1(0,2)),"T2s(k,i)^T2(j,k)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(1,0) + t2s_2(1,0)*t2_1(1,1)
+		       + t2s_2(2,0)*t2_1(1,2)),"T2s(k,i)^T2(j,k)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(2,0) + t2s_2(1,0)*t2_1(2,1)
+		       + t2s_2(2,0)*t2_1(2,2)),"T2s(k,i)^T2(j,k)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(0,1)*t2_1(0,0) + t2s_2(1,1)*t2_1(0,1)
+		       + t2s_2(2,1)*t2_1(0,2)),"T2s(k,i)^T2(j,k)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(0,1)*t2_1(1,0) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(2,1)*t2_1(1,2)),"T2s(k,i)^T2(j,k)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(0,1)*t2_1(2,0) + t2s_2(1,1)*t2_1(2,1)
+		       + t2s_2(2,1)*t2_1(2,2)),"T2s(k,i)^T2(j,k)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(0,2)*t2_1(0,0) + t2s_2(1,2)*t2_1(0,1)
+		       + t2s_2(2,2)*t2_1(0,2)),"T2s(k,i)^T2(j,k)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(0,2)*t2_1(1,0) + t2s_2(1,2)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(1,2)),"T2s(k,i)^T2(j,k)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(0,2)*t2_1(2,0) + t2s_2(1,2)*t2_1(2,1)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2s(k,i)^T2(j,k)(2,2)");
+  t2s_1(i,j)=t2_1(j,k)^t2s_2(k,i);
+  test_for_zero(t2s_1(0,0) - (t2s_2(0,0)*t2_1(0,0) + t2s_2(1,0)*t2_1(0,1)
+		       + t2s_2(2,0)*t2_1(0,2)),"T2(j,k)^T2s(k,i)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t2s_2(0,0)*t2_1(1,0) + t2s_2(1,0)*t2_1(1,1)
+		       + t2s_2(2,0)*t2_1(1,2)),"T2(j,k)^T2s(k,i)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t2s_2(0,0)*t2_1(2,0) + t2s_2(1,0)*t2_1(2,1)
+		       + t2s_2(2,0)*t2_1(2,2)),"T2(j,k)^T2s(k,i)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t2s_2(0,1)*t2_1(0,0) + t2s_2(1,1)*t2_1(0,1)
+		       + t2s_2(2,1)*t2_1(0,2)),"T2(j,k)^T2s(k,i)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t2s_2(0,1)*t2_1(1,0) + t2s_2(1,1)*t2_1(1,1)
+		       + t2s_2(2,1)*t2_1(1,2)),"T2(j,k)^T2s(k,i)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t2s_2(0,1)*t2_1(2,0) + t2s_2(1,1)*t2_1(2,1)
+		       + t2s_2(2,1)*t2_1(2,2)),"T2(j,k)^T2s(k,i)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t2s_2(0,2)*t2_1(0,0) + t2s_2(1,2)*t2_1(0,1)
+		       + t2s_2(2,2)*t2_1(0,2)),"T2(j,k)^T2s(k,i)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t2s_2(0,2)*t2_1(1,0) + t2s_2(1,2)*t2_1(1,1)
+		       + t2s_2(2,2)*t2_1(1,2)),"T2(j,k)^T2s(k,i)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t2s_2(0,2)*t2_1(2,0) + t2s_2(1,2)*t2_1(2,1)
+		       + t2s_2(2,2)*t2_1(2,2)),"T2(j,k)^T2s(k,i)(2,2)");
+
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Equals */
+
+  t2s_1(i,j)-=5*t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)-(-3*t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(i,j)-=T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(-3*t2s_2(0,1)+t1_2(0)*t1_2(1)),"T2s(i,j)-=T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(-3*t2s_2(0,2)+t1_2(0)*t1_2(2)),"T2s(i,j)-=T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(-3*t2s_2(1,0)+t1_2(1)*t1_2(0)),"T2s(i,j)-=T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(-3*t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(i,j)-=T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(-3*t2s_2(1,2)+t1_2(1)*t1_2(2)),"T2s(i,j)-=T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(-3*t2s_2(2,0)+t1_2(2)*t1_2(0)),"T2s(i,j)-=T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(-3*t2s_2(2,1)+t1_2(2)*t1_2(1)),"T2s(i,j)-=T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(-3*t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(i,j)-=T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Equals */
+
+  /* Switch indices */
+
+  t2s_1(j,i)=t2s_2(i,j)+(t1_2(j)^t1_2(i));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(0,0)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(0,1)+t1_2(0)*t1_2(1)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(0,1)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(0,2)+t1_2(0)*t1_2(2)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(0,2)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(1,0)+t1_2(1)*t1_2(0)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(1,1)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(1,2)+t1_2(1)*t1_2(2)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(1,2)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(2,0)+t1_2(2)*t1_2(0)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(2,0)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(2,1)+t1_2(2)*t1_2(1)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(j,i)=T2s(i,j)+T2s(j,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Equals */
+
+  /* Switch indices */
+
+  t2s_1(j,i)+=t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)-(2*t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(j,i)+=T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(1,0)-(2*t2s_2(0,1)+t1_2(0)*t1_2(1)),"T2s(j,i)+=T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(2,0)-(2*t2s_2(0,2)+t1_2(0)*t1_2(2)),"T2s(j,i)+=T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(0,1)-(2*t2s_2(1,0)+t1_2(1)*t1_2(0)),"T2s(j,i)+=T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(2*t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(j,i)+=T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(2,1)-(2*t2s_2(1,2)+t1_2(1)*t1_2(2)),"T2s(j,i)+=T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(0,2)-(2*t2s_2(2,0)+t1_2(2)*t1_2(0)),"T2s(j,i)+=T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(1,2)-(2*t2s_2(2,1)+t1_2(2)*t1_2(1)),"T2s(j,i)+=T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(2*t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(j,i)+=T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,42 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Equals */
+
+  /* Switch indices */
+
+  t2s_1(j,i)-=5*t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)-(-3*t2s_2(0,0)+t1_2(0)*t1_2(0)),"T2s(j,i)-=T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(1,0)-(-3*t2s_2(0,1)+t1_2(0)*t1_2(1)),"T2s(j,i)-=T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(2,0)-(-3*t2s_2(0,2)+t1_2(0)*t1_2(2)),"T2s(j,i)-=T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(0,1)-(-3*t2s_2(1,0)+t1_2(1)*t1_2(0)),"T2s(j,i)-=T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(-3*t2s_2(1,1)+t1_2(1)*t1_2(1)),"T2s(j,i)-=T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(2,1)-(-3*t2s_2(1,2)+t1_2(1)*t1_2(2)),"T2s(j,i)-=T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(0,2)-(-3*t2s_2(2,0)+t1_2(2)*t1_2(0)),"T2s(j,i)-=T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(1,2)-(-3*t2s_2(2,1)+t1_2(2)*t1_2(1)),"T2s(j,i)-=T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(-3*t2s_2(2,2)+t1_2(2)*t1_2(2)),"T2s(j,i)-=T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,39 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric*Tensor1 */
+
+  t1_1(i)=t2s_2(i,j)*t1_2(j);
+  test_for_zero(t1_1(0)-(t2s_2(0,0)*t1_2(0) + t2s_2(0,1)*t1_2(1) +t2s_2(0,2)*t1_2(2)),"T2s(i,j)*T1(j)(0)");
+  test_for_zero(t1_1(1)-(t2s_2(1,0)*t1_2(0) + t2s_2(1,1)*t1_2(1) +t2s_2(1,2)*t1_2(2)),"T2s(i,j)*T1(j)(1)");
+  test_for_zero(t1_1(2)-(t2s_2(2,0)*t1_2(0) + t2s_2(2,1)*t1_2(1) +t2s_2(2,2)*t1_2(2)),"T2s(i,j)*T1(j)(2)");
+
+  t1_1(i)=t1_2(j)*t2s_2(i,j);
+  test_for_zero(t1_1(0)-(t2s_2(0,0)*t1_2(0) + t2s_2(0,1)*t1_2(1) +t2s_2(0,2)*t1_2(2)),"T1(j)*T2s(i,j)(0)");
+  test_for_zero(t1_1(1)-(t2s_2(1,0)*t1_2(0) + t2s_2(1,1)*t1_2(1) +t2s_2(1,2)*t1_2(2)),"T1(j)*T2s(i,j)(1)");
+  test_for_zero(t1_1(2)-(t2s_2(2,0)*t1_2(0) + t2s_2(2,1)*t1_2(1) +t2s_2(2,2)*t1_2(2)),"T1(j)*T2s(i,j)(2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,39 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric*Tensor1 */
+
+  t1_1(j)=t2s_2(i,j)*t1_2(i);
+  test_for_zero(t1_1(0)-(t2s_2(0,0)*t1_2(0) + t2s_2(1,0)*t1_2(1) +t2s_2(2,0)*t1_2(2)),"T2s(i,j)*T1(i)(0)");
+  test_for_zero(t1_1(1)-(t2s_2(0,1)*t1_2(0) + t2s_2(1,1)*t1_2(1) +t2s_2(2,1)*t1_2(2)),"T2s(i,j)*T1(i)(1)");
+  test_for_zero(t1_1(2)-(t2s_2(0,2)*t1_2(0) + t2s_2(1,2)*t1_2(1) +t2s_2(2,2)*t1_2(2)),"T2s(i,j)*T1(i)(2)");
+
+  t1_1(j)=t1_2(i)*t2s_2(i,j);
+  test_for_zero(t1_1(0)-(t2s_2(0,0)*t1_2(0) + t2s_2(1,0)*t1_2(1) +t2s_2(2,0)*t1_2(2)),"T1(i)*T2s(i,j)(0)");
+  test_for_zero(t1_1(1)-(t2s_2(0,1)*t1_2(0) + t2s_2(1,1)*t1_2(1) +t2s_2(2,1)*t1_2(2)),"T1(i)*T2s(i,j)(1)");
+  test_for_zero(t1_1(2)-(t2s_2(0,2)*t1_2(0) + t2s_2(1,2)*t1_2(1) +t2s_2(2,2)*t1_2(2)),"T1(i)*T2s(i,j)(2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,45 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric*Tensor2_symmetric */
+
+  test_for_zero
+    (t2s_1(i,j)*t2s_2(i,j)
+     -(t2s_1(0,0)*t2s_2(0,0) + t2s_1(0,1)*t2s_2(0,1) + t2s_1(0,2)*t2s_2(0,2)
+       + t2s_1(1,0)*t2s_2(1,0) + t2s_1(1,1)*t2s_2(1,1) + t2s_1(1,2)*t2s_2(1,2)
+       + t2s_1(2,0)*t2s_2(2,0) + t2s_1(2,1)*t2s_2(2,1) 
+       + t2s_1(2,2)*t2s_2(2,2)),
+     "T2s(i,j)*T2s(i,j)");	
+
+  test_for_zero
+    (t2s_1(i,j)*t2s_2(j,i)
+     -(t2s_1(0,0)*t2s_2(0,0) + t2s_1(0,1)*t2s_2(1,0) + t2s_1(0,2)*t2s_2(2,0)
+       + t2s_1(1,0)*t2s_2(0,1) + t2s_1(1,1)*t2s_2(1,1) + t2s_1(1,2)*t2s_2(2,1)
+       + t2s_1(2,0)*t2s_2(0,2) + t2s_1(2,1)*t2s_2(1,2)
+       + t2s_1(2,2)*t2s_2(2,2)),
+     "T2s(i,j)*T2s(j,i)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,59 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric*Tensor2_symmetric */
+
+  t2_1(i,k)=t2s_2(i,j)*t2s_3(j,k);
+  test_for_zero
+    (t2_1(0,0)
+     - (t2s_2(0,0)*t2s_3(0,0) + t2s_2(0,1)*t2s_3(1,0) + t2s_2(0,2)*t2s_3(2,0)),
+     "T2s(i,j)*T2s(j,k)(0,0)");
+  test_for_zero(t2_1(0,1)
+		- (t2s_2(0,0)*t2s_3(0,1) + t2s_2(0,1)*t2s_3(1,1) + t2s_2(0,2)*t2s_3(2,1)),
+     "T2s(i,j)*T2s(j,k)(0,1)");
+  test_for_zero(t2_1(0,2)
+		- (t2s_2(0,0)*t2s_3(0,2) + t2s_2(0,1)*t2s_3(1,2) + t2s_2(0,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(j,k)(0,2)");
+  test_for_zero(t2_1(1,0)
+		- (t2s_2(1,0)*t2s_3(0,0) + t2s_2(1,1)*t2s_3(1,0) + t2s_2(1,2)*t2s_3(2,0)),
+     "T2s(i,j)*T2s(j,k)(1,0)");
+  test_for_zero(t2_1(1,1)
+		- (t2s_2(1,0)*t2s_3(0,1) + t2s_2(1,1)*t2s_3(1,1) + t2s_2(1,2)*t2s_3(2,1)),
+     "T2s(i,j)*T2s(j,k)(1,1)");
+  test_for_zero(t2_1(1,2)
+		- (t2s_2(1,0)*t2s_3(0,2) + t2s_2(1,1)*t2s_3(1,2) + t2s_2(1,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(j,k)(1,2)");
+  test_for_zero(t2_1(2,0)
+		- (t2s_2(2,0)*t2s_3(0,0) + t2s_2(2,1)*t2s_3(1,0) + t2s_2(2,2)*t2s_3(2,0)),
+     "T2s(i,j)*T2s(j,k)(2,0)");
+  test_for_zero(t2_1(2,1)
+		- (t2s_2(2,0)*t2s_3(0,1) + t2s_2(2,1)*t2s_3(1,1) + t2s_2(2,2)*t2s_3(2,1)),
+     "T2s(i,j)*T2s(j,k)(2,1)");
+  test_for_zero(t2_1(2,2)
+		- (t2s_2(2,0)*t2s_3(0,2) + t2s_2(2,1)*t2s_3(1,2) + t2s_2(2,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(j,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,58 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric*Tensor2_symmetric */
+
+  t2_1(i,k)=t2s_2(i,j)*t2s_3(k,j);
+  test_for_zero(t2_1(0,0)
+		- (t2s_2(0,0)*t2s_3(0,0) + t2s_2(0,1)*t2s_3(0,1) + t2s_2(0,2)*t2s_3(0,2)),
+     "T2s(i,j)*T2s(k,j)(0,0)");
+  test_for_zero(t2_1(0,1)
+		- (t2s_2(0,0)*t2s_3(1,0) + t2s_2(0,1)*t2s_3(1,1) + t2s_2(0,2)*t2s_3(1,2)),
+     "T2s(i,j)*T2s(k,j)(0,1)");
+  test_for_zero(t2_1(0,2)
+		- (t2s_2(0,0)*t2s_3(2,0) + t2s_2(0,1)*t2s_3(2,1) + t2s_2(0,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(k,j)(0,2)");
+  test_for_zero(t2_1(1,0)
+		- (t2s_2(1,0)*t2s_3(0,0) + t2s_2(1,1)*t2s_3(0,1) + t2s_2(1,2)*t2s_3(0,2)),
+     "T2s(i,j)*T2s(k,j)(1,0)");
+  test_for_zero(t2_1(1,1)
+		- (t2s_2(1,0)*t2s_3(1,0) + t2s_2(1,1)*t2s_3(1,1) + t2s_2(1,2)*t2s_3(1,2)),
+     "T2s(i,j)*T2s(k,j)(1,1)");
+  test_for_zero(t2_1(1,2)
+		- (t2s_2(1,0)*t2s_3(2,0) + t2s_2(1,1)*t2s_3(2,1) + t2s_2(1,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(k,j)(1,2)");
+  test_for_zero(t2_1(2,0)
+		- (t2s_2(2,0)*t2s_3(0,0) + t2s_2(2,1)*t2s_3(0,1) + t2s_2(2,2)*t2s_3(0,2)),
+     "T2s(i,j)*T2s(k,j)(2,0)");
+  test_for_zero(t2_1(2,1)
+		- (t2s_2(2,0)*t2s_3(1,0) + t2s_2(2,1)*t2s_3(1,1) + t2s_2(2,2)*t2s_3(1,2)),
+     "T2s(i,j)*T2s(k,j)(2,1)");
+  test_for_zero(t2_1(2,2)
+		- (t2s_2(2,0)*t2s_3(2,0) + t2s_2(2,1)*t2s_3(2,1) + t2s_2(2,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(k,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* -Tensor2_symmetric */
+
+  t2s_1(i,j)=-t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)+(t2s_2(0,0)),"-T2s(0,0)");
+  test_for_zero(t2s_1(0,1)+(t2s_2(0,1)),"-T2s(0,1)");
+  test_for_zero(t2s_1(0,2)+(t2s_2(0,2)),"-T2s(0,2)");
+  test_for_zero(t2s_1(1,0)+(t2s_2(1,0)),"-T2s(1,0)");
+  test_for_zero(t2s_1(1,1)+(t2s_2(1,1)),"-T2s(1,1)");
+  test_for_zero(t2s_1(1,2)+(t2s_2(1,2)),"-T2s(1,2)");
+  test_for_zero(t2s_1(2,0)+(t2s_2(2,0)),"-T2s(2,0)");
+  test_for_zero(t2s_1(2,1)+(t2s_2(2,1)),"-T2s(2,1)");
+  test_for_zero(t2s_1(2,2)+(t2s_2(2,2)),"-T2s(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,58 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric*Tensor2_symmetric */
+
+  t2_1(j,k)=t2s_2(i,j)*t2s_3(i,k);
+  test_for_zero(t2_1(0,0)
+		- (t2s_2(0,0)*t2s_3(0,0) + t2s_2(1,0)*t2s_3(1,0) + t2s_2(2,0)*t2s_3(2,0)),
+     "T2s(i,j)*T2s(i,k)(0,0)");
+  test_for_zero(t2_1(0,1)
+		- (t2s_2(0,0)*t2s_3(0,1) + t2s_2(1,0)*t2s_3(1,1) + t2s_2(2,0)*t2s_3(2,1)),
+     "T2s(i,j)*T2s(i,k)(0,1)");
+  test_for_zero(t2_1(0,2)
+		- (t2s_2(0,0)*t2s_3(0,2) + t2s_2(1,0)*t2s_3(1,2) + t2s_2(2,0)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(i,k)(0,2)");
+  test_for_zero(t2_1(1,0)
+		- (t2s_2(0,1)*t2s_3(0,0) + t2s_2(1,1)*t2s_3(1,0) + t2s_2(2,1)*t2s_3(2,0)),
+     "T2s(i,j)*T2s(i,k)(1,0)");
+  test_for_zero(t2_1(1,1)
+		- (t2s_2(0,1)*t2s_3(0,1) + t2s_2(1,1)*t2s_3(1,1) + t2s_2(2,1)*t2s_3(2,1)),
+     "T2s(i,j)*T2s(i,k)(1,1)");
+  test_for_zero(t2_1(1,2)
+		- (t2s_2(0,1)*t2s_3(0,2) + t2s_2(1,1)*t2s_3(1,2) + t2s_2(2,1)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(i,k)(1,2)");
+  test_for_zero(t2_1(2,0)
+		- (t2s_2(0,2)*t2s_3(0,0) + t2s_2(1,2)*t2s_3(1,0) + t2s_2(2,2)*t2s_3(2,0)),
+     "T2s(i,j)*T2s(i,k)(2,0)");
+  test_for_zero(t2_1(2,1)
+		- (t2s_2(0,2)*t2s_3(0,1) + t2s_2(1,2)*t2s_3(1,1) + t2s_2(2,2)*t2s_3(2,1)),
+     "T2s(i,j)*T2s(i,k)(2,1)");
+  test_for_zero(t2_1(2,2)
+		- (t2s_2(0,2)*t2s_3(0,2) + t2s_2(1,2)*t2s_3(1,2) + t2s_2(2,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(i,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,58 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric*Tensor2_symmetric */
+
+  t2_1(j,k)=t2s_2(i,j)*t2s_3(k,i);
+  test_for_zero(t2_1(0,0)
+		- (t2s_2(0,0)*t2s_3(0,0) + t2s_2(1,0)*t2s_3(0,1) + t2s_2(2,0)*t2s_3(0,2)),
+     "T2s(i,j)*T2s(k,i)(0,0)");
+  test_for_zero(t2_1(0,1)
+		- (t2s_2(0,0)*t2s_3(1,0) + t2s_2(1,0)*t2s_3(1,1) + t2s_2(2,0)*t2s_3(1,2)),
+     "T2s(i,j)*T2s(k,i)(0,1)");
+  test_for_zero(t2_1(0,2)
+		- (t2s_2(0,0)*t2s_3(2,0) + t2s_2(1,0)*t2s_3(2,1) + t2s_2(2,0)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(k,i)(0,2)");
+  test_for_zero(t2_1(1,0)
+		- (t2s_2(0,1)*t2s_3(0,0) + t2s_2(1,1)*t2s_3(0,1) + t2s_2(2,1)*t2s_3(0,2)),
+     "T2s(i,j)*T2s(k,i)(1,0)");
+  test_for_zero(t2_1(1,1)
+		- (t2s_2(0,1)*t2s_3(1,0) + t2s_2(1,1)*t2s_3(1,1) + t2s_2(2,1)*t2s_3(1,2)),
+     "T2s(i,j)*T2s(k,i)(1,1)");
+  test_for_zero(t2_1(1,2)
+		- (t2s_2(0,1)*t2s_3(2,0) + t2s_2(1,1)*t2s_3(2,1) + t2s_2(2,1)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(k,i)(1,2)");
+  test_for_zero(t2_1(2,0)
+		- (t2s_2(0,2)*t2s_3(0,0) + t2s_2(1,2)*t2s_3(0,1) + t2s_2(2,2)*t2s_3(0,2)),
+     "T2s(i,j)*T2s(k,i)(2,0)");
+  test_for_zero(t2_1(2,1)
+		- (t2s_2(0,2)*t2s_3(1,0) + t2s_2(1,2)*t2s_3(1,1) + t2s_2(2,2)*t2s_3(1,2)),
+     "T2s(i,j)*T2s(k,i)(2,1)");
+  test_for_zero(t2_1(2,2)
+		- (t2s_2(0,2)*t2s_3(2,0) + t2s_2(1,2)*t2s_3(2,1) + t2s_2(2,2)*t2s_3(2,2)),
+     "T2s(i,j)*T2s(k,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,62 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric+-*T or /T */
+  
+  t2s_1(i,j)=t2s_2(i,j)*10;
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)*10),"T2s*T(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)*10),"T2s*T(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)*10),"T2s*T(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)*10),"T2s*T(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)*10),"T2s*T(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)*10),"T2s*T(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)*10),"T2s*T(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)*10),"T2s*T(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)*10),"T2s*T(2,2)");
+
+  t2s_1(i,j)=10*t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)*10),"T*T2s(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)*10),"T*T2s(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)*10),"T*T2s(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)*10),"T*T2s(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)*10),"T*T2s(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)*10),"T*T2s(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)*10),"T*T2s(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)*10),"T*T2s(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)*10),"T*T2s(2,2)");
+  
+  t2s_1(i,j)=t2s_2(i,j)/10;
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)/10),"T2s/T(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)/10),"T2s/T(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)/10),"T2s/T(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)/10),"T2s/T(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)/10),"T2s/T(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)/10),"T2s/T(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)/10),"T2s/T(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)/10),"T2s/T(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)/10),"T2s/T(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,73 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  /* Tensor2_symmetric+-*T or /T */
+
+  t2s_1(i,j)=t2s_2(i,j)+10;
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)+10),"T2s+T(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)+10),"T2s+T(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)+10),"T2s+T(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)+10),"T2s+T(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)+10),"T2s+T(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)+10),"T2s+T(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)+10),"T2s+T(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)+10),"T2s+T(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)+10),"T2s+T(2,2)");
+
+  t2s_1(i,j)=10+t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)+10),"T+T2s(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)+10),"T+T2s(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)+10),"T+T2s(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)+10),"T+T2s(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)+10),"T+T2s(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)+10),"T+T2s(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)+10),"T+T2s(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)+10),"T+T2s(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)+10),"T+T2s(2,2)");
+
+  t2s_1(i,j)=t2s_2(i,j)-10;
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)-10),"T2s-T(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)-10),"T2s-T(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)-10),"T2s-T(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)-10),"T2s-T(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)-10),"T2s-T(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)-10),"T2s-T(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)-10),"T2s-T(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)-10),"T2s-T(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)-10),"T2s-T(2,2)");
+
+  t2s_1(i,j)=10-t2s_2(i,j);
+  test_for_zero(t2s_1(0,0)-(10-t2s_2(0,0)),"T-T2s(0,0)");
+  test_for_zero(t2s_1(0,1)-(10-t2s_2(0,1)),"T-T2s(0,1)");
+  test_for_zero(t2s_1(0,2)-(10-t2s_2(0,2)),"T-T2s(0,2)");
+  test_for_zero(t2s_1(1,0)-(10-t2s_2(1,0)),"T-T2s(1,0)");
+  test_for_zero(t2s_1(1,1)-(10-t2s_2(1,1)),"T-T2s(1,1)");
+  test_for_zero(t2s_1(1,2)-(10-t2s_2(1,2)),"T-T2s(1,2)");
+  test_for_zero(t2s_1(2,0)-(10-t2s_2(2,0)),"T-T2s(2,0)");
+  test_for_zero(t2s_1(2,1)-(10-t2s_2(2,1)),"T-T2s(2,1)");
+  test_for_zero(t2s_1(2,2)-(10-t2s_2(2,2)),"T-T2s(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,48 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(i,j)+t2_2(i,j);
+  test_for_zero(t2_1(0,0)-(t2s_2(0,0)+t2_2(0,0)),"T2s(i,j)+T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2s_2(0,1)+t2_2(0,1)),"T2s(i,j)+T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2s_2(0,2)+t2_2(0,2)),"T2s(i,j)+T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2s_2(1,0)+t2_2(1,0)),"T2s(i,j)+T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2s_2(1,1)+t2_2(1,1)),"T2s(i,j)+T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2s_2(1,2)+t2_2(1,2)),"T2s(i,j)+T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2s_2(2,0)+t2_2(2,0)),"T2s(i,j)+T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2s_2(2,1)+t2_2(2,1)),"T2s(i,j)+T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2s_2(2,2)+t2_2(2,2)),"T2s(i,j)+T2(i,j)(2,2)");
+  t2_1(i,j)=t2_2(i,j)+t2s_2(i,j);
+  test_for_zero(t2_1(0,0)-(t2s_2(0,0)+t2_2(0,0)),"T2(i,j)+T2s(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2s_2(0,1)+t2_2(0,1)),"T2(i,j)+T2s(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2s_2(0,2)+t2_2(0,2)),"T2(i,j)+T2s(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2s_2(1,0)+t2_2(1,0)),"T2(i,j)+T2s(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2s_2(1,1)+t2_2(1,1)),"T2(i,j)+T2s(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2s_2(1,2)+t2_2(1,2)),"T2(i,j)+T2s(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2s_2(2,0)+t2_2(2,0)),"T2(i,j)+T2s(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2s_2(2,1)+t2_2(2,1)),"T2(i,j)+T2s(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2s_2(2,2)+t2_2(2,2)),"T2(i,j)+T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,48 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(i,j)+t2_2(j,i);
+  test_for_zero(t2_1(0,0)-(t2s_2(0,0)+t2_2(0,0)),"T2s(i,j)+T2(j,i)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2s_2(0,1)+t2_2(1,0)),"T2s(i,j)+T2(j,i)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2s_2(0,2)+t2_2(2,0)),"T2s(i,j)+T2(j,i)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2s_2(1,0)+t2_2(0,1)),"T2s(i,j)+T2(j,i)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2s_2(1,1)+t2_2(1,1)),"T2s(i,j)+T2(j,i)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2s_2(1,2)+t2_2(2,1)),"T2s(i,j)+T2(j,i)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2s_2(2,0)+t2_2(0,2)),"T2s(i,j)+T2(j,i)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2s_2(2,1)+t2_2(1,2)),"T2s(i,j)+T2(j,i)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2s_2(2,2)+t2_2(2,2)),"T2s(i,j)+T2(j,i)(2,2)");
+  t2_1(i,j)=t2_2(j,i)+t2s_2(i,j);
+  test_for_zero(t2_1(0,0)-(t2s_2(0,0)+t2_2(0,0)),"T2(j,i)+T2s(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2s_2(0,1)+t2_2(1,0)),"T2(j,i)+T2s(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2s_2(0,2)+t2_2(2,0)),"T2(j,i)+T2s(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2s_2(1,0)+t2_2(0,1)),"T2(j,i)+T2s(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2s_2(1,1)+t2_2(1,1)),"T2(j,i)+T2s(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2s_2(1,2)+t2_2(2,1)),"T2(j,i)+T2s(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2s_2(2,0)+t2_2(0,2)),"T2(j,i)+T2s(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2s_2(2,1)+t2_2(1,2)),"T2(j,i)+T2s(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2s_2(2,2)+t2_2(2,2)),"T2(j,i)+T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,48 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(i,j)-t2_2(i,j);
+  test_for_zero(t2_1(0,0)-(t2s_2(0,0)-t2_2(0,0)),"T2s(i,j)-T2(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2s_2(0,1)-t2_2(0,1)),"T2s(i,j)-T2(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2s_2(0,2)-t2_2(0,2)),"T2s(i,j)-T2(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2s_2(1,0)-t2_2(1,0)),"T2s(i,j)-T2(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2s_2(1,1)-t2_2(1,1)),"T2s(i,j)-T2(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2s_2(1,2)-t2_2(1,2)),"T2s(i,j)-T2(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2s_2(2,0)-t2_2(2,0)),"T2s(i,j)-T2(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2s_2(2,1)-t2_2(2,1)),"T2s(i,j)-T2(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2s_2(2,2)-t2_2(2,2)),"T2s(i,j)-T2(i,j)(2,2)");
+  t2_1(i,j)=t2_2(i,j)-t2s_2(i,j);
+  test_for_zero(t2_1(0,0)-(-t2s_2(0,0)+t2_2(0,0)),"T2(i,j)-T2s(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(-t2s_2(0,1)+t2_2(0,1)),"T2(i,j)-T2s(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(-t2s_2(0,2)+t2_2(0,2)),"T2(i,j)-T2s(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(-t2s_2(1,0)+t2_2(1,0)),"T2(i,j)-T2s(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(-t2s_2(1,1)+t2_2(1,1)),"T2(i,j)-T2s(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(-t2s_2(1,2)+t2_2(1,2)),"T2(i,j)-T2s(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(-t2s_2(2,0)+t2_2(2,0)),"T2(i,j)-T2s(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(-t2s_2(2,1)+t2_2(2,1)),"T2(i,j)-T2s(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(-t2s_2(2,2)+t2_2(2,2)),"T2(i,j)-T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,48 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(i,j)-t2_2(j,i);
+  test_for_zero(t2_1(0,0)-(t2s_2(0,0)-t2_2(0,0)),"T2s(i,j)-T2(j,i)(0,0)");
+  test_for_zero(t2_1(0,1)-(t2s_2(0,1)-t2_2(1,0)),"T2s(i,j)-T2(j,i)(0,1)");
+  test_for_zero(t2_1(0,2)-(t2s_2(0,2)-t2_2(2,0)),"T2s(i,j)-T2(j,i)(0,2)");
+  test_for_zero(t2_1(1,0)-(t2s_2(1,0)-t2_2(0,1)),"T2s(i,j)-T2(j,i)(1,0)");
+  test_for_zero(t2_1(1,1)-(t2s_2(1,1)-t2_2(1,1)),"T2s(i,j)-T2(j,i)(1,1)");
+  test_for_zero(t2_1(1,2)-(t2s_2(1,2)-t2_2(2,1)),"T2s(i,j)-T2(j,i)(1,2)");
+  test_for_zero(t2_1(2,0)-(t2s_2(2,0)-t2_2(0,2)),"T2s(i,j)-T2(j,i)(2,0)");
+  test_for_zero(t2_1(2,1)-(t2s_2(2,1)-t2_2(1,2)),"T2s(i,j)-T2(j,i)(2,1)");
+  test_for_zero(t2_1(2,2)-(t2s_2(2,2)-t2_2(2,2)),"T2s(i,j)-T2(j,i)(2,2)");
+  t2_1(i,j)=t2_2(j,i)-t2s_2(i,j);
+  test_for_zero(t2_1(0,0)-(-t2s_2(0,0)+t2_2(0,0)),"T2(j,i)-T2s(i,j)(0,0)");
+  test_for_zero(t2_1(0,1)-(-t2s_2(0,1)+t2_2(1,0)),"T2(j,i)-T2s(i,j)(0,1)");
+  test_for_zero(t2_1(0,2)-(-t2s_2(0,2)+t2_2(2,0)),"T2(j,i)-T2s(i,j)(0,2)");
+  test_for_zero(t2_1(1,0)-(-t2s_2(1,0)+t2_2(0,1)),"T2(j,i)-T2s(i,j)(1,0)");
+  test_for_zero(t2_1(1,1)-(-t2s_2(1,1)+t2_2(1,1)),"T2(j,i)-T2s(i,j)(1,1)");
+  test_for_zero(t2_1(1,2)-(-t2s_2(1,2)+t2_2(2,1)),"T2(j,i)-T2s(i,j)(1,2)");
+  test_for_zero(t2_1(2,0)-(-t2s_2(2,0)+t2_2(0,2)),"T2(j,i)-T2s(i,j)(2,0)");
+  test_for_zero(t2_1(2,1)-(-t2s_2(2,1)+t2_2(1,2)),"T2(j,i)-T2s(i,j)(2,1)");
+  test_for_zero(t2_1(2,2)-(-t2s_2(2,2)+t2_2(2,2)),"T2(j,i)-T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,60 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2s_1(i,j)=(t2s_2(i,j)&(t1_2(i)^(t1_2(j))));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)*t1_2(0)*t1_2(0)),"T2s(i,j)&T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)*t1_2(0)*t1_2(1)),"T2s(i,j)&T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)*t1_2(0)*t1_2(2)),"T2s(i,j)&T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)*t1_2(1)*t1_2(0)),"T2s(i,j)&T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)*t1_2(1)*t1_2(1)),"T2s(i,j)&T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)*t1_2(1)*t1_2(2)),"T2s(i,j)&T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)*t1_2(2)*t1_2(0)),"T2s(i,j)&T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)*t1_2(2)*t1_2(1)),"T2s(i,j)&T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)*t1_2(2)*t1_2(2)),"T2s(i,j)&T2s(i,j)(2,2)");
+
+  t2s_1(i,j)=(t2s_2(i,j)&(t1_2(j)^(t1_2(i))));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)*t1_2(0)*t1_2(0)),"T2s(i,j)&T2s(j,i)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)*t1_2(0)*t1_2(1)),"T2s(i,j)&T2s(j,i)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)*t1_2(0)*t1_2(2)),"T2s(i,j)&T2s(j,i)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)*t1_2(1)*t1_2(0)),"T2s(i,j)&T2s(j,i)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)*t1_2(1)*t1_2(1)),"T2s(i,j)&T2s(j,i)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)*t1_2(1)*t1_2(2)),"T2s(i,j)&T2s(j,i)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)*t1_2(2)*t1_2(0)),"T2s(i,j)&T2s(j,i)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)*t1_2(2)*t1_2(1)),"T2s(i,j)&T2s(j,i)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)*t1_2(2)*t1_2(2)),"T2s(i,j)&T2s(j,i)(2,2)");
+
+  t2s_1(i,j)=((t1_2(j)^(t1_2(i)))&t2s_2(i,j));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)*t1_2(0)*t1_2(0)),"T2s(j,i)&T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)*t1_2(0)*t1_2(1)),"T2s(j,i)&T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)*t1_2(0)*t1_2(2)),"T2s(j,i)&T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)*t1_2(1)*t1_2(0)),"T2s(j,i)&T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)*t1_2(1)*t1_2(1)),"T2s(j,i)&T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)*t1_2(1)*t1_2(2)),"T2s(j,i)&T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)*t1_2(2)*t1_2(0)),"T2s(j,i)&T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)*t1_2(2)*t1_2(1)),"T2s(j,i)&T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)*t1_2(2)*t1_2(2)),"T2s(j,i)&T2s(i,j)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,66 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(k,i)*t2_2(k,j);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(1,0)*t2_2(1,0)
+		       + t2s_2(2,0)*t2_2(2,0)),"T2s(k,i)*T2(k,j)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(0,1) + t2s_2(1,0)*t2_2(1,1)
+		       + t2s_2(2,0)*t2_2(2,1)),"T2s(k,i)*T2(k,j)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(0,2) + t2s_2(1,0)*t2_2(1,2)
+		       + t2s_2(2,0)*t2_2(2,2)),"T2s(k,i)*T2(k,j)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(0,1)*t2_2(0,0) + t2s_2(1,1)*t2_2(1,0)
+		       + t2s_2(2,1)*t2_2(2,0)),"T2s(k,i)*T2(k,j)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(0,1)*t2_2(0,1) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(2,1)*t2_2(2,1)),"T2s(k,i)*T2(k,j)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(0,1)*t2_2(0,2) + t2s_2(1,1)*t2_2(1,2)
+		       + t2s_2(2,1)*t2_2(2,2)),"T2s(k,i)*T2(k,j)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(0,2)*t2_2(0,0) + t2s_2(1,2)*t2_2(1,0)
+		       + t2s_2(2,2)*t2_2(2,0)),"T2s(k,i)*T2(k,j)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(0,2)*t2_2(0,1) + t2s_2(1,2)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(2,1)),"T2s(k,i)*T2(k,j)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(0,2)*t2_2(0,2) + t2s_2(1,2)*t2_2(1,2)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2s(k,i)*T2(k,j)(2,2)");
+  t2_1(i,j)=t2_2(k,j)*t2s_2(k,i);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(1,0)*t2_2(1,0)
+		       + t2s_2(2,0)*t2_2(2,0)),"T2(k,j)*T2s(k,i)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(0,1) + t2s_2(1,0)*t2_2(1,1)
+		       + t2s_2(2,0)*t2_2(2,1)),"T2(k,j)*T2s(k,i)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(0,2) + t2s_2(1,0)*t2_2(1,2)
+		       + t2s_2(2,0)*t2_2(2,2)),"T2(k,j)*T2s(k,i)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(0,1)*t2_2(0,0) + t2s_2(1,1)*t2_2(1,0)
+		       + t2s_2(2,1)*t2_2(2,0)),"T2(k,j)*T2s(k,i)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(0,1)*t2_2(0,1) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(2,1)*t2_2(2,1)),"T2(k,j)*T2s(k,i)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(0,1)*t2_2(0,2) + t2s_2(1,1)*t2_2(1,2)
+		       + t2s_2(2,1)*t2_2(2,2)),"T2(k,j)*T2s(k,i)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(0,2)*t2_2(0,0) + t2s_2(1,2)*t2_2(1,0)
+		       + t2s_2(2,2)*t2_2(2,0)),"T2(k,j)*T2s(k,i)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(0,2)*t2_2(0,1) + t2s_2(1,2)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(2,1)),"T2(k,j)*T2s(k,i)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(0,2)*t2_2(0,2) + t2s_2(1,2)*t2_2(1,2)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2(k,j)*T2s(k,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2s_1(i,j)=(t2s_2(i,j)%(t1_2(i)^(t1_2(j))));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)/t1_2(0)/t1_2(0)),"T2s(j,i)%T2s(i,j)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)/t1_2(0)/t1_2(1)),"T2s(j,i)%T2s(i,j)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)/t1_2(0)/t1_2(2)),"T2s(j,i)%T2s(i,j)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)/t1_2(1)/t1_2(0)),"T2s(j,i)%T2s(i,j)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)/t1_2(1)/t1_2(1)),"T2s(j,i)%T2s(i,j)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)/t1_2(1)/t1_2(2)),"T2s(j,i)%T2s(i,j)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)/t1_2(2)/t1_2(0)),"T2s(j,i)%T2s(i,j)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)/t1_2(2)/t1_2(1)),"T2s(j,i)%T2s(i,j)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)/t1_2(2)/t1_2(2)),"T2s(j,i)%T2s(i,j)(2,2)");
+
+  t2s_1(i,j)=(t2s_2(i,j)%(t1_2(j)^(t1_2(i))));
+  test_for_zero(t2s_1(0,0)-(t2s_2(0,0)/t1_2(0)/t1_2(0)),"T2s(j,i)%T2s(j,i)(0,0)");
+  test_for_zero(t2s_1(0,1)-(t2s_2(0,1)/t1_2(0)/t1_2(1)),"T2s(j,i)%T2s(j,i)(0,1)");
+  test_for_zero(t2s_1(0,2)-(t2s_2(0,2)/t1_2(0)/t1_2(2)),"T2s(j,i)%T2s(j,i)(0,2)");
+  test_for_zero(t2s_1(1,0)-(t2s_2(1,0)/t1_2(1)/t1_2(0)),"T2s(j,i)%T2s(j,i)(1,0)");
+  test_for_zero(t2s_1(1,1)-(t2s_2(1,1)/t1_2(1)/t1_2(1)),"T2s(j,i)%T2s(j,i)(1,1)");
+  test_for_zero(t2s_1(1,2)-(t2s_2(1,2)/t1_2(1)/t1_2(2)),"T2s(j,i)%T2s(j,i)(1,2)");
+  test_for_zero(t2s_1(2,0)-(t2s_2(2,0)/t1_2(2)/t1_2(0)),"T2s(j,i)%T2s(j,i)(2,0)");
+  test_for_zero(t2s_1(2,1)-(t2s_2(2,1)/t1_2(2)/t1_2(1)),"T2s(j,i)%T2s(j,i)(2,1)");
+  test_for_zero(t2s_1(2,2)-(t2s_2(2,2)/t1_2(2)/t1_2(2)),"T2s(j,i)%T2s(j,i)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,68 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  test_for_zero(t2s_2(i,j)*t2_2(i,j)
+    - (t2s_2(0,0)*t2_2(0,0)
+       + t2s_2(0,1)*t2_2(0,1)
+       + t2s_2(0,2)*t2_2(0,2)
+       + t2s_2(1,0)*t2_2(1,0)
+       + t2s_2(1,1)*t2_2(1,1)
+       + t2s_2(1,2)*t2_2(1,2)
+       + t2s_2(2,0)*t2_2(2,0)
+       + t2s_2(2,1)*t2_2(2,1)
+       + t2s_2(2,2)*t2_2(2,2)),"T2s(i,j)*T2(i,j)");
+  test_for_zero(t2_2(i,j)*t2s_2(i,j)
+    - (t2s_2(0,0)*t2_2(0,0)
+       + t2s_2(0,1)*t2_2(0,1)
+       + t2s_2(0,2)*t2_2(0,2)
+       + t2s_2(1,0)*t2_2(1,0)
+       + t2s_2(1,1)*t2_2(1,1)
+       + t2s_2(1,2)*t2_2(1,2)
+       + t2s_2(2,0)*t2_2(2,0)
+       + t2s_2(2,1)*t2_2(2,1)
+       + t2s_2(2,2)*t2_2(2,2)),"T2(i,j)*T2s(i,j)");
+  test_for_zero(t2s_2(i,j)*t2_2(j,i)
+    - (t2s_2(0,0)*t2_2(0,0)
+       + t2s_2(0,1)*t2_2(1,0)
+       + t2s_2(0,2)*t2_2(2,0)
+       + t2s_2(1,0)*t2_2(0,1)
+       + t2s_2(1,1)*t2_2(1,1)
+       + t2s_2(1,2)*t2_2(2,1)
+       + t2s_2(2,0)*t2_2(0,2)
+       + t2s_2(2,1)*t2_2(1,2)
+       + t2s_2(2,2)*t2_2(2,2)),"T2s(i,j)*T2(j,i)");
+  test_for_zero(t2_2(j,i)*t2s_2(i,j)
+    - (t2s_2(0,0)*t2_2(0,0)
+       + t2s_2(0,1)*t2_2(1,0)
+       + t2s_2(0,2)*t2_2(2,0)
+       + t2s_2(1,0)*t2_2(0,1)
+       + t2s_2(1,1)*t2_2(1,1)
+       + t2s_2(1,2)*t2_2(2,1)
+       + t2s_2(2,0)*t2_2(0,2)
+       + t2s_2(2,1)*t2_2(1,2)
+       + t2s_2(2,2)*t2_2(2,2)),"T2(j,i)*T2s(i,j)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,66 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(i,k)*t2_2(k,j);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(0,1)*t2_2(1,0)
+			     + t2s_2(0,2)*t2_2(2,0)),"T2s(i,k)*T2(k,j)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(0,1) + t2s_2(0,1)*t2_2(1,1)
+		       + t2s_2(0,2)*t2_2(2,1)),"T2s(i,k)*T2(k,j)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(0,2) + t2s_2(0,1)*t2_2(1,2)
+		       + t2s_2(0,2)*t2_2(2,2)),"T2s(i,k)*T2(k,j)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(1,0)*t2_2(0,0) + t2s_2(1,1)*t2_2(1,0)
+		       + t2s_2(1,2)*t2_2(2,0)),"T2s(i,k)*T2(k,j)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(1,0)*t2_2(0,1) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(1,2)*t2_2(2,1)),"T2s(i,k)*T2(k,j)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(1,0)*t2_2(0,2) + t2s_2(1,1)*t2_2(1,2)
+		       + t2s_2(1,2)*t2_2(2,2)),"T2s(i,k)*T2(k,j)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(2,0)*t2_2(0,0) + t2s_2(2,1)*t2_2(1,0)
+		       + t2s_2(2,2)*t2_2(2,0)),"T2s(i,k)*T2(k,j)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(2,0)*t2_2(0,1) + t2s_2(2,1)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(2,1)),"T2s(i,k)*T2(k,j)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(2,0)*t2_2(0,2) + t2s_2(2,1)*t2_2(1,2)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2s(i,k)*T2(k,j)(2,2)");
+  t2_1(i,j)=t2_2(k,j)*t2s_2(i,k);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(0,1)*t2_2(1,0)
+		       + t2s_2(0,2)*t2_2(2,0)),"T2(k,j)*T2s(i,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(0,1) + t2s_2(0,1)*t2_2(1,1)
+		       + t2s_2(0,2)*t2_2(2,1)),"T2(k,j)*T2s(i,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(0,2) + t2s_2(0,1)*t2_2(1,2)
+		       + t2s_2(0,2)*t2_2(2,2)),"T2(k,j)*T2s(i,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(1,0)*t2_2(0,0) + t2s_2(1,1)*t2_2(1,0)
+		       + t2s_2(1,2)*t2_2(2,0)),"T2(k,j)*T2s(i,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(1,0)*t2_2(0,1) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(1,2)*t2_2(2,1)),"T2(k,j)*T2s(i,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(1,0)*t2_2(0,2) + t2s_2(1,1)*t2_2(1,2)
+		       + t2s_2(1,2)*t2_2(2,2)),"T2(k,j)*T2s(i,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(2,0)*t2_2(0,0) + t2s_2(2,1)*t2_2(1,0)
+		       + t2s_2(2,2)*t2_2(2,0)),"T2(k,j)*T2s(i,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(2,0)*t2_2(0,1) + t2s_2(2,1)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(2,1)),"T2(k,j)*T2s(i,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(2,0)*t2_2(0,2) + t2s_2(2,1)*t2_2(1,2)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2(k,j)*T2s(i,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T2s/test_T2sXXXVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T2s/test_T2sXXXVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,66 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T2sXXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor2_symmetric tests */
+
+  t2_1(i,j)=t2s_2(i,k)*t2_2(j,k);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(0,1)*t2_2(0,1)
+		       + t2s_2(0,2)*t2_2(0,2)),"T2s(i,k)*T2(j,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(1,0) + t2s_2(0,1)*t2_2(1,1)
+		       + t2s_2(0,2)*t2_2(1,2)),"T2s(i,k)*T2(j,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(2,0) + t2s_2(0,1)*t2_2(2,1)
+		       + t2s_2(0,2)*t2_2(2,2)),"T2s(i,k)*T2(j,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(1,0)*t2_2(0,0) + t2s_2(1,1)*t2_2(0,1)
+		       + t2s_2(1,2)*t2_2(0,2)),"T2s(i,k)*T2(j,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(1,0)*t2_2(1,0) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(1,2)*t2_2(1,2)),"T2s(i,k)*T2(j,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(1,0)*t2_2(2,0) + t2s_2(1,1)*t2_2(2,1)
+		       + t2s_2(1,2)*t2_2(2,2)),"T2s(i,k)*T2(j,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(2,0)*t2_2(0,0) + t2s_2(2,1)*t2_2(0,1)
+		       + t2s_2(2,2)*t2_2(0,2)),"T2s(i,k)*T2(j,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(2,0)*t2_2(1,0) + t2s_2(2,1)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(1,2)),"T2s(i,k)*T2(j,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(2,0)*t2_2(2,0) + t2s_2(2,1)*t2_2(2,1)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2s(i,k)*T2(j,k)(2,2)");
+  t2_1(i,j)=t2_2(j,k)*t2s_2(i,k);
+  test_for_zero(t2_1(0,0) - (t2s_2(0,0)*t2_2(0,0) + t2s_2(0,1)*t2_2(0,1)
+		       + t2s_2(0,2)*t2_2(0,2)),"T2(j,k)*T2s(i,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2s_2(0,0)*t2_2(1,0) + t2s_2(0,1)*t2_2(1,1)
+		       + t2s_2(0,2)*t2_2(1,2)),"T2(j,k)*T2s(i,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2s_2(0,0)*t2_2(2,0) + t2s_2(0,1)*t2_2(2,1)
+		       + t2s_2(0,2)*t2_2(2,2)),"T2(j,k)*T2s(i,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2s_2(1,0)*t2_2(0,0) + t2s_2(1,1)*t2_2(0,1)
+		       + t2s_2(1,2)*t2_2(0,2)),"T2(j,k)*T2s(i,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2s_2(1,0)*t2_2(1,0) + t2s_2(1,1)*t2_2(1,1)
+		       + t2s_2(1,2)*t2_2(1,2)),"T2(j,k)*T2s(i,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2s_2(1,0)*t2_2(2,0) + t2s_2(1,1)*t2_2(2,1)
+		       + t2s_2(1,2)*t2_2(2,2)),"T2(j,k)*T2s(i,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2s_2(2,0)*t2_2(0,0) + t2s_2(2,1)*t2_2(0,1)
+		       + t2s_2(2,2)*t2_2(0,2)),"T2(j,k)*T2s(i,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2s_2(2,0)*t2_2(1,0) + t2s_2(2,1)*t2_2(1,1)
+		       + t2s_2(2,2)*t2_2(1,2)),"T2(j,k)*T2s(i,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2s_2(2,0)*t2_2(2,0) + t2s_2(2,1)*t2_2(2,1)
+		       + t2s_2(2,2)*t2_2(2,2)),"T2(j,k)*T2s(i,k)(2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3/test_T3.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3/test_T3.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,1064 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3 tests */
+
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,0,0) - t2_2(0,0)*t1_2(0)*10,
+		"T3*T(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,0,1) - t2_2(0,0)*t1_2(1)*10,
+		"T3*T(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,0,2) - t2_2(0,0)*t1_2(2)*10,
+		"T3*T(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,1,0) - t2_2(0,1)*t1_2(0)*10,
+		"T3*T(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,1,1) - t2_2(0,1)*t1_2(1)*10,
+		"T3*T(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,1,2) - t2_2(0,1)*t1_2(2)*10,
+		"T3*T(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,2,0) - t2_2(0,2)*t1_2(0)*10,
+		"T3*T(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,2,1) - t2_2(0,2)*t1_2(1)*10,
+		"T3*T(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(0,2,2) - t2_2(0,2)*t1_2(2)*10,
+		"T3*T(0,2,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,0,0) - t2_2(1,0)*t1_2(0)*10,
+		"T3*T(1,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,0,1) - t2_2(1,0)*t1_2(1)*10,
+		"T3*T(1,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,0,2) - t2_2(1,0)*t1_2(2)*10,
+		"T3*T(1,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,1,0) - t2_2(1,1)*t1_2(0)*10,
+		"T3*T(1,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,1,1) - t2_2(1,1)*t1_2(1)*10,
+		"T3*T(1,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,1,2) - t2_2(1,1)*t1_2(2)*10,
+		"T3*T(1,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,2,0) - t2_2(1,2)*t1_2(0)*10,
+		"T3*T(1,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,2,1) - t2_2(1,2)*t1_2(1)*10,
+		"T3*T(1,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(1,2,2) - t2_2(1,2)*t1_2(2)*10,
+		"T3*T(1,2,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,0,0) - t2_2(2,0)*t1_2(0)*10,
+		"T3*T(2,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,0,1) - t2_2(2,0)*t1_2(1)*10,
+		"T3*T(2,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,0,2) - t2_2(2,0)*t1_2(2)*10,
+		"T3*T(2,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,1,0) - t2_2(2,1)*t1_2(0)*10,
+		"T3*T(2,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,1,1) - t2_2(2,1)*t1_2(1)*10,
+		"T3*T(2,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,1,2) - t2_2(2,1)*t1_2(2)*10,
+		"T3*T(2,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,2,0) - t2_2(2,2)*t1_2(0)*10,
+		"T3*T(2,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,2,1) - t2_2(2,2)*t1_2(1)*10,
+		"T3*T(2,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*10)(2,2,2) - t2_2(2,2)*t1_2(2)*10,
+		"T3*T(2,2,2)");
+  
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,0,0) - t2_2(0,0)*t1_2(0)*10,
+		"T*T3(0,0,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,0,1) - t2_2(0,0)*t1_2(1)*10,
+		"T*T3(0,0,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,0,2) - t2_2(0,0)*t1_2(2)*10,
+		"T*T3(0,0,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,1,0) - t2_2(0,1)*t1_2(0)*10,
+		"T*T3(0,1,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,1,1) - t2_2(0,1)*t1_2(1)*10,
+		"T*T3(0,1,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,1,2) - t2_2(0,1)*t1_2(2)*10,
+		"T*T3(0,1,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,2,0) - t2_2(0,2)*t1_2(0)*10,
+		"T*T3(0,2,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,2,1) - t2_2(0,2)*t1_2(1)*10,
+		"T*T3(0,2,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(0,2,2) - t2_2(0,2)*t1_2(2)*10,
+		"T*T3(0,2,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,0,0) - t2_2(1,0)*t1_2(0)*10,
+		"T*T3(1,0,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,0,1) - t2_2(1,0)*t1_2(1)*10,
+		"T*T3(1,0,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,0,2) - t2_2(1,0)*t1_2(2)*10,
+		"T*T3(1,0,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,1,0) - t2_2(1,1)*t1_2(0)*10,
+		"T*T3(1,1,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,1,1) - t2_2(1,1)*t1_2(1)*10,
+		"T*T3(1,1,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,1,2) - t2_2(1,1)*t1_2(2)*10,
+		"T*T3(1,1,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,2,0) - t2_2(1,2)*t1_2(0)*10,
+		"T*T3(1,2,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,2,1) - t2_2(1,2)*t1_2(1)*10,
+		"T*T3(1,2,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(1,2,2) - t2_2(1,2)*t1_2(2)*10,
+		"T*T3(1,2,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,0,0) - t2_2(2,0)*t1_2(0)*10,
+		"T*T3(2,0,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,0,1) - t2_2(2,0)*t1_2(1)*10,
+		"T*T3(2,0,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,0,2) - t2_2(2,0)*t1_2(2)*10,
+		"T*T3(2,0,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,1,0) - t2_2(2,1)*t1_2(0)*10,
+		"T*T3(2,1,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,1,1) - t2_2(2,1)*t1_2(1)*10,
+		"T*T3(2,1,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,1,2) - t2_2(2,1)*t1_2(2)*10,
+		"T*T3(2,1,2)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,2,0) - t2_2(2,2)*t1_2(0)*10,
+		"T*T3(2,2,0)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,2,1) - t2_2(2,2)*t1_2(1)*10,
+		"T*T3(2,2,1)");
+  test_for_zero((10*(t2_2(i,j)*t1_2(k)))(2,2,2) - t2_2(2,2)*t1_2(2)*10,
+		"T*T3(2,2,2)");
+
+  
+  t2_1(i,k)=(t2_2(i,j)*t1_2(k))*t1_1(j);
+  
+  test_for_zero(t2_1(0,0) - (t2_2(0,0)*t1_2(0)*t1_1(0)
+			     + t2_2(0,1)*t1_2(0)*t1_1(1)
+			     + t2_2(0,2)*t1_2(0)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2_2(0,0)*t1_2(1)*t1_1(0)
+			     + t2_2(0,1)*t1_2(1)*t1_1(1)
+			     + t2_2(0,2)*t1_2(1)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2_2(0,0)*t1_2(2)*t1_1(0)
+			     + t2_2(0,1)*t1_2(2)*t1_1(1)
+			     + t2_2(0,2)*t1_2(2)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2_2(1,0)*t1_2(0)*t1_1(0)
+			     + t2_2(1,1)*t1_2(0)*t1_1(1)
+			     + t2_2(1,2)*t1_2(0)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2_2(1,0)*t1_2(1)*t1_1(0)
+			     + t2_2(1,1)*t1_2(1)*t1_1(1)
+			     + t2_2(1,2)*t1_2(1)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2_2(1,0)*t1_2(2)*t1_1(0)
+			     + t2_2(1,1)*t1_2(2)*t1_1(1)
+			     + t2_2(1,2)*t1_2(2)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2_2(2,0)*t1_2(0)*t1_1(0)
+			     + t2_2(2,1)*t1_2(0)*t1_1(1)
+			     + t2_2(2,2)*t1_2(0)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2_2(2,0)*t1_2(1)*t1_1(0)
+			     + t2_2(2,1)*t1_2(1)*t1_1(1)
+			     + t2_2(2,2)*t1_2(1)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2_2(2,0)*t1_2(2)*t1_1(0)
+			     + t2_2(2,1)*t1_2(2)*t1_1(1)
+			     + t2_2(2,2)*t1_2(2)*t1_1(2)),
+		"T3(i,j,k)*T1(j)(2,2)");
+  
+  t2_1(i,k)=t1_2(j)*(t2_2(i,j)*t1_1(k));
+  
+  test_for_zero(t2_1(0,0) - (t2_2(0,0)*t1_1(0)*t1_2(0)
+			     + t2_2(0,1)*t1_1(0)*t1_2(1)
+			     + t2_2(0,2)*t1_1(0)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t2_2(0,0)*t1_1(1)*t1_2(0)
+			     + t2_2(0,1)*t1_1(1)*t1_2(1)
+			     + t2_2(0,2)*t1_1(1)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t2_2(0,0)*t1_1(2)*t1_2(0)
+			     + t2_2(0,1)*t1_1(2)*t1_2(1)
+			     + t2_2(0,2)*t1_1(2)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t2_2(1,0)*t1_1(0)*t1_2(0)
+			     + t2_2(1,1)*t1_1(0)*t1_2(1)
+			     + t2_2(1,2)*t1_1(0)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t2_2(1,0)*t1_1(1)*t1_2(0)
+			     + t2_2(1,1)*t1_1(1)*t1_2(1)
+			     + t2_2(1,2)*t1_1(1)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t2_2(1,0)*t1_1(2)*t1_2(0)
+			     + t2_2(1,1)*t1_1(2)*t1_2(1)
+			     + t2_2(1,2)*t1_1(2)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t2_2(2,0)*t1_1(0)*t1_2(0)
+			     + t2_2(2,1)*t1_1(0)*t1_2(1)
+			     + t2_2(2,2)*t1_1(0)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t2_2(2,0)*t1_1(1)*t1_2(0)
+			     + t2_2(2,1)*t1_1(1)*t1_2(1)
+			     + t2_2(2,2)*t1_1(1)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t2_2(2,0)*t1_1(2)*t1_2(0)
+			     + t2_2(2,1)*t1_1(2)*t1_2(1)
+			     + t2_2(2,2)*t1_1(2)*t1_2(2)),
+		"T1(j)*T3(i,j,k)(2,2)");
+
+  t1_1(i)=(t2_2(i,j)*t1_2(k))*t2s_2(j,k);
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2s_2(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2s_2(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2s_2(0,2)
+			   + t2_2(0,1)*t1_2(0)*t2s_2(1,0)
+			   + t2_2(0,1)*t1_2(1)*t2s_2(1,1)
+			   + t2_2(0,1)*t1_2(2)*t2s_2(1,2)
+			   + t2_2(0,2)*t1_2(0)*t2s_2(2,0)
+			   + t2_2(0,2)*t1_2(1)*t2s_2(2,1)
+			   + t2_2(0,2)*t1_2(2)*t2s_2(2,2)),
+		"T3(i,j,k)*T2s(j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(1,0)*t1_2(0)*t2s_2(0,0)
+			   + t2_2(1,0)*t1_2(1)*t2s_2(0,1)
+			   + t2_2(1,0)*t1_2(2)*t2s_2(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2s_2(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2s_2(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2s_2(1,2)
+			   + t2_2(1,2)*t1_2(0)*t2s_2(2,0)
+			   + t2_2(1,2)*t1_2(1)*t2s_2(2,1)
+			   + t2_2(1,2)*t1_2(2)*t2s_2(2,2)),
+		"T3(i,j,k)*T2s(j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(2,0)*t1_2(0)*t2s_2(0,0)
+			   + t2_2(2,0)*t1_2(1)*t2s_2(0,1)
+			   + t2_2(2,0)*t1_2(2)*t2s_2(0,2)
+			   + t2_2(2,1)*t1_2(0)*t2s_2(1,0)
+			   + t2_2(2,1)*t1_2(1)*t2s_2(1,1)
+			   + t2_2(2,1)*t1_2(2)*t2s_2(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2s_2(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2s_2(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2s_2(2,2)),
+		"T3(i,j,k)*T2s(j,k)(2)");
+
+  t1_1(i)=t2s_3(j,k)*(t2_2(i,j)*t1_2(k));
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2s_3(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2s_3(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2s_3(0,2)
+			   + t2_2(0,1)*t1_2(0)*t2s_3(1,0)
+			   + t2_2(0,1)*t1_2(1)*t2s_3(1,1)
+			   + t2_2(0,1)*t1_2(2)*t2s_3(1,2)
+			   + t2_2(0,2)*t1_2(0)*t2s_3(2,0)
+			   + t2_2(0,2)*t1_2(1)*t2s_3(2,1)
+			   + t2_2(0,2)*t1_2(2)*t2s_3(2,2)),
+		"T2s(j,k)*T3(i,j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(1,0)*t1_2(0)*t2s_3(0,0)
+			   + t2_2(1,0)*t1_2(1)*t2s_3(0,1)
+			   + t2_2(1,0)*t1_2(2)*t2s_3(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2s_3(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2s_3(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2s_3(1,2)
+			   + t2_2(1,2)*t1_2(0)*t2s_3(2,0)
+			   + t2_2(1,2)*t1_2(1)*t2s_3(2,1)
+			   + t2_2(1,2)*t1_2(2)*t2s_3(2,2)),
+		"T2s(j,k)*T3(i,j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(2,0)*t1_2(0)*t2s_3(0,0)
+			   + t2_2(2,0)*t1_2(1)*t2s_3(0,1)
+			   + t2_2(2,0)*t1_2(2)*t2s_3(0,2)
+			   + t2_2(2,1)*t1_2(0)*t2s_3(1,0)
+			   + t2_2(2,1)*t1_2(1)*t2s_3(1,1)
+			   + t2_2(2,1)*t1_2(2)*t2s_3(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2s_3(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2s_3(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2s_3(2,2)),
+		"T2s(j,k)*T3(i,j,k)(2)");
+
+
+  t1_1(i)=(t2_2(j,i)*t1_2(k))*t2s_2(j,k);
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2s_2(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2s_2(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2s_2(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2s_2(1,0)
+			   + t2_2(1,0)*t1_2(1)*t2s_2(1,1)
+			   + t2_2(1,0)*t1_2(2)*t2s_2(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2s_2(2,0)
+			   + t2_2(2,0)*t1_2(1)*t2s_2(2,1)
+			   + t2_2(2,0)*t1_2(2)*t2s_2(2,2)),
+		"T3(j,i,k)*T2s(j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,1)*t1_2(0)*t2s_2(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2s_2(0,1)
+			   + t2_2(0,1)*t1_2(2)*t2s_2(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2s_2(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2s_2(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2s_2(1,2)
+			   + t2_2(2,1)*t1_2(0)*t2s_2(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2s_2(2,1)
+			   + t2_2(2,1)*t1_2(2)*t2s_2(2,2)),
+		"T3(j,i,k)*T2s(j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,2)*t1_2(0)*t2s_2(0,0)
+			   + t2_2(0,2)*t1_2(1)*t2s_2(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2s_2(0,2)
+			   + t2_2(1,2)*t1_2(0)*t2s_2(1,0)
+			   + t2_2(1,2)*t1_2(1)*t2s_2(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2s_2(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2s_2(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2s_2(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2s_2(2,2)),
+		"T3(j,i,k)*T2s(j,k)(2)");
+
+  t1_1(i)=t2s_3(j,k)*(t2_2(j,i)*t1_2(k));
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2s_3(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2s_3(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2s_3(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2s_3(1,0)
+			   + t2_2(1,0)*t1_2(1)*t2s_3(1,1)
+			   + t2_2(1,0)*t1_2(2)*t2s_3(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2s_3(2,0)
+			   + t2_2(2,0)*t1_2(1)*t2s_3(2,1)
+			   + t2_2(2,0)*t1_2(2)*t2s_3(2,2)),
+		"T2s(j,k)*T3(j,i,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,1)*t1_2(0)*t2s_3(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2s_3(0,1)
+			   + t2_2(0,1)*t1_2(2)*t2s_3(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2s_3(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2s_3(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2s_3(1,2)
+			   + t2_2(2,1)*t1_2(0)*t2s_3(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2s_3(2,1)
+			   + t2_2(2,1)*t1_2(2)*t2s_3(2,2)),
+		"T2s(j,k)*T3(j,i,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,2)*t1_2(0)*t2s_3(0,0)
+			   + t2_2(0,2)*t1_2(1)*t2s_3(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2s_3(0,2)
+			   + t2_2(1,2)*t1_2(0)*t2s_3(1,0)
+			   + t2_2(1,2)*t1_2(1)*t2s_3(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2s_3(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2s_3(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2s_3(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2s_3(2,2)),
+		"T2s(j,k)*T3(j,i,k)(2)");
+
+
+  t1_1(i)=(t2_2(j,k)*t1_2(i))*t2s_2(j,k);
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2s_2(0,0)
+			   + t2_2(0,1)*t1_2(0)*t2s_2(0,1)
+			   + t2_2(0,2)*t1_2(0)*t2s_2(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2s_2(1,0)
+			   + t2_2(1,1)*t1_2(0)*t2s_2(1,1)
+			   + t2_2(1,2)*t1_2(0)*t2s_2(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2s_2(2,0)
+			   + t2_2(2,1)*t1_2(0)*t2s_2(2,1)
+			   + t2_2(2,2)*t1_2(0)*t2s_2(2,2)),
+		"T3(j,k,i)*T2s(j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,0)*t1_2(1)*t2s_2(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2s_2(0,1)
+			   + t2_2(0,2)*t1_2(1)*t2s_2(0,2)
+			   + t2_2(1,0)*t1_2(1)*t2s_2(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2s_2(1,1)
+			   + t2_2(1,2)*t1_2(1)*t2s_2(1,2)
+			   + t2_2(2,0)*t1_2(1)*t2s_2(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2s_2(2,1)
+			   + t2_2(2,2)*t1_2(1)*t2s_2(2,2)),
+		"T3(j,k,i)*T2s(j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,0)*t1_2(2)*t2s_2(0,0)
+			   + t2_2(0,1)*t1_2(2)*t2s_2(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2s_2(0,2)
+			   + t2_2(1,0)*t1_2(2)*t2s_2(1,0)
+			   + t2_2(1,1)*t1_2(2)*t2s_2(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2s_2(1,2)
+			   + t2_2(2,0)*t1_2(2)*t2s_2(2,0)
+			   + t2_2(2,1)*t1_2(2)*t2s_2(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2s_2(2,2)),
+		"T3(j,k,i)*T2s(j,k)(2)");
+
+  t1_1(i)=t2s_3(j,k)*(t2_2(j,k)*t1_2(i));
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2s_3(0,0)
+			   + t2_2(0,1)*t1_2(0)*t2s_3(0,1)
+			   + t2_2(0,2)*t1_2(0)*t2s_3(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2s_3(1,0)
+			   + t2_2(1,1)*t1_2(0)*t2s_3(1,1)
+			   + t2_2(1,2)*t1_2(0)*t2s_3(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2s_3(2,0)
+			   + t2_2(2,1)*t1_2(0)*t2s_3(2,1)
+			   + t2_2(2,2)*t1_2(0)*t2s_3(2,2)),
+		"T2s(j,k)*T3(j,k,i)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,0)*t1_2(1)*t2s_3(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2s_3(0,1)
+			   + t2_2(0,2)*t1_2(1)*t2s_3(0,2)
+			   + t2_2(1,0)*t1_2(1)*t2s_3(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2s_3(1,1)
+			   + t2_2(1,2)*t1_2(1)*t2s_3(1,2)
+			   + t2_2(2,0)*t1_2(1)*t2s_3(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2s_3(2,1)
+			   + t2_2(2,2)*t1_2(1)*t2s_3(2,2)),
+		"T2s(j,k)*T3(j,k,i)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,0)*t1_2(2)*t2s_3(0,0)
+			   + t2_2(0,1)*t1_2(2)*t2s_3(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2s_3(0,2)
+			   + t2_2(1,0)*t1_2(2)*t2s_3(1,0)
+			   + t2_2(1,1)*t1_2(2)*t2s_3(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2s_3(1,2)
+			   + t2_2(2,0)*t1_2(2)*t2s_3(2,0)
+			   + t2_2(2,1)*t1_2(2)*t2s_3(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2s_3(2,2)),
+		"T2s(j,k)*T3(j,k,i)(2)");
+
+
+
+
+  t1_1(i)=(t2_2(i,j)*t1_2(k))*t2_2(j,k);
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2_2(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2_2(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2_2(0,2)
+			   + t2_2(0,1)*t1_2(0)*t2_2(1,0)
+			   + t2_2(0,1)*t1_2(1)*t2_2(1,1)
+			   + t2_2(0,1)*t1_2(2)*t2_2(1,2)
+			   + t2_2(0,2)*t1_2(0)*t2_2(2,0)
+			   + t2_2(0,2)*t1_2(1)*t2_2(2,1)
+			   + t2_2(0,2)*t1_2(2)*t2_2(2,2)),
+		"T3(i,j,k)*T2(j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(1,0)*t1_2(0)*t2_2(0,0)
+			   + t2_2(1,0)*t1_2(1)*t2_2(0,1)
+			   + t2_2(1,0)*t1_2(2)*t2_2(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2_2(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2_2(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2_2(1,2)
+			   + t2_2(1,2)*t1_2(0)*t2_2(2,0)
+			   + t2_2(1,2)*t1_2(1)*t2_2(2,1)
+			   + t2_2(1,2)*t1_2(2)*t2_2(2,2)),
+		"T3(i,j,k)*T2(j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(2,0)*t1_2(0)*t2_2(0,0)
+			   + t2_2(2,0)*t1_2(1)*t2_2(0,1)
+			   + t2_2(2,0)*t1_2(2)*t2_2(0,2)
+			   + t2_2(2,1)*t1_2(0)*t2_2(1,0)
+			   + t2_2(2,1)*t1_2(1)*t2_2(1,1)
+			   + t2_2(2,1)*t1_2(2)*t2_2(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2_2(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2_2(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2_2(2,2)),
+		"T3(i,j,k)*T2(j,k)(2)");
+
+  t1_1(i)=t2_3(j,k)*(t2_2(i,j)*t1_2(k));
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2_3(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2_3(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2_3(0,2)
+			   + t2_2(0,1)*t1_2(0)*t2_3(1,0)
+			   + t2_2(0,1)*t1_2(1)*t2_3(1,1)
+			   + t2_2(0,1)*t1_2(2)*t2_3(1,2)
+			   + t2_2(0,2)*t1_2(0)*t2_3(2,0)
+			   + t2_2(0,2)*t1_2(1)*t2_3(2,1)
+			   + t2_2(0,2)*t1_2(2)*t2_3(2,2)),
+		"T2(j,k)*T3(i,j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(1,0)*t1_2(0)*t2_3(0,0)
+			   + t2_2(1,0)*t1_2(1)*t2_3(0,1)
+			   + t2_2(1,0)*t1_2(2)*t2_3(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2_3(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2_3(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2_3(1,2)
+			   + t2_2(1,2)*t1_2(0)*t2_3(2,0)
+			   + t2_2(1,2)*t1_2(1)*t2_3(2,1)
+			   + t2_2(1,2)*t1_2(2)*t2_3(2,2)),
+		"T2(j,k)*T3(i,j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(2,0)*t1_2(0)*t2_3(0,0)
+			   + t2_2(2,0)*t1_2(1)*t2_3(0,1)
+			   + t2_2(2,0)*t1_2(2)*t2_3(0,2)
+			   + t2_2(2,1)*t1_2(0)*t2_3(1,0)
+			   + t2_2(2,1)*t1_2(1)*t2_3(1,1)
+			   + t2_2(2,1)*t1_2(2)*t2_3(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2_3(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2_3(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2_3(2,2))
+		,"T2(j,k)*T3(i,j,k)(2)");
+
+
+  t1_1(i)=(t2_2(j,i)*t1_2(k))*t2_2(j,k);
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2_2(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2_2(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2_2(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2_2(1,0)
+			   + t2_2(1,0)*t1_2(1)*t2_2(1,1)
+			   + t2_2(1,0)*t1_2(2)*t2_2(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2_2(2,0)
+			   + t2_2(2,0)*t1_2(1)*t2_2(2,1)
+			   + t2_2(2,0)*t1_2(2)*t2_2(2,2)),
+		"T3(j,i,k)*T2(j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,1)*t1_2(0)*t2_2(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2_2(0,1)
+			   + t2_2(0,1)*t1_2(2)*t2_2(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2_2(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2_2(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2_2(1,2)
+			   + t2_2(2,1)*t1_2(0)*t2_2(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2_2(2,1)
+			   + t2_2(2,1)*t1_2(2)*t2_2(2,2)),
+		"T3(j,i,k)*T2(j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,2)*t1_2(0)*t2_2(0,0)
+			   + t2_2(0,2)*t1_2(1)*t2_2(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2_2(0,2)
+			   + t2_2(1,2)*t1_2(0)*t2_2(1,0)
+			   + t2_2(1,2)*t1_2(1)*t2_2(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2_2(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2_2(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2_2(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2_2(2,2)),
+		"T3(j,i,k)*T2(j,k)(2)");
+
+  t1_1(i)=t2_3(j,k)*(t2_2(j,i)*t1_2(k));
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2_3(0,0)
+			   + t2_2(0,0)*t1_2(1)*t2_3(0,1)
+			   + t2_2(0,0)*t1_2(2)*t2_3(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2_3(1,0)
+			   + t2_2(1,0)*t1_2(1)*t2_3(1,1)
+			   + t2_2(1,0)*t1_2(2)*t2_3(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2_3(2,0)
+			   + t2_2(2,0)*t1_2(1)*t2_3(2,1)
+			   + t2_2(2,0)*t1_2(2)*t2_3(2,2))
+		,"T2(j,k)*T3(j,i,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,1)*t1_2(0)*t2_3(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2_3(0,1)
+			   + t2_2(0,1)*t1_2(2)*t2_3(0,2)
+			   + t2_2(1,1)*t1_2(0)*t2_3(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2_3(1,1)
+			   + t2_2(1,1)*t1_2(2)*t2_3(1,2)
+			   + t2_2(2,1)*t1_2(0)*t2_3(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2_3(2,1)
+			   + t2_2(2,1)*t1_2(2)*t2_3(2,2))
+		,"T2(j,k)*T3(j,i,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,2)*t1_2(0)*t2_3(0,0)
+			   + t2_2(0,2)*t1_2(1)*t2_3(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2_3(0,2)
+			   + t2_2(1,2)*t1_2(0)*t2_3(1,0)
+			   + t2_2(1,2)*t1_2(1)*t2_3(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2_3(1,2)
+			   + t2_2(2,2)*t1_2(0)*t2_3(2,0)
+			   + t2_2(2,2)*t1_2(1)*t2_3(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2_3(2,2))
+		,"T2(j,k)*T3(j,i,k)(2)");
+
+
+  t1_1(i)=(t2_2(j,k)*t1_2(i))*t2_2(j,k);
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2_2(0,0)
+			   + t2_2(0,1)*t1_2(0)*t2_2(0,1)
+			   + t2_2(0,2)*t1_2(0)*t2_2(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2_2(1,0)
+			   + t2_2(1,1)*t1_2(0)*t2_2(1,1)
+			   + t2_2(1,2)*t1_2(0)*t2_2(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2_2(2,0)
+			   + t2_2(2,1)*t1_2(0)*t2_2(2,1)
+			   + t2_2(2,2)*t1_2(0)*t2_2(2,2))
+		,"T3(j,k,i)*T2(j,k)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,0)*t1_2(1)*t2_2(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2_2(0,1)
+			   + t2_2(0,2)*t1_2(1)*t2_2(0,2)
+			   + t2_2(1,0)*t1_2(1)*t2_2(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2_2(1,1)
+			   + t2_2(1,2)*t1_2(1)*t2_2(1,2)
+			   + t2_2(2,0)*t1_2(1)*t2_2(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2_2(2,1)
+			   + t2_2(2,2)*t1_2(1)*t2_2(2,2))
+		,"T3(j,k,i)*T2(j,k)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,0)*t1_2(2)*t2_2(0,0)
+			   + t2_2(0,1)*t1_2(2)*t2_2(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2_2(0,2)
+			   + t2_2(1,0)*t1_2(2)*t2_2(1,0)
+			   + t2_2(1,1)*t1_2(2)*t2_2(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2_2(1,2)
+			   + t2_2(2,0)*t1_2(2)*t2_2(2,0)
+			   + t2_2(2,1)*t1_2(2)*t2_2(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2_2(2,2))
+		,"T3(j,k,i)*T2(j,k)(2)");
+
+  t1_1(i)=t2_3(j,k)*(t2_2(j,k)*t1_2(i));
+  test_for_zero(t1_1(0) - (t2_2(0,0)*t1_2(0)*t2_3(0,0)
+			   + t2_2(0,1)*t1_2(0)*t2_3(0,1)
+			   + t2_2(0,2)*t1_2(0)*t2_3(0,2)
+			   + t2_2(1,0)*t1_2(0)*t2_3(1,0)
+			   + t2_2(1,1)*t1_2(0)*t2_3(1,1)
+			   + t2_2(1,2)*t1_2(0)*t2_3(1,2)
+			   + t2_2(2,0)*t1_2(0)*t2_3(2,0)
+			   + t2_2(2,1)*t1_2(0)*t2_3(2,1)
+			   + t2_2(2,2)*t1_2(0)*t2_3(2,2))
+		,"T2(j,k)*T3(j,k,i)(0)");
+  test_for_zero(t1_1(1) - (t2_2(0,0)*t1_2(1)*t2_3(0,0)
+			   + t2_2(0,1)*t1_2(1)*t2_3(0,1)
+			   + t2_2(0,2)*t1_2(1)*t2_3(0,2)
+			   + t2_2(1,0)*t1_2(1)*t2_3(1,0)
+			   + t2_2(1,1)*t1_2(1)*t2_3(1,1)
+			   + t2_2(1,2)*t1_2(1)*t2_3(1,2)
+			   + t2_2(2,0)*t1_2(1)*t2_3(2,0)
+			   + t2_2(2,1)*t1_2(1)*t2_3(2,1)
+			   + t2_2(2,2)*t1_2(1)*t2_3(2,2))
+		,"T2(j,k)*T3(j,k,i)(1)");
+  test_for_zero(t1_1(2) - (t2_2(0,0)*t1_2(2)*t2_3(0,0)
+			   + t2_2(0,1)*t1_2(2)*t2_3(0,1)
+			   + t2_2(0,2)*t1_2(2)*t2_3(0,2)
+			   + t2_2(1,0)*t1_2(2)*t2_3(1,0)
+			   + t2_2(1,1)*t1_2(2)*t2_3(1,1)
+			   + t2_2(1,2)*t1_2(2)*t2_3(1,2)
+			   + t2_2(2,0)*t1_2(2)*t2_3(2,0)
+			   + t2_2(2,1)*t1_2(2)*t2_3(2,1)
+			   + t2_2(2,2)*t1_2(2)*t2_3(2,2))
+		,"T2(j,k)*T3(j,k,i)(2)");
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,0,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,0,0),
+		"T3(i,j,k)*T2(k,l)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,0,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,0,1),
+		"T3(i,j,k)*T2(k,l)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,0,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,0,2),
+		"T3(i,j,k)*T2(k,l)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,1,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,1,0),
+		"T3(i,j,k)*T2(k,l)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,1,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,1,1),
+		"T3(i,j,k)*T2(k,l)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,1,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,1,2),
+		"T3(i,j,k)*T2(k,l)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,2,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,2,0),
+		"T3(i,j,k)*T2(k,l)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,2,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,2,1),
+		"T3(i,j,k)*T2(k,l)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(0,2,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(0,2,2),
+		"T3(i,j,k)*T2(k,l)(0,2,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,0,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,0,0),
+		"T3(i,j,k)*T2(k,l)(1,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,0,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,0,1),
+		"T3(i,j,k)*T2(k,l)(1,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,0,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,0,2),
+		"T3(i,j,k)*T2(k,l)(1,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,1,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,1,0),
+		"T3(i,j,k)*T2(k,l)(1,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,1,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,1,1),
+		"T3(i,j,k)*T2(k,l)(1,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,1,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,1,2),
+		"T3(i,j,k)*T2(k,l)(1,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,2,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,2,0),
+		"T3(i,j,k)*T2(k,l)(1,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,2,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,2,1),
+		"T3(i,j,k)*T2(k,l)(1,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(1,2,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(1,2,2),
+		"T3(i,j,k)*T2(k,l)(1,2,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,0,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,0,0),
+		"T3(i,j,k)*T2(k,l)(2,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,0,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,0,1),
+		"T3(i,j,k)*T2(k,l)(2,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,0,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,0,2),
+		"T3(i,j,k)*T2(k,l)(2,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,1,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,1,0),
+		"T3(i,j,k)*T2(k,l)(2,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,1,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,1,1),
+		"T3(i,j,k)*T2(k,l)(2,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,1,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,1,2),
+		"T3(i,j,k)*T2(k,l)(2,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,2,0)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,2,0),
+		"T3(i,j,k)*T2(k,l)(2,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,2,1)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,2,1),
+		"T3(i,j,k)*T2(k,l)(2,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))*t2_3(k,l))(2,2,2)
+		- (t2_2(i,j)*(t1_2(k)*t2_3(k,l)))(2,2,2),
+		"T3(i,j,k)*T2(k,l)(2,2,2)");
+
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t2_3(i,j)*t1_1(k))
+		- (t2_2(0,0)*t1_2(0)*t2_3(0,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(0)*t2_3(1,0)*t1_1(0)
+		   + t2_2(2,0)*t1_2(0)*t2_3(2,0)*t1_1(0)
+		   + t2_2(0,1)*t1_2(0)*t2_3(0,1)*t1_1(0)
+		   + t2_2(1,1)*t1_2(0)*t2_3(1,1)*t1_1(0)
+		   + t2_2(2,1)*t1_2(0)*t2_3(2,1)*t1_1(0)
+		   + t2_2(0,2)*t1_2(0)*t2_3(0,2)*t1_1(0)
+		   + t2_2(1,2)*t1_2(0)*t2_3(1,2)*t1_1(0)
+		   + t2_2(2,2)*t1_2(0)*t2_3(2,2)*t1_1(0)
+		   + t2_2(0,0)*t1_2(1)*t2_3(0,0)*t1_1(1)
+		   + t2_2(1,0)*t1_2(1)*t2_3(1,0)*t1_1(1)
+		   + t2_2(2,0)*t1_2(1)*t2_3(2,0)*t1_1(1)
+		   + t2_2(0,1)*t1_2(1)*t2_3(0,1)*t1_1(1)
+		   + t2_2(1,1)*t1_2(1)*t2_3(1,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(1)*t2_3(2,1)*t1_1(1)
+		   + t2_2(0,2)*t1_2(1)*t2_3(0,2)*t1_1(1)
+		   + t2_2(1,2)*t1_2(1)*t2_3(1,2)*t1_1(1)
+		   + t2_2(2,2)*t1_2(1)*t2_3(2,2)*t1_1(1)
+		   + t2_2(0,0)*t1_2(2)*t2_3(0,0)*t1_1(2)
+		   + t2_2(1,0)*t1_2(2)*t2_3(1,0)*t1_1(2)
+		   + t2_2(2,0)*t1_2(2)*t2_3(2,0)*t1_1(2)
+		   + t2_2(0,1)*t1_2(2)*t2_3(0,1)*t1_1(2)
+		   + t2_2(1,1)*t1_2(2)*t2_3(1,1)*t1_1(2)
+		   + t2_2(2,1)*t1_2(2)*t2_3(2,1)*t1_1(2)
+		   + t2_2(0,2)*t1_2(2)*t2_3(0,2)*t1_1(2)
+		   + t2_2(1,2)*t1_2(2)*t2_3(1,2)*t1_1(2)
+		   + t2_2(2,2)*t1_2(2)*t2_3(2,2)*t1_1(2)),
+		"T3(i,j,k)*T3(i,j,k)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t2_3(j,i)*t1_1(k))
+		- (t2_2(0,0)*t1_2(0)*t2_3(0,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(0)*t2_3(0,1)*t1_1(0)
+		   + t2_2(2,0)*t1_2(0)*t2_3(0,2)*t1_1(0)
+		   + t2_2(0,1)*t1_2(0)*t2_3(1,0)*t1_1(0)
+		   + t2_2(1,1)*t1_2(0)*t2_3(1,1)*t1_1(0)
+		   + t2_2(2,1)*t1_2(0)*t2_3(1,2)*t1_1(0)
+		   + t2_2(0,2)*t1_2(0)*t2_3(2,0)*t1_1(0)
+		   + t2_2(1,2)*t1_2(0)*t2_3(2,1)*t1_1(0)
+		   + t2_2(2,2)*t1_2(0)*t2_3(2,2)*t1_1(0)
+		   + t2_2(0,0)*t1_2(1)*t2_3(0,0)*t1_1(1)
+		   + t2_2(1,0)*t1_2(1)*t2_3(0,1)*t1_1(1)
+		   + t2_2(2,0)*t1_2(1)*t2_3(0,2)*t1_1(1)
+		   + t2_2(0,1)*t1_2(1)*t2_3(1,0)*t1_1(1)
+		   + t2_2(1,1)*t1_2(1)*t2_3(1,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(1)*t2_3(1,2)*t1_1(1)
+		   + t2_2(0,2)*t1_2(1)*t2_3(2,0)*t1_1(1)
+		   + t2_2(1,2)*t1_2(1)*t2_3(2,1)*t1_1(1)
+		   + t2_2(2,2)*t1_2(1)*t2_3(2,2)*t1_1(1)
+		   + t2_2(0,0)*t1_2(2)*t2_3(0,0)*t1_1(2)
+		   + t2_2(1,0)*t1_2(2)*t2_3(0,1)*t1_1(2)
+		   + t2_2(2,0)*t1_2(2)*t2_3(0,2)*t1_1(2)
+		   + t2_2(0,1)*t1_2(2)*t2_3(1,0)*t1_1(2)
+		   + t2_2(1,1)*t1_2(2)*t2_3(1,1)*t1_1(2)
+		   + t2_2(2,1)*t1_2(2)*t2_3(1,2)*t1_1(2)
+		   + t2_2(0,2)*t1_2(2)*t2_3(2,0)*t1_1(2)
+		   + t2_2(1,2)*t1_2(2)*t2_3(2,1)*t1_1(2)
+		   + t2_2(2,2)*t1_2(2)*t2_3(2,2)*t1_1(2)),
+		"T3(i,j,k)*T3(j,i,k)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t2_3(i,k)*t1_1(j))
+		- (t2_2(0,0)*t1_2(0)*t2_3(0,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(0)*t2_3(1,0)*t1_1(0)
+		   + t2_2(2,0)*t1_2(0)*t2_3(2,0)*t1_1(0)
+		   + t2_2(0,1)*t1_2(0)*t2_3(0,0)*t1_1(1)
+		   + t2_2(1,1)*t1_2(0)*t2_3(1,0)*t1_1(1)
+		   + t2_2(2,1)*t1_2(0)*t2_3(2,0)*t1_1(1)
+		   + t2_2(0,2)*t1_2(0)*t2_3(0,0)*t1_1(2)
+		   + t2_2(1,2)*t1_2(0)*t2_3(1,0)*t1_1(2)
+		   + t2_2(2,2)*t1_2(0)*t2_3(2,0)*t1_1(2)
+		   + t2_2(0,0)*t1_2(1)*t2_3(0,1)*t1_1(0)
+		   + t2_2(1,0)*t1_2(1)*t2_3(1,1)*t1_1(0)
+		   + t2_2(2,0)*t1_2(1)*t2_3(2,1)*t1_1(0)
+		   + t2_2(0,1)*t1_2(1)*t2_3(0,1)*t1_1(1)
+		   + t2_2(1,1)*t1_2(1)*t2_3(1,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(1)*t2_3(2,1)*t1_1(1)
+		   + t2_2(0,2)*t1_2(1)*t2_3(0,1)*t1_1(2)
+		   + t2_2(1,2)*t1_2(1)*t2_3(1,1)*t1_1(2)
+		   + t2_2(2,2)*t1_2(1)*t2_3(2,1)*t1_1(2)
+		   + t2_2(0,0)*t1_2(2)*t2_3(0,2)*t1_1(0)
+		   + t2_2(1,0)*t1_2(2)*t2_3(1,2)*t1_1(0)
+		   + t2_2(2,0)*t1_2(2)*t2_3(2,2)*t1_1(0)
+		   + t2_2(0,1)*t1_2(2)*t2_3(0,2)*t1_1(1)
+		   + t2_2(1,1)*t1_2(2)*t2_3(1,2)*t1_1(1)
+		   + t2_2(2,1)*t1_2(2)*t2_3(2,2)*t1_1(1)
+		   + t2_2(0,2)*t1_2(2)*t2_3(0,2)*t1_1(2)
+		   + t2_2(1,2)*t1_2(2)*t2_3(1,2)*t1_1(2)
+		   + t2_2(2,2)*t1_2(2)*t2_3(2,2)*t1_1(2)),
+		"T3(i,j,k)*T3(i,k,j)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t2_3(j,k)*t1_1(i))
+		- (t2_2(0,0)*t1_2(0)*t2_3(0,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(0)*t2_3(0,0)*t1_1(1)
+		   + t2_2(2,0)*t1_2(0)*t2_3(0,0)*t1_1(2)
+		   + t2_2(0,1)*t1_2(0)*t2_3(1,0)*t1_1(0)
+		   + t2_2(1,1)*t1_2(0)*t2_3(1,0)*t1_1(1)
+		   + t2_2(2,1)*t1_2(0)*t2_3(1,0)*t1_1(2)
+		   + t2_2(0,2)*t1_2(0)*t2_3(2,0)*t1_1(0)
+		   + t2_2(1,2)*t1_2(0)*t2_3(2,0)*t1_1(1)
+		   + t2_2(2,2)*t1_2(0)*t2_3(2,0)*t1_1(2)
+		   + t2_2(0,0)*t1_2(1)*t2_3(0,1)*t1_1(0)
+		   + t2_2(1,0)*t1_2(1)*t2_3(0,1)*t1_1(1)
+		   + t2_2(2,0)*t1_2(1)*t2_3(0,1)*t1_1(2)
+		   + t2_2(0,1)*t1_2(1)*t2_3(1,1)*t1_1(0)
+		   + t2_2(1,1)*t1_2(1)*t2_3(1,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(1)*t2_3(1,1)*t1_1(2)
+		   + t2_2(0,2)*t1_2(1)*t2_3(2,1)*t1_1(0)
+		   + t2_2(1,2)*t1_2(1)*t2_3(2,1)*t1_1(1)
+		   + t2_2(2,2)*t1_2(1)*t2_3(2,1)*t1_1(2)
+		   + t2_2(0,0)*t1_2(2)*t2_3(0,2)*t1_1(0)
+		   + t2_2(1,0)*t1_2(2)*t2_3(0,2)*t1_1(1)
+		   + t2_2(2,0)*t1_2(2)*t2_3(0,2)*t1_1(2)
+		   + t2_2(0,1)*t1_2(2)*t2_3(1,2)*t1_1(0)
+		   + t2_2(1,1)*t1_2(2)*t2_3(1,2)*t1_1(1)
+		   + t2_2(2,1)*t1_2(2)*t2_3(1,2)*t1_1(2)
+		   + t2_2(0,2)*t1_2(2)*t2_3(2,2)*t1_1(0)
+		   + t2_2(1,2)*t1_2(2)*t2_3(2,2)*t1_1(1)
+		   + t2_2(2,2)*t1_2(2)*t2_3(2,2)*t1_1(2)),
+		"T3(i,j,k)*T3(j,k,i)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t2_3(k,j)*t1_1(i))
+		- (t2_2(0,0)*t1_2(0)*t2_3(0,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(0)*t2_3(0,0)*t1_1(1)
+		   + t2_2(2,0)*t1_2(0)*t2_3(0,0)*t1_1(2)
+		   + t2_2(0,1)*t1_2(0)*t2_3(0,1)*t1_1(0)
+		   + t2_2(1,1)*t1_2(0)*t2_3(0,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(0)*t2_3(0,1)*t1_1(2)
+		   + t2_2(0,2)*t1_2(0)*t2_3(0,2)*t1_1(0)
+		   + t2_2(1,2)*t1_2(0)*t2_3(0,2)*t1_1(1)
+		   + t2_2(2,2)*t1_2(0)*t2_3(0,2)*t1_1(2)
+		   + t2_2(0,0)*t1_2(1)*t2_3(1,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(1)*t2_3(1,0)*t1_1(1)
+		   + t2_2(2,0)*t1_2(1)*t2_3(1,0)*t1_1(2)
+		   + t2_2(0,1)*t1_2(1)*t2_3(1,1)*t1_1(0)
+		   + t2_2(1,1)*t1_2(1)*t2_3(1,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(1)*t2_3(1,1)*t1_1(2)
+		   + t2_2(0,2)*t1_2(1)*t2_3(1,2)*t1_1(0)
+		   + t2_2(1,2)*t1_2(1)*t2_3(1,2)*t1_1(1)
+		   + t2_2(2,2)*t1_2(1)*t2_3(1,2)*t1_1(2)
+		   + t2_2(0,0)*t1_2(2)*t2_3(2,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(2)*t2_3(2,0)*t1_1(1)
+		   + t2_2(2,0)*t1_2(2)*t2_3(2,0)*t1_1(2)
+		   + t2_2(0,1)*t1_2(2)*t2_3(2,1)*t1_1(0)
+		   + t2_2(1,1)*t1_2(2)*t2_3(2,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(2)*t2_3(2,1)*t1_1(2)
+		   + t2_2(0,2)*t1_2(2)*t2_3(2,2)*t1_1(0)
+		   + t2_2(1,2)*t1_2(2)*t2_3(2,2)*t1_1(1)
+		   + t2_2(2,2)*t1_2(2)*t2_3(2,2)*t1_1(2)),
+		"T3(i,j,k)*T3(k,j,i)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t2_3(k,i)*t1_1(j))
+		- (t2_2(0,0)*t1_2(0)*t2_3(0,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(0)*t2_3(0,1)*t1_1(0)
+		   + t2_2(2,0)*t1_2(0)*t2_3(0,2)*t1_1(0)
+		   + t2_2(0,1)*t1_2(0)*t2_3(0,0)*t1_1(1)
+		   + t2_2(1,1)*t1_2(0)*t2_3(0,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(0)*t2_3(0,2)*t1_1(1)
+		   + t2_2(0,2)*t1_2(0)*t2_3(0,0)*t1_1(2)
+		   + t2_2(1,2)*t1_2(0)*t2_3(0,1)*t1_1(2)
+		   + t2_2(2,2)*t1_2(0)*t2_3(0,2)*t1_1(2)
+		   + t2_2(0,0)*t1_2(1)*t2_3(1,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(1)*t2_3(1,1)*t1_1(0)
+		   + t2_2(2,0)*t1_2(1)*t2_3(1,2)*t1_1(0)
+		   + t2_2(0,1)*t1_2(1)*t2_3(1,0)*t1_1(1)
+		   + t2_2(1,1)*t1_2(1)*t2_3(1,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(1)*t2_3(1,2)*t1_1(1)
+		   + t2_2(0,2)*t1_2(1)*t2_3(1,0)*t1_1(2)
+		   + t2_2(1,2)*t1_2(1)*t2_3(1,1)*t1_1(2)
+		   + t2_2(2,2)*t1_2(1)*t2_3(1,2)*t1_1(2)
+		   + t2_2(0,0)*t1_2(2)*t2_3(2,0)*t1_1(0)
+		   + t2_2(1,0)*t1_2(2)*t2_3(2,1)*t1_1(0)
+		   + t2_2(2,0)*t1_2(2)*t2_3(2,2)*t1_1(0)
+		   + t2_2(0,1)*t1_2(2)*t2_3(2,0)*t1_1(1)
+		   + t2_2(1,1)*t1_2(2)*t2_3(2,1)*t1_1(1)
+		   + t2_2(2,1)*t1_2(2)*t2_3(2,2)*t1_1(1)
+		   + t2_2(0,2)*t1_2(2)*t2_3(2,0)*t1_1(2)
+		   + t2_2(1,2)*t1_2(2)*t2_3(2,1)*t1_1(2)
+		   + t2_2(2,2)*t1_2(2)*t2_3(2,2)*t1_1(2)),
+		"T3(i,j,k)*T3(k,i,j)");
+
+
+
+
+
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t3dg_2(i,j,k))
+		- (t2_2(0,0)*t1_2(0)*t3dg_2(0,0,0)
+		   + t2_2(1,0)*t1_2(0)*t3dg_2(1,0,0)
+		   + t2_2(2,0)*t1_2(0)*t3dg_2(2,0,0)
+		   + t2_2(0,1)*t1_2(0)*t3dg_2(0,1,0)
+		   + t2_2(1,1)*t1_2(0)*t3dg_2(1,1,0)
+		   + t2_2(2,1)*t1_2(0)*t3dg_2(2,1,0)
+		   + t2_2(0,2)*t1_2(0)*t3dg_2(0,2,0)
+		   + t2_2(1,2)*t1_2(0)*t3dg_2(1,2,0)
+		   + t2_2(2,2)*t1_2(0)*t3dg_2(2,2,0)
+		   + t2_2(0,0)*t1_2(1)*t3dg_2(0,0,1)
+		   + t2_2(1,0)*t1_2(1)*t3dg_2(1,0,1)
+		   + t2_2(2,0)*t1_2(1)*t3dg_2(2,0,1)
+		   + t2_2(0,1)*t1_2(1)*t3dg_2(0,1,1)
+		   + t2_2(1,1)*t1_2(1)*t3dg_2(1,1,1)
+		   + t2_2(2,1)*t1_2(1)*t3dg_2(2,1,1)
+		   + t2_2(0,2)*t1_2(1)*t3dg_2(0,2,1)
+		   + t2_2(1,2)*t1_2(1)*t3dg_2(1,2,1)
+		   + t2_2(2,2)*t1_2(1)*t3dg_2(2,2,1)
+		   + t2_2(0,0)*t1_2(2)*t3dg_2(0,0,2)
+		   + t2_2(1,0)*t1_2(2)*t3dg_2(1,0,2)
+		   + t2_2(2,0)*t1_2(2)*t3dg_2(2,0,2)
+		   + t2_2(0,1)*t1_2(2)*t3dg_2(0,1,2)
+		   + t2_2(1,1)*t1_2(2)*t3dg_2(1,1,2)
+		   + t2_2(2,1)*t1_2(2)*t3dg_2(2,1,2)
+		   + t2_2(0,2)*t1_2(2)*t3dg_2(0,2,2)
+		   + t2_2(1,2)*t1_2(2)*t3dg_2(1,2,2)
+		   + t2_2(2,2)*t1_2(2)*t3dg_2(2,2,2)),
+		"T3(i,j,k)*T3dg(i,j,k)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t3dg_2(j,i,k))
+		- (t2_2(0,0)*t1_2(0)*t3dg_2(0,0,0)
+		   + t2_2(1,0)*t1_2(0)*t3dg_2(0,1,0)
+		   + t2_2(2,0)*t1_2(0)*t3dg_2(0,2,0)
+		   + t2_2(0,1)*t1_2(0)*t3dg_2(1,0,0)
+		   + t2_2(1,1)*t1_2(0)*t3dg_2(1,1,0)
+		   + t2_2(2,1)*t1_2(0)*t3dg_2(1,2,0)
+		   + t2_2(0,2)*t1_2(0)*t3dg_2(2,0,0)
+		   + t2_2(1,2)*t1_2(0)*t3dg_2(2,1,0)
+		   + t2_2(2,2)*t1_2(0)*t3dg_2(2,2,0)
+		   + t2_2(0,0)*t1_2(1)*t3dg_2(0,0,1)
+		   + t2_2(1,0)*t1_2(1)*t3dg_2(0,1,1)
+		   + t2_2(2,0)*t1_2(1)*t3dg_2(0,2,1)
+		   + t2_2(0,1)*t1_2(1)*t3dg_2(1,0,1)
+		   + t2_2(1,1)*t1_2(1)*t3dg_2(1,1,1)
+		   + t2_2(2,1)*t1_2(1)*t3dg_2(1,2,1)
+		   + t2_2(0,2)*t1_2(1)*t3dg_2(2,0,1)
+		   + t2_2(1,2)*t1_2(1)*t3dg_2(2,1,1)
+		   + t2_2(2,2)*t1_2(1)*t3dg_2(2,2,1)
+		   + t2_2(0,0)*t1_2(2)*t3dg_2(0,0,2)
+		   + t2_2(1,0)*t1_2(2)*t3dg_2(0,1,2)
+		   + t2_2(2,0)*t1_2(2)*t3dg_2(0,2,2)
+		   + t2_2(0,1)*t1_2(2)*t3dg_2(1,0,2)
+		   + t2_2(1,1)*t1_2(2)*t3dg_2(1,1,2)
+		   + t2_2(2,1)*t1_2(2)*t3dg_2(1,2,2)
+		   + t2_2(0,2)*t1_2(2)*t3dg_2(2,0,2)
+		   + t2_2(1,2)*t1_2(2)*t3dg_2(2,1,2)
+		   + t2_2(2,2)*t1_2(2)*t3dg_2(2,2,2)),
+		"T3(i,j,k)*T3dg(j,i,k)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t3dg_2(i,k,j))
+		- (t2_2(0,0)*t1_2(0)*t3dg_2(0,0,0)
+		   + t2_2(1,0)*t1_2(0)*t3dg_2(1,0,0)
+		   + t2_2(2,0)*t1_2(0)*t3dg_2(2,0,0)
+		   + t2_2(0,1)*t1_2(0)*t3dg_2(0,0,1)
+		   + t2_2(1,1)*t1_2(0)*t3dg_2(1,0,1)
+		   + t2_2(2,1)*t1_2(0)*t3dg_2(2,0,1)
+		   + t2_2(0,2)*t1_2(0)*t3dg_2(0,0,2)
+		   + t2_2(1,2)*t1_2(0)*t3dg_2(1,0,2)
+		   + t2_2(2,2)*t1_2(0)*t3dg_2(2,0,2)
+		   + t2_2(0,0)*t1_2(1)*t3dg_2(0,1,0)
+		   + t2_2(1,0)*t1_2(1)*t3dg_2(1,1,0)
+		   + t2_2(2,0)*t1_2(1)*t3dg_2(2,1,0)
+		   + t2_2(0,1)*t1_2(1)*t3dg_2(0,1,1)
+		   + t2_2(1,1)*t1_2(1)*t3dg_2(1,1,1)
+		   + t2_2(2,1)*t1_2(1)*t3dg_2(2,1,1)
+		   + t2_2(0,2)*t1_2(1)*t3dg_2(0,1,2)
+		   + t2_2(1,2)*t1_2(1)*t3dg_2(1,1,2)
+		   + t2_2(2,2)*t1_2(1)*t3dg_2(2,1,2)
+		   + t2_2(0,0)*t1_2(2)*t3dg_2(0,2,0)
+		   + t2_2(1,0)*t1_2(2)*t3dg_2(1,2,0)
+		   + t2_2(2,0)*t1_2(2)*t3dg_2(2,2,0)
+		   + t2_2(0,1)*t1_2(2)*t3dg_2(0,2,1)
+		   + t2_2(1,1)*t1_2(2)*t3dg_2(1,2,1)
+		   + t2_2(2,1)*t1_2(2)*t3dg_2(2,2,1)
+		   + t2_2(0,2)*t1_2(2)*t3dg_2(0,2,2)
+		   + t2_2(1,2)*t1_2(2)*t3dg_2(1,2,2)
+		   + t2_2(2,2)*t1_2(2)*t3dg_2(2,2,2)),
+		"T3(i,j,k)*T3dg(i,k,j)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t3dg_2(j,k,i))
+		- (t2_2(0,0)*t1_2(0)*t3dg_2(0,0,0)
+		   + t2_2(1,0)*t1_2(0)*t3dg_2(0,0,1)
+		   + t2_2(2,0)*t1_2(0)*t3dg_2(0,0,2)
+		   + t2_2(0,1)*t1_2(0)*t3dg_2(1,0,0)
+		   + t2_2(1,1)*t1_2(0)*t3dg_2(1,0,1)
+		   + t2_2(2,1)*t1_2(0)*t3dg_2(1,0,2)
+		   + t2_2(0,2)*t1_2(0)*t3dg_2(2,0,0)
+		   + t2_2(1,2)*t1_2(0)*t3dg_2(2,0,1)
+		   + t2_2(2,2)*t1_2(0)*t3dg_2(2,0,2)
+		   + t2_2(0,0)*t1_2(1)*t3dg_2(0,1,0)
+		   + t2_2(1,0)*t1_2(1)*t3dg_2(0,1,1)
+		   + t2_2(2,0)*t1_2(1)*t3dg_2(0,1,2)
+		   + t2_2(0,1)*t1_2(1)*t3dg_2(1,1,0)
+		   + t2_2(1,1)*t1_2(1)*t3dg_2(1,1,1)
+		   + t2_2(2,1)*t1_2(1)*t3dg_2(1,1,2)
+		   + t2_2(0,2)*t1_2(1)*t3dg_2(2,1,0)
+		   + t2_2(1,2)*t1_2(1)*t3dg_2(2,1,1)
+		   + t2_2(2,2)*t1_2(1)*t3dg_2(2,1,2)
+		   + t2_2(0,0)*t1_2(2)*t3dg_2(0,2,0)
+		   + t2_2(1,0)*t1_2(2)*t3dg_2(0,2,1)
+		   + t2_2(2,0)*t1_2(2)*t3dg_2(0,2,2)
+		   + t2_2(0,1)*t1_2(2)*t3dg_2(1,2,0)
+		   + t2_2(1,1)*t1_2(2)*t3dg_2(1,2,1)
+		   + t2_2(2,1)*t1_2(2)*t3dg_2(1,2,2)
+		   + t2_2(0,2)*t1_2(2)*t3dg_2(2,2,0)
+		   + t2_2(1,2)*t1_2(2)*t3dg_2(2,2,1)
+		   + t2_2(2,2)*t1_2(2)*t3dg_2(2,2,2)),
+		"T3(i,j,k)*T3dg(j,k,i)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t3dg_2(k,j,i))
+		- (t2_2(0,0)*t1_2(0)*t3dg_2(0,0,0)
+		   + t2_2(1,0)*t1_2(0)*t3dg_2(0,0,1)
+		   + t2_2(2,0)*t1_2(0)*t3dg_2(0,0,2)
+		   + t2_2(0,1)*t1_2(0)*t3dg_2(0,1,0)
+		   + t2_2(1,1)*t1_2(0)*t3dg_2(0,1,1)
+		   + t2_2(2,1)*t1_2(0)*t3dg_2(0,1,2)
+		   + t2_2(0,2)*t1_2(0)*t3dg_2(0,2,0)
+		   + t2_2(1,2)*t1_2(0)*t3dg_2(0,2,1)
+		   + t2_2(2,2)*t1_2(0)*t3dg_2(0,2,2)
+		   + t2_2(0,0)*t1_2(1)*t3dg_2(1,0,0)
+		   + t2_2(1,0)*t1_2(1)*t3dg_2(1,0,1)
+		   + t2_2(2,0)*t1_2(1)*t3dg_2(1,0,2)
+		   + t2_2(0,1)*t1_2(1)*t3dg_2(1,1,0)
+		   + t2_2(1,1)*t1_2(1)*t3dg_2(1,1,1)
+		   + t2_2(2,1)*t1_2(1)*t3dg_2(1,1,2)
+		   + t2_2(0,2)*t1_2(1)*t3dg_2(1,2,0)
+		   + t2_2(1,2)*t1_2(1)*t3dg_2(1,2,1)
+		   + t2_2(2,2)*t1_2(1)*t3dg_2(1,2,2)
+		   + t2_2(0,0)*t1_2(2)*t3dg_2(2,0,0)
+		   + t2_2(1,0)*t1_2(2)*t3dg_2(2,0,1)
+		   + t2_2(2,0)*t1_2(2)*t3dg_2(2,0,2)
+		   + t2_2(0,1)*t1_2(2)*t3dg_2(2,1,0)
+		   + t2_2(1,1)*t1_2(2)*t3dg_2(2,1,1)
+		   + t2_2(2,1)*t1_2(2)*t3dg_2(2,1,2)
+		   + t2_2(0,2)*t1_2(2)*t3dg_2(2,2,0)
+		   + t2_2(1,2)*t1_2(2)*t3dg_2(2,2,1)
+		   + t2_2(2,2)*t1_2(2)*t3dg_2(2,2,2)),
+		"T3(i,j,k)*T3dg(k,j,i)");
+
+  test_for_zero((t2_2(i,j)*t1_2(k))*(t3dg_2(k,i,j))
+		- (t2_2(0,0)*t1_2(0)*t3dg_2(0,0,0)
+		   + t2_2(1,0)*t1_2(0)*t3dg_2(0,1,0)
+		   + t2_2(2,0)*t1_2(0)*t3dg_2(0,2,0)
+		   + t2_2(0,1)*t1_2(0)*t3dg_2(0,0,1)
+		   + t2_2(1,1)*t1_2(0)*t3dg_2(0,1,1)
+		   + t2_2(2,1)*t1_2(0)*t3dg_2(0,2,1)
+		   + t2_2(0,2)*t1_2(0)*t3dg_2(0,0,2)
+		   + t2_2(1,2)*t1_2(0)*t3dg_2(0,1,2)
+		   + t2_2(2,2)*t1_2(0)*t3dg_2(0,2,2)
+		   + t2_2(0,0)*t1_2(1)*t3dg_2(1,0,0)
+		   + t2_2(1,0)*t1_2(1)*t3dg_2(1,1,0)
+		   + t2_2(2,0)*t1_2(1)*t3dg_2(1,2,0)
+		   + t2_2(0,1)*t1_2(1)*t3dg_2(1,0,1)
+		   + t2_2(1,1)*t1_2(1)*t3dg_2(1,1,1)
+		   + t2_2(2,1)*t1_2(1)*t3dg_2(1,2,1)
+		   + t2_2(0,2)*t1_2(1)*t3dg_2(1,0,2)
+		   + t2_2(1,2)*t1_2(1)*t3dg_2(1,1,2)
+		   + t2_2(2,2)*t1_2(1)*t3dg_2(1,2,2)
+		   + t2_2(0,0)*t1_2(2)*t3dg_2(2,0,0)
+		   + t2_2(1,0)*t1_2(2)*t3dg_2(2,1,0)
+		   + t2_2(2,0)*t1_2(2)*t3dg_2(2,2,0)
+		   + t2_2(0,1)*t1_2(2)*t3dg_2(2,0,1)
+		   + t2_2(1,1)*t1_2(2)*t3dg_2(2,1,1)
+		   + t2_2(2,1)*t1_2(2)*t3dg_2(2,2,1)
+		   + t2_2(0,2)*t1_2(2)*t3dg_2(2,0,2)
+		   + t2_2(1,2)*t1_2(2)*t3dg_2(2,1,2)
+		   + t2_2(2,2)*t1_2(2)*t3dg_2(2,2,2)),
+		"T3(i,j,k)*T3dg(k,i,j)");
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3/test_T3II.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3/test_T3II.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,372 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3II(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))+(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(i,j,k)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))+(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(i,j,k)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))+(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(i,j,k)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))+(t2_3(0,1)*t1_1(0)))
+		,"T3(i,j,k)+T3(i,j,k)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))+(t2_3(0,1)*t1_1(1)))
+		,"T3(i,j,k)+T3(i,j,k)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))+(t2_3(0,1)*t1_1(2)))
+		,"T3(i,j,k)+T3(i,j,k)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))+(t2_3(0,2)*t1_1(0)))
+		,"T3(i,j,k)+T3(i,j,k)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))+(t2_3(0,2)*t1_1(1)))
+		,"T3(i,j,k)+T3(i,j,k)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,j)*t1_1(k)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))+(t2_3(0,2)*t1_1(2)))
+		,"T3(i,j,k)+T3(i,j,k)(0,2,2)");
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))+(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(i,k,j)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))+(t2_3(0,1)*t1_1(0)))
+		,"T3(i,j,k)+T3(i,k,j)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))+(t2_3(0,2)*t1_1(0)))
+		,"T3(i,j,k)+T3(i,k,j)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))+(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(i,k,j)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))+(t2_3(0,1)*t1_1(1)))
+		,"T3(i,j,k)+T3(i,k,j)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))+(t2_3(0,2)*t1_1(1)))
+		,"T3(i,j,k)+T3(i,k,j)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))+(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(i,k,j)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))+(t2_3(0,1)*t1_1(2)))
+		,"T3(i,j,k)+T3(i,k,j)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(i,k)*t1_1(j)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))+(t2_3(0,2)*t1_1(2)))
+		,"T3(i,j,k)+T3(i,k,j)(0,2,2)");
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))+(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(j,i,k)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))+(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(j,i,k)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))+(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(j,i,k)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))+(t2_3(1,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(j,i,k)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))+(t2_3(1,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(j,i,k)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))+(t2_3(1,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(j,i,k)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))+(t2_3(2,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(j,i,k)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))+(t2_3(2,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(j,i,k)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(j,i)*t1_1(k)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))+(t2_3(2,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(j,i,k)(0,2,2)");
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))+(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(k,i,j)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))+(t2_3(1,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(k,i,j)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))+(t2_3(2,0)*t1_1(0)))
+		,"T3(i,j,k)+T3(k,i,j)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))+(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(k,i,j)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))+(t2_3(1,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(k,i,j)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))+(t2_3(2,0)*t1_1(1)))
+		,"T3(i,j,k)+T3(k,i,j)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))+(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(k,i,j)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))+(t2_3(1,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(k,i,j)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))+(t2_3(k,i)*t1_1(j)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))+(t2_3(2,0)*t1_1(2)))
+		,"T3(i,j,k)+T3(k,i,j)(0,2,2)");
+
+
+
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))-(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(i,j,k)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))-(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(i,j,k)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))-(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(i,j,k)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))-(t2_3(0,1)*t1_1(0)))
+		,"T3(i,j,k)-T3(i,j,k)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))-(t2_3(0,1)*t1_1(1)))
+		,"T3(i,j,k)-T3(i,j,k)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))-(t2_3(0,1)*t1_1(2)))
+		,"T3(i,j,k)-T3(i,j,k)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))-(t2_3(0,2)*t1_1(0)))
+		,"T3(i,j,k)-T3(i,j,k)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))-(t2_3(0,2)*t1_1(1)))
+		,"T3(i,j,k)-T3(i,j,k)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,j)*t1_1(k)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))-(t2_3(0,2)*t1_1(2)))
+		,"T3(i,j,k)-T3(i,j,k)(0,2,2)");
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))-(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(i,k,j)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))-(t2_3(0,1)*t1_1(0)))
+		,"T3(i,j,k)-T3(i,k,j)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))-(t2_3(0,2)*t1_1(0)))
+		,"T3(i,j,k)-T3(i,k,j)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))-(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(i,k,j)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))-(t2_3(0,1)*t1_1(1)))
+		,"T3(i,j,k)-T3(i,k,j)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))-(t2_3(0,2)*t1_1(1)))
+		,"T3(i,j,k)-T3(i,k,j)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))-(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(i,k,j)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))-(t2_3(0,1)*t1_1(2)))
+		,"T3(i,j,k)-T3(i,k,j)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(i,k)*t1_1(j)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))-(t2_3(0,2)*t1_1(2)))
+		,"T3(i,j,k)-T3(i,k,j)(0,2,2)");
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))-(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(j,i,k)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))-(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(j,i,k)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))-(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(j,i,k)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))-(t2_3(1,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(j,i,k)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))-(t2_3(1,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(j,i,k)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))-(t2_3(1,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(j,i,k)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))-(t2_3(2,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(j,i,k)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))-(t2_3(2,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(j,i,k)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(j,i)*t1_1(k)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))-(t2_3(2,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(j,i,k)(0,2,2)");
+
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,0,0)
+		- ((t2_2(0,0)*t1_2(0))-(t2_3(0,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(k,i,j)(0,0,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,0,1)
+		- ((t2_2(0,0)*t1_2(1))-(t2_3(1,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(k,i,j)(0,0,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,0,2)
+		- ((t2_2(0,0)*t1_2(2))-(t2_3(2,0)*t1_1(0)))
+		,"T3(i,j,k)-T3(k,i,j)(0,0,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,1,0)
+		- ((t2_2(0,1)*t1_2(0))-(t2_3(0,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(k,i,j)(0,1,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,1,1)
+		- ((t2_2(0,1)*t1_2(1))-(t2_3(1,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(k,i,j)(0,1,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,1,2)
+		- ((t2_2(0,1)*t1_2(2))-(t2_3(2,0)*t1_1(1)))
+		,"T3(i,j,k)-T3(k,i,j)(0,1,2)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,2,0)
+		- ((t2_2(0,2)*t1_2(0))-(t2_3(0,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(k,i,j)(0,2,0)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,2,1)
+		- ((t2_2(0,2)*t1_2(1))-(t2_3(1,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(k,i,j)(0,2,1)");
+  test_for_zero(((t2_2(i,j)*t1_2(k))-(t2_3(k,i)*t1_1(j)))(0,2,2)
+		- ((t2_2(0,2)*t1_2(2))-(t2_3(2,0)*t1_1(2)))
+		,"T3(i,j,k)-T3(k,i,j)(0,2,2)");
+
+  t3dg_1(j,k,i)=(t2_2(i,j)*t1_2(k)) || (t2_2(i,k)*t1_2(j));
+  test_for_zero(t3dg_1(0,0,0) - (t2_2(0,0)*t1_2(0) + t2_2(0,0)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(0,0,0)");
+  test_for_zero(t3dg_1(0,1,0) - (t2_2(0,0)*t1_2(1) + t2_2(0,1)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(0,0,1)");
+  test_for_zero(t3dg_1(0,2,0) - (t2_2(0,0)*t1_2(2) + t2_2(0,2)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(0,0,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t2_2(0,1)*t1_2(0) + t2_2(0,0)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(0,1,0)");
+  test_for_zero(t3dg_1(1,1,0) - (t2_2(0,1)*t1_2(1) + t2_2(0,1)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(0,1,1)");
+  test_for_zero(t3dg_1(1,2,0) - (t2_2(0,1)*t1_2(2) + t2_2(0,2)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(0,1,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t2_2(0,2)*t1_2(0) + t2_2(0,0)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(0,2,0)");
+  test_for_zero(t3dg_1(2,1,0) - (t2_2(0,2)*t1_2(1) + t2_2(0,1)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(0,2,1)");
+  test_for_zero(t3dg_1(2,2,0) - (t2_2(0,2)*t1_2(2) + t2_2(0,2)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(0,2,2)");
+  test_for_zero(t3dg_1(0,0,1) - (t2_2(1,0)*t1_2(0) + t2_2(1,0)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(1,0,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t2_2(1,0)*t1_2(1) + t2_2(1,1)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(1,0,1)");
+  test_for_zero(t3dg_1(0,2,1) - (t2_2(1,0)*t1_2(2) + t2_2(1,2)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(1,0,2)");
+  test_for_zero(t3dg_1(1,0,1) - (t2_2(1,1)*t1_2(0) + t2_2(1,0)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t2_2(1,1)*t1_2(1) + t2_2(1,1)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(1,1,1)");
+  test_for_zero(t3dg_1(1,2,1) - (t2_2(1,1)*t1_2(2) + t2_2(1,2)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(1,1,2)");
+  test_for_zero(t3dg_1(2,0,1) - (t2_2(1,2)*t1_2(0) + t2_2(1,0)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(1,2,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t2_2(1,2)*t1_2(1) + t2_2(1,1)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(1,2,1)");
+  test_for_zero(t3dg_1(2,2,1) - (t2_2(1,2)*t1_2(2) + t2_2(1,2)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(1,2,2)");
+  test_for_zero(t3dg_1(0,0,2) - (t2_2(2,0)*t1_2(0) + t2_2(2,0)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(2,0,0)");
+  test_for_zero(t3dg_1(0,1,2) - (t2_2(2,0)*t1_2(1) + t2_2(2,1)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(2,0,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t2_2(2,0)*t1_2(2) + t2_2(2,2)*t1_2(0))
+		,"T3(i,j,k)||T3(i,k,j)(2,0,2)");
+  test_for_zero(t3dg_1(1,0,2) - (t2_2(2,1)*t1_2(0) + t2_2(2,0)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(2,1,0)");
+  test_for_zero(t3dg_1(1,1,2) - (t2_2(2,1)*t1_2(1) + t2_2(2,1)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(2,1,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t2_2(2,1)*t1_2(2) + t2_2(2,2)*t1_2(1))
+		,"T3(i,j,k)||T3(i,k,j)(2,1,2)");
+  test_for_zero(t3dg_1(2,0,2) - (t2_2(2,2)*t1_2(0) + t2_2(2,0)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(2,2,0)");
+  test_for_zero(t3dg_1(2,1,2) - (t2_2(2,2)*t1_2(1) + t2_2(2,1)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t2_2(2,2)*t1_2(2) + t2_2(2,2)*t1_2(2))
+		,"T3(i,j,k)||T3(i,k,j)(2,2,2)");
+  t3dg_1(i,k,j)=(t2_2(i,j)*t1_2(k)) || (t2_2(k,j)*t1_2(i));
+  test_for_zero(t3dg_1(0,0,0) - (t2_2(0,0)*t1_2(0) + t2_2(0,0)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,0,0)");
+  test_for_zero(t3dg_1(0,1,0) - (t2_2(0,0)*t1_2(1) + t2_2(1,0)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,0,1)");
+  test_for_zero(t3dg_1(0,2,0) - (t2_2(0,0)*t1_2(2) + t2_2(2,0)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,0,2)");
+  test_for_zero(t3dg_1(0,0,1) - (t2_2(0,1)*t1_2(0) + t2_2(0,1)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t2_2(0,1)*t1_2(1) + t2_2(1,1)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,1,1)");
+  test_for_zero(t3dg_1(0,2,1) - (t2_2(0,1)*t1_2(2) + t2_2(2,1)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,1,2)");
+  test_for_zero(t3dg_1(0,0,2) - (t2_2(0,2)*t1_2(0) + t2_2(0,2)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,2,0)");
+  test_for_zero(t3dg_1(0,1,2) - (t2_2(0,2)*t1_2(1) + t2_2(1,2)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t2_2(0,2)*t1_2(2) + t2_2(2,2)*t1_2(0))
+		,"T3(i,j,k)||T3(k,j,i)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t2_2(1,0)*t1_2(0) + t2_2(0,0)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,0,0)");
+  test_for_zero(t3dg_1(1,1,0) - (t2_2(1,0)*t1_2(1) + t2_2(1,0)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,0,1)");
+  test_for_zero(t3dg_1(1,2,0) - (t2_2(1,0)*t1_2(2) + t2_2(2,0)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,0,2)");
+  test_for_zero(t3dg_1(1,0,1) - (t2_2(1,1)*t1_2(0) + t2_2(0,1)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t2_2(1,1)*t1_2(1) + t2_2(1,1)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,1,1)");
+  test_for_zero(t3dg_1(1,2,1) - (t2_2(1,1)*t1_2(2) + t2_2(2,1)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,1,2)");
+  test_for_zero(t3dg_1(1,0,2) - (t2_2(1,2)*t1_2(0) + t2_2(0,2)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,2,0)");
+  test_for_zero(t3dg_1(1,1,2) - (t2_2(1,2)*t1_2(1) + t2_2(1,2)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t2_2(1,2)*t1_2(2) + t2_2(2,2)*t1_2(1))
+		,"T3(i,j,k)||T3(k,j,i)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t2_2(2,0)*t1_2(0) + t2_2(0,0)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,0,0)");
+  test_for_zero(t3dg_1(2,1,0) - (t2_2(2,0)*t1_2(1) + t2_2(1,0)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,0,1)");
+  test_for_zero(t3dg_1(2,2,0) - (t2_2(2,0)*t1_2(2) + t2_2(2,0)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,0,2)");
+  test_for_zero(t3dg_1(2,0,1) - (t2_2(2,1)*t1_2(0) + t2_2(0,1)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t2_2(2,1)*t1_2(1) + t2_2(1,1)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,1,1)");
+  test_for_zero(t3dg_1(2,2,1) - (t2_2(2,1)*t1_2(2) + t2_2(2,1)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,1,2)");
+  test_for_zero(t3dg_1(2,0,2) - (t2_2(2,2)*t1_2(0) + t2_2(0,2)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,2,0)");
+  test_for_zero(t3dg_1(2,1,2) - (t2_2(2,2)*t1_2(1) + t2_2(1,2)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t2_2(2,2)*t1_2(2) + t2_2(2,2)*t1_2(2))
+		,"T3(i,j,k)||T3(k,j,i)(2,2,2)");
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3as.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3as.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,277 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+extern 
+void test_T3asI(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asII(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asIII(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asIV(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asV(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asVI(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asVII(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asVIII(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asIX(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asX(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asXI(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asXII(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asXIII(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+extern 
+void test_T3asXIV(const int &T, Tensor0<double*> &t0_1,
+	       const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
+
+
+
+void test_T3as(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  test_T3asI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T3asXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,88 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  t3as_1(i,j,k)=(t3dg_2(i,j,k) && t3dg_2(i,k,j));
+
+  test_for_zero(t3as_1(0,0,0) - (t3dg_2(0,0,0) - t3dg_2(0,0,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,0,0)");
+  test_for_zero(t3as_1(0,0,1) - (t3dg_2(0,0,1) - t3dg_2(0,1,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,0,1)");
+  test_for_zero(t3as_1(0,0,2) - (t3dg_2(0,0,2) - t3dg_2(0,2,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,0,2)");
+  test_for_zero(t3as_1(0,1,0) - (t3dg_2(0,1,0) - t3dg_2(0,0,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,1,0)");
+  test_for_zero(t3as_1(0,1,1) - (t3dg_2(0,1,1) - t3dg_2(0,1,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,1,1)");
+  test_for_zero(t3as_1(0,1,2) - (t3dg_2(0,1,2) - t3dg_2(0,2,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,1,2)");
+  test_for_zero(t3as_1(0,2,0) - (t3dg_2(0,2,0) - t3dg_2(0,0,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,2,0)");
+  test_for_zero(t3as_1(0,2,1) - (t3dg_2(0,2,1) - t3dg_2(0,1,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,2,1)");
+  test_for_zero(t3as_1(0,2,2) - (t3dg_2(0,2,2) - t3dg_2(0,2,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(0,2,2)");
+  test_for_zero(t3as_1(1,0,0) - (t3dg_2(1,0,0) - t3dg_2(1,0,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,0,0)");
+  test_for_zero(t3as_1(1,0,1) - (t3dg_2(1,0,1) - t3dg_2(1,1,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,0,1)");
+  test_for_zero(t3as_1(1,0,2) - (t3dg_2(1,0,2) - t3dg_2(1,2,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,0,2)");
+  test_for_zero(t3as_1(1,1,0) - (t3dg_2(1,1,0) - t3dg_2(1,0,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,1,0)");
+  test_for_zero(t3as_1(1,1,1) - (t3dg_2(1,1,1) - t3dg_2(1,1,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,1,1)");
+  test_for_zero(t3as_1(1,1,2) - (t3dg_2(1,1,2) - t3dg_2(1,2,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,1,2)");
+  test_for_zero(t3as_1(1,2,0) - (t3dg_2(1,2,0) - t3dg_2(1,0,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,2,0)");
+  test_for_zero(t3as_1(1,2,1) - (t3dg_2(1,2,1) - t3dg_2(1,1,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,2,1)");
+  test_for_zero(t3as_1(1,2,2) - (t3dg_2(1,2,2) - t3dg_2(1,2,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(1,2,2)");
+  test_for_zero(t3as_1(2,0,0) - (t3dg_2(2,0,0) - t3dg_2(2,0,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,0,0)");
+  test_for_zero(t3as_1(2,0,1) - (t3dg_2(2,0,1) - t3dg_2(2,1,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,0,1)");
+  test_for_zero(t3as_1(2,0,2) - (t3dg_2(2,0,2) - t3dg_2(2,2,0))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,0,2)");
+  test_for_zero(t3as_1(2,1,0) - (t3dg_2(2,1,0) - t3dg_2(2,0,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,1,0)");
+  test_for_zero(t3as_1(2,1,1) - (t3dg_2(2,1,1) - t3dg_2(2,1,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,1,1)");
+  test_for_zero(t3as_1(2,1,2) - (t3dg_2(2,1,2) - t3dg_2(2,2,1))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,1,2)");
+  test_for_zero(t3as_1(2,2,0) - (t3dg_2(2,2,0) - t3dg_2(2,0,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,2,0)");
+  test_for_zero(t3as_1(2,2,1) - (t3dg_2(2,2,1) - t3dg_2(2,1,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,2,1)");
+  test_for_zero(t3as_1(2,2,2) - (t3dg_2(2,2,2) - t3dg_2(2,2,2))
+		,"T3as(i,j,k)=T3dg(i,j,k) && T3dg(i,k,j)(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  t3as_1(j,i,k)=(t3dg_2(i,j,k) && t3dg_2(k,j,i));
+  test_for_zero(t3as_1(0,0,0) - (t3dg_2(0,0,0) - t3dg_2(0,0,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,0,0)");
+  test_for_zero(t3as_1(0,0,1) - (t3dg_2(0,0,1) - t3dg_2(1,0,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,0,1)");
+  test_for_zero(t3as_1(0,0,2) - (t3dg_2(0,0,2) - t3dg_2(2,0,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,0,2)");
+  test_for_zero(t3as_1(1,0,0) - (t3dg_2(0,1,0) - t3dg_2(0,1,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,1,0)");
+  test_for_zero(t3as_1(1,0,1) - (t3dg_2(0,1,1) - t3dg_2(1,1,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,1,1)");
+  test_for_zero(t3as_1(1,0,2) - (t3dg_2(0,1,2) - t3dg_2(2,1,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,1,2)");
+  test_for_zero(t3as_1(2,0,0) - (t3dg_2(0,2,0) - t3dg_2(0,2,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,2,0)");
+  test_for_zero(t3as_1(2,0,1) - (t3dg_2(0,2,1) - t3dg_2(1,2,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,2,1)");
+  test_for_zero(t3as_1(2,0,2) - (t3dg_2(0,2,2) - t3dg_2(2,2,0))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(0,2,2)");
+  test_for_zero(t3as_1(0,1,0) - (t3dg_2(1,0,0) - t3dg_2(0,0,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,0,0)");
+  test_for_zero(t3as_1(0,1,1) - (t3dg_2(1,0,1) - t3dg_2(1,0,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,0,1)");
+  test_for_zero(t3as_1(0,1,2) - (t3dg_2(1,0,2) - t3dg_2(2,0,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,0,2)");
+  test_for_zero(t3as_1(1,1,0) - (t3dg_2(1,1,0) - t3dg_2(0,1,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,1,0)");
+  test_for_zero(t3as_1(1,1,1) - (t3dg_2(1,1,1) - t3dg_2(1,1,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,1,1)");
+  test_for_zero(t3as_1(1,1,2) - (t3dg_2(1,1,2) - t3dg_2(2,1,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,1,2)");
+  test_for_zero(t3as_1(2,1,0) - (t3dg_2(1,2,0) - t3dg_2(0,2,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,2,0)");
+  test_for_zero(t3as_1(2,1,1) - (t3dg_2(1,2,1) - t3dg_2(1,2,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,2,1)");
+  test_for_zero(t3as_1(2,1,2) - (t3dg_2(1,2,2) - t3dg_2(2,2,1))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(1,2,2)");
+  test_for_zero(t3as_1(0,2,0) - (t3dg_2(2,0,0) - t3dg_2(0,0,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,0,0)");
+  test_for_zero(t3as_1(0,2,1) - (t3dg_2(2,0,1) - t3dg_2(1,0,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,0,1)");
+  test_for_zero(t3as_1(0,2,2) - (t3dg_2(2,0,2) - t3dg_2(2,0,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,0,2)");
+  test_for_zero(t3as_1(1,2,0) - (t3dg_2(2,1,0) - t3dg_2(0,1,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,1,0)");
+  test_for_zero(t3as_1(1,2,1) - (t3dg_2(2,1,1) - t3dg_2(1,1,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,1,1)");
+  test_for_zero(t3as_1(1,2,2) - (t3dg_2(2,1,2) - t3dg_2(2,1,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,1,2)");
+  test_for_zero(t3as_1(2,2,0) - (t3dg_2(2,2,0) - t3dg_2(0,2,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,2,0)");
+  test_for_zero(t3as_1(2,2,1) - (t3dg_2(2,2,1) - t3dg_2(1,2,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,2,1)");
+  test_for_zero(t3as_1(2,2,2) - (t3dg_2(2,2,2) - t3dg_2(2,2,2))
+		,"T3dg(i,j,k) && T3dg(k,j,i)(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  t3as_1(i,k,j)=(t3dg_2(i,j,k) && t3dg_2(i,k,j));
+  test_for_zero(t3as_1(0,0,0) - (t3dg_2(0,0,0) - t3dg_2(0,0,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,0,0)");
+  test_for_zero(t3as_1(0,1,0) - (t3dg_2(0,0,1) - t3dg_2(0,1,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,0,1)");
+  test_for_zero(t3as_1(0,2,0) - (t3dg_2(0,0,2) - t3dg_2(0,2,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,0,2)");
+  test_for_zero(t3as_1(0,0,1) - (t3dg_2(0,1,0) - t3dg_2(0,0,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,1,0)");
+  test_for_zero(t3as_1(0,1,1) - (t3dg_2(0,1,1) - t3dg_2(0,1,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,1,1)");
+  test_for_zero(t3as_1(0,2,1) - (t3dg_2(0,1,2) - t3dg_2(0,2,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,1,2)");
+  test_for_zero(t3as_1(0,0,2) - (t3dg_2(0,2,0) - t3dg_2(0,0,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,2,0)");
+  test_for_zero(t3as_1(0,1,2) - (t3dg_2(0,2,1) - t3dg_2(0,1,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,2,1)");
+  test_for_zero(t3as_1(0,2,2) - (t3dg_2(0,2,2) - t3dg_2(0,2,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(0,2,2)");
+  test_for_zero(t3as_1(1,0,0) - (t3dg_2(1,0,0) - t3dg_2(1,0,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,0,0)");
+  test_for_zero(t3as_1(1,1,0) - (t3dg_2(1,0,1) - t3dg_2(1,1,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,0,1)");
+  test_for_zero(t3as_1(1,2,0) - (t3dg_2(1,0,2) - t3dg_2(1,2,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,0,2)");
+  test_for_zero(t3as_1(1,0,1) - (t3dg_2(1,1,0) - t3dg_2(1,0,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,1,0)");
+  test_for_zero(t3as_1(1,1,1) - (t3dg_2(1,1,1) - t3dg_2(1,1,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,1,1)");
+  test_for_zero(t3as_1(1,2,1) - (t3dg_2(1,1,2) - t3dg_2(1,2,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,1,2)");
+  test_for_zero(t3as_1(1,0,2) - (t3dg_2(1,2,0) - t3dg_2(1,0,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,2,0)");
+  test_for_zero(t3as_1(1,1,2) - (t3dg_2(1,2,1) - t3dg_2(1,1,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,2,1)");
+  test_for_zero(t3as_1(1,2,2) - (t3dg_2(1,2,2) - t3dg_2(1,2,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(1,2,2)");
+  test_for_zero(t3as_1(2,0,0) - (t3dg_2(2,0,0) - t3dg_2(2,0,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,0,0)");
+  test_for_zero(t3as_1(2,1,0) - (t3dg_2(2,0,1) - t3dg_2(2,1,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,0,1)");
+  test_for_zero(t3as_1(2,2,0) - (t3dg_2(2,0,2) - t3dg_2(2,2,0))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,0,2)");
+  test_for_zero(t3as_1(2,0,1) - (t3dg_2(2,1,0) - t3dg_2(2,0,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,1,0)");
+  test_for_zero(t3as_1(2,1,1) - (t3dg_2(2,1,1) - t3dg_2(2,1,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,1,1)");
+  test_for_zero(t3as_1(2,2,1) - (t3dg_2(2,1,2) - t3dg_2(2,2,1))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,1,2)");
+  test_for_zero(t3as_1(2,0,2) - (t3dg_2(2,2,0) - t3dg_2(2,0,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,2,0)");
+  test_for_zero(t3as_1(2,1,2) - (t3dg_2(2,2,1) - t3dg_2(2,1,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,2,1)");
+  test_for_zero(t3as_1(2,2,2) - (t3dg_2(2,2,2) - t3dg_2(2,2,2))
+		,"T3as(i,k,j)=T3dg(i,j,k) && T3dg(i,k,j)(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  t3as_1(i,j,k)=t3as_2(i,j,k) + t3as_3(i,j,k);
+  test_for_zero(t3as_1(0,0,0)-(t3as_2(0,0,0)+t3as_3(0,0,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,0,0)");
+  test_for_zero(t3as_1(0,0,1)-(t3as_2(0,0,1)+t3as_3(0,0,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,0,1)");
+  test_for_zero(t3as_1(0,0,2)-(t3as_2(0,0,2)+t3as_3(0,0,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,0,2)");
+  test_for_zero(t3as_1(0,1,0)-(t3as_2(0,1,0)+t3as_3(0,1,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,1,0)");
+  test_for_zero(t3as_1(0,1,1)-(t3as_2(0,1,1)+t3as_3(0,1,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,1,1)");
+  test_for_zero(t3as_1(0,1,2)-(t3as_2(0,1,2)+t3as_3(0,1,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,1,2)");
+  test_for_zero(t3as_1(0,2,0)-(t3as_2(0,2,0)+t3as_3(0,2,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,2,0)");
+  test_for_zero(t3as_1(0,2,1)-(t3as_2(0,2,1)+t3as_3(0,2,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,2,1)");
+  test_for_zero(t3as_1(0,2,2)-(t3as_2(0,2,2)+t3as_3(0,2,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(0,2,2)");
+  test_for_zero(t3as_1(1,0,0)-(t3as_2(1,0,0)+t3as_3(1,0,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,0,0)");
+  test_for_zero(t3as_1(1,0,1)-(t3as_2(1,0,1)+t3as_3(1,0,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,0,1)");
+  test_for_zero(t3as_1(1,0,2)-(t3as_2(1,0,2)+t3as_3(1,0,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,0,2)");
+  test_for_zero(t3as_1(1,1,0)-(t3as_2(1,1,0)+t3as_3(1,1,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,1,0)");
+  test_for_zero(t3as_1(1,1,1)-(t3as_2(1,1,1)+t3as_3(1,1,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,1,1)");
+  test_for_zero(t3as_1(1,1,2)-(t3as_2(1,1,2)+t3as_3(1,1,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,1,2)");
+  test_for_zero(t3as_1(1,2,0)-(t3as_2(1,2,0)+t3as_3(1,2,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,2,0)");
+  test_for_zero(t3as_1(1,2,1)-(t3as_2(1,2,1)+t3as_3(1,2,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,2,1)");
+  test_for_zero(t3as_1(1,2,2)-(t3as_2(1,2,2)+t3as_3(1,2,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(1,2,2)");
+  test_for_zero(t3as_1(2,0,0)-(t3as_2(2,0,0)+t3as_3(2,0,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,0,0)");
+  test_for_zero(t3as_1(2,0,1)-(t3as_2(2,0,1)+t3as_3(2,0,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,0,1)");
+  test_for_zero(t3as_1(2,0,2)-(t3as_2(2,0,2)+t3as_3(2,0,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,0,2)");
+  test_for_zero(t3as_1(2,1,0)-(t3as_2(2,1,0)+t3as_3(2,1,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,1,0)");
+  test_for_zero(t3as_1(2,1,1)-(t3as_2(2,1,1)+t3as_3(2,1,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,1,1)");
+  test_for_zero(t3as_1(2,1,2)-(t3as_2(2,1,2)+t3as_3(2,1,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,1,2)");
+  test_for_zero(t3as_1(2,2,0)-(t3as_2(2,2,0)+t3as_3(2,2,0))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,2,0)");
+  test_for_zero(t3as_1(2,2,1)-(t3as_2(2,2,1)+t3as_3(2,2,1))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,2,1)");
+  test_for_zero(t3as_1(2,2,2)-(t3as_2(2,2,2)+t3as_3(2,2,2))
+		,"T3as(i,j,k) + T3as(i,j,k)(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,72 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  test_for_zero(t3as_2(i,j,k)*(t2_2(i,j)*t1_2(k))
+		- (t3as_2(0,1,0)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,1,0)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(0,2,0)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(2,2,0)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,0,1)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,0,1)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(0,2,1)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(1,2,1)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(2,2)*t1_2(1)
+		   + t3as_2(0,0,2)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,0,2)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(2,0,2)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(1,1,2)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,1,2)*t2_2(2,1)*t1_2(2))
+		,"T3as(i,j,k)*T3dg(i,j,k)");
+  test_for_zero((t2_2(i,j)*t1_2(k)*t3as_2(i,j,k))
+		- (t3as_2(0,1,0)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,1,0)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(0,2,0)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(2,2,0)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,0,1)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,0,1)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(0,2,1)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(1,2,1)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(2,2)*t1_2(1)
+		   + t3as_2(0,0,2)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,0,2)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(2,0,2)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(1,1,2)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,1,2)*t2_2(2,1)*t1_2(2))
+		,"T3dg(i,j,k)*T3as(i,j,k)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  t3as_1(i,j,k)=t3as_2(i,j,k) + t3as_3(i,k,j);
+  test_for_zero(t3as_1(0,0,0)-(t3as_2(0,0,0)-t3as_3(0,0,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,0,0)");
+  test_for_zero(t3as_1(0,0,1)-(t3as_2(0,0,1)-t3as_3(0,0,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,0,1)");
+  test_for_zero(t3as_1(0,0,2)-(t3as_2(0,0,2)-t3as_3(0,0,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,0,2)");
+  test_for_zero(t3as_1(0,1,0)-(t3as_2(0,1,0)-t3as_3(0,1,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,1,0)");
+  test_for_zero(t3as_1(0,1,1)-(t3as_2(0,1,1)-t3as_3(0,1,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,1,1)");
+  test_for_zero(t3as_1(0,1,2)-(t3as_2(0,1,2)-t3as_3(0,1,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,1,2)");
+  test_for_zero(t3as_1(0,2,0)-(t3as_2(0,2,0)-t3as_3(0,2,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,2,0)");
+  test_for_zero(t3as_1(0,2,1)-(t3as_2(0,2,1)-t3as_3(0,2,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,2,1)");
+  test_for_zero(t3as_1(0,2,2)-(t3as_2(0,2,2)-t3as_3(0,2,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(0,2,2)");
+  test_for_zero(t3as_1(1,0,0)-(t3as_2(1,0,0)-t3as_3(1,0,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,0,0)");
+  test_for_zero(t3as_1(1,0,1)-(t3as_2(1,0,1)-t3as_3(1,0,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,0,1)");
+  test_for_zero(t3as_1(1,0,2)-(t3as_2(1,0,2)-t3as_3(1,0,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,0,2)");
+  test_for_zero(t3as_1(1,1,0)-(t3as_2(1,1,0)-t3as_3(1,1,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,1,0)");
+  test_for_zero(t3as_1(1,1,1)-(t3as_2(1,1,1)-t3as_3(1,1,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,1,1)");
+  test_for_zero(t3as_1(1,1,2)-(t3as_2(1,1,2)-t3as_3(1,1,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,1,2)");
+  test_for_zero(t3as_1(1,2,0)-(t3as_2(1,2,0)-t3as_3(1,2,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,2,0)");
+  test_for_zero(t3as_1(1,2,1)-(t3as_2(1,2,1)-t3as_3(1,2,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,2,1)");
+  test_for_zero(t3as_1(1,2,2)-(t3as_2(1,2,2)-t3as_3(1,2,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(1,2,2)");
+  test_for_zero(t3as_1(2,0,0)-(t3as_2(2,0,0)-t3as_3(2,0,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,0,0)");
+  test_for_zero(t3as_1(2,0,1)-(t3as_2(2,0,1)-t3as_3(2,0,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,0,1)");
+  test_for_zero(t3as_1(2,0,2)-(t3as_2(2,0,2)-t3as_3(2,0,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,0,2)");
+  test_for_zero(t3as_1(2,1,0)-(t3as_2(2,1,0)-t3as_3(2,1,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,1,0)");
+  test_for_zero(t3as_1(2,1,1)-(t3as_2(2,1,1)-t3as_3(2,1,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,1,1)");
+  test_for_zero(t3as_1(2,1,2)-(t3as_2(2,1,2)-t3as_3(2,1,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,1,2)");
+  test_for_zero(t3as_1(2,2,0)-(t3as_2(2,2,0)-t3as_3(2,2,0))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,2,0)");
+  test_for_zero(t3as_1(2,2,1)-(t3as_2(2,2,1)-t3as_3(2,2,1))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,2,1)");
+  test_for_zero(t3as_1(2,2,2)-(t3as_2(2,2,2)-t3as_3(2,2,2))
+		,"T3as(i,j,k) + T3as(i,k,j)(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  t3dg_1(i,k,j)=(t3as_2(i,j,k) || t3as_2(k,j,i));
+  test_for_zero(t3dg_1(0,0,0)-(t3as_2(0,0,0)+t3as_2(0,0,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,0,0)");
+  test_for_zero(t3dg_1(0,1,0)-(t3as_2(0,0,1)+t3as_2(1,0,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,0,1)");
+  test_for_zero(t3dg_1(0,2,0)-(t3as_2(0,0,2)+t3as_2(2,0,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,0,2)");
+  test_for_zero(t3dg_1(0,0,1)-(t3as_2(0,1,0)+t3as_2(0,1,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1)-(t3as_2(0,1,1)+t3as_2(1,1,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,1,1)");
+  test_for_zero(t3dg_1(0,2,1)-(t3as_2(0,1,2)+t3as_2(2,1,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,1,2)");
+  test_for_zero(t3dg_1(0,0,2)-(t3as_2(0,2,0)+t3as_2(0,2,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,2,0)");
+  test_for_zero(t3dg_1(0,1,2)-(t3as_2(0,2,1)+t3as_2(1,2,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2)-(t3as_2(0,2,2)+t3as_2(2,2,0))
+		,"T3as(i,j,k) || T3as(k,j,i)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0)-(t3as_2(1,0,0)+t3as_2(0,0,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,0,0)");
+  test_for_zero(t3dg_1(1,1,0)-(t3as_2(1,0,1)+t3as_2(1,0,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,0,1)");
+  test_for_zero(t3dg_1(1,2,0)-(t3as_2(1,0,2)+t3as_2(2,0,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,0,2)");
+  test_for_zero(t3dg_1(1,0,1)-(t3as_2(1,1,0)+t3as_2(0,1,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1)-(t3as_2(1,1,1)+t3as_2(1,1,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,1,1)");
+  test_for_zero(t3dg_1(1,2,1)-(t3as_2(1,1,2)+t3as_2(2,1,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,1,2)");
+  test_for_zero(t3dg_1(1,0,2)-(t3as_2(1,2,0)+t3as_2(0,2,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,2,0)");
+  test_for_zero(t3dg_1(1,1,2)-(t3as_2(1,2,1)+t3as_2(1,2,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2)-(t3as_2(1,2,2)+t3as_2(2,2,1))
+		,"T3as(i,j,k) || T3as(k,j,i)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0)-(t3as_2(2,0,0)+t3as_2(0,0,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,0,0)");
+  test_for_zero(t3dg_1(2,1,0)-(t3as_2(2,0,1)+t3as_2(1,0,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,0,1)");
+  test_for_zero(t3dg_1(2,2,0)-(t3as_2(2,0,2)+t3as_2(2,0,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,0,2)");
+  test_for_zero(t3dg_1(2,0,1)-(t3as_2(2,1,0)+t3as_2(0,1,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1)-(t3as_2(2,1,1)+t3as_2(1,1,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,1,1)");
+  test_for_zero(t3dg_1(2,2,1)-(t3as_2(2,1,2)+t3as_2(2,1,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,1,2)");
+  test_for_zero(t3dg_1(2,0,2)-(t3as_2(2,2,0)+t3as_2(0,2,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,2,0)");
+  test_for_zero(t3dg_1(2,1,2)-(t3as_2(2,2,1)+t3as_2(1,2,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2)-(t3as_2(2,2,2)+t3as_2(2,2,2))
+		,"T3as(i,j,k) || T3as(k,j,i)(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+  
+  t3as_1(i,j,k)=t3as_2(i,j,k)*10;
+  test_for_zero(t3as_1(0,0,0)-(t3as_2(0,0,0)*10)
+		,"T3as*T(0,0,0)");
+  test_for_zero(t3as_1(0,0,1)-(t3as_2(0,0,1)*10)
+		,"T3as*T(0,0,1)");
+  test_for_zero(t3as_1(0,0,2)-(t3as_2(0,0,2)*10)
+		,"T3as*T(0,0,2)");
+  test_for_zero(t3as_1(0,1,0)-(t3as_2(0,1,0)*10)
+		,"T3as*T(0,1,0)");
+  test_for_zero(t3as_1(0,1,1)-(t3as_2(0,1,1)*10)
+		,"T3as*T(0,1,1)");
+  test_for_zero(t3as_1(0,1,2)-(t3as_2(0,1,2)*10)
+		,"T3as*T(0,1,2)");
+  test_for_zero(t3as_1(0,2,0)-(t3as_2(0,2,0)*10)
+		,"T3as*T(0,2,0)");
+  test_for_zero(t3as_1(0,2,1)-(t3as_2(0,2,1)*10)
+		,"T3as*T(0,2,1)");
+  test_for_zero(t3as_1(0,2,2)-(t3as_2(0,2,2)*10)
+		,"T3as*T(0,2,2)");
+  test_for_zero(t3as_1(1,0,0)-(t3as_2(1,0,0)*10)
+		,"T3as*T(1,0,0)");
+  test_for_zero(t3as_1(1,0,1)-(t3as_2(1,0,1)*10)
+		,"T3as*T(1,0,1)");
+  test_for_zero(t3as_1(1,0,2)-(t3as_2(1,0,2)*10)
+		,"T3as*T(1,0,2)");
+  test_for_zero(t3as_1(1,1,0)-(t3as_2(1,1,0)*10)
+		,"T3as*T(1,1,0)");
+  test_for_zero(t3as_1(1,1,1)-(t3as_2(1,1,1)*10)
+		,"T3as*T(1,1,1)");
+  test_for_zero(t3as_1(1,1,2)-(t3as_2(1,1,2)*10)
+		,"T3as*T(1,1,2)");
+  test_for_zero(t3as_1(1,2,0)-(t3as_2(1,2,0)*10)
+		,"T3as*T(1,2,0)");
+  test_for_zero(t3as_1(1,2,1)-(t3as_2(1,2,1)*10)
+		,"T3as*T(1,2,1)");
+  test_for_zero(t3as_1(1,2,2)-(t3as_2(1,2,2)*10)
+		,"T3as*T(1,2,2)");
+  test_for_zero(t3as_1(2,0,0)-(t3as_2(2,0,0)*10)
+		,"T3as*T(2,0,0)");
+  test_for_zero(t3as_1(2,0,1)-(t3as_2(2,0,1)*10)
+		,"T3as*T(2,0,1)");
+  test_for_zero(t3as_1(2,0,2)-(t3as_2(2,0,2)*10)
+		,"T3as*T(2,0,2)");
+  test_for_zero(t3as_1(2,1,0)-(t3as_2(2,1,0)*10)
+		,"T3as*T(2,1,0)");
+  test_for_zero(t3as_1(2,1,1)-(t3as_2(2,1,1)*10)
+		,"T3as*T(2,1,1)");
+  test_for_zero(t3as_1(2,1,2)-(t3as_2(2,1,2)*10)
+		,"T3as*T(2,1,2)");
+  test_for_zero(t3as_1(2,2,0)-(t3as_2(2,2,0)*10)
+		,"T3as*T(2,2,0)");
+  test_for_zero(t3as_1(2,2,1)-(t3as_2(2,2,1)*10)
+		,"T3as*T(2,2,1)");
+  test_for_zero(t3as_1(2,2,2)-(t3as_2(2,2,2)*10)
+		,"T3as*T(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,87 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  t3as_1(i,j,k)=5*t3as_2(i,j,k);
+  test_for_zero(t3as_1(0,0,0)-(t3as_2(0,0,0)*5)
+		,"T*T3as(0,0,0)");
+  test_for_zero(t3as_1(0,0,1)-(t3as_2(0,0,1)*5)
+		,"T*T3as(0,0,1)");
+  test_for_zero(t3as_1(0,0,2)-(t3as_2(0,0,2)*5)
+		,"T*T3as(0,0,2)");
+  test_for_zero(t3as_1(0,1,0)-(t3as_2(0,1,0)*5)
+		,"T*T3as(0,1,0)");
+  test_for_zero(t3as_1(0,1,1)-(t3as_2(0,1,1)*5)
+		,"T*T3as(0,1,1)");
+  test_for_zero(t3as_1(0,1,2)-(t3as_2(0,1,2)*5)
+		,"T*T3as(0,1,2)");
+  test_for_zero(t3as_1(0,2,0)-(t3as_2(0,2,0)*5)
+		,"T*T3as(0,2,0)");
+  test_for_zero(t3as_1(0,2,1)-(t3as_2(0,2,1)*5)
+		,"T*T3as(0,2,1)");
+  test_for_zero(t3as_1(0,2,2)-(t3as_2(0,2,2)*5)
+		,"T*T3as(0,2,2)");
+  test_for_zero(t3as_1(1,0,0)-(t3as_2(1,0,0)*5)
+		,"T*T3as(1,0,0)");
+  test_for_zero(t3as_1(1,0,1)-(t3as_2(1,0,1)*5)
+		,"T*T3as(1,0,1)");
+  test_for_zero(t3as_1(1,0,2)-(t3as_2(1,0,2)*5)
+		,"T*T3as(1,0,2)");
+  test_for_zero(t3as_1(1,1,0)-(t3as_2(1,1,0)*5)
+		,"T*T3as(1,1,0)");
+  test_for_zero(t3as_1(1,1,1)-(t3as_2(1,1,1)*5)
+		,"T*T3as(1,1,1)");
+  test_for_zero(t3as_1(1,1,2)-(t3as_2(1,1,2)*5)
+		,"T*T3as(1,1,2)");
+  test_for_zero(t3as_1(1,2,0)-(t3as_2(1,2,0)*5)
+		,"T*T3as(1,2,0)");
+  test_for_zero(t3as_1(1,2,1)-(t3as_2(1,2,1)*5)
+		,"T*T3as(1,2,1)");
+  test_for_zero(t3as_1(1,2,2)-(t3as_2(1,2,2)*5)
+		,"T*T3as(1,2,2)");
+  test_for_zero(t3as_1(2,0,0)-(t3as_2(2,0,0)*5)
+		,"T*T3as(2,0,0)");
+  test_for_zero(t3as_1(2,0,1)-(t3as_2(2,0,1)*5)
+		,"T*T3as(2,0,1)");
+  test_for_zero(t3as_1(2,0,2)-(t3as_2(2,0,2)*5)
+		,"T*T3as(2,0,2)");
+  test_for_zero(t3as_1(2,1,0)-(t3as_2(2,1,0)*5)
+		,"T*T3as(2,1,0)");
+  test_for_zero(t3as_1(2,1,1)-(t3as_2(2,1,1)*5)
+		,"T*T3as(2,1,1)");
+  test_for_zero(t3as_1(2,1,2)-(t3as_2(2,1,2)*5)
+		,"T*T3as(2,1,2)");
+  test_for_zero(t3as_1(2,2,0)-(t3as_2(2,2,0)*5)
+		,"T*T3as(2,2,0)");
+  test_for_zero(t3as_1(2,2,1)-(t3as_2(2,2,1)*5)
+		,"T*T3as(2,2,1)");
+  test_for_zero(t3as_1(2,2,2)-(t3as_2(2,2,2)*5)
+		,"T*T3as(2,2,2)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,72 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  test_for_zero(t3as_2(i,j,k)*(t2_2(i,k)*t1_2(j))
+		- (t3as_2(0,1,0)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,1,0)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(0,2,0)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,2,0)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(2,2,0)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,0,1)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(0,2,1)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(1,2,1)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,2,1)*t2_2(2,1)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(2,0,2)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,1,2)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(1,1,2)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(2,2)*t1_2(1))
+		,"T3as(i,j,k)*T3dg(i,k,j)");
+  test_for_zero((t2_2(i,k)*t1_2(j)*t3as_2(i,j,k))
+		- (t3as_2(0,1,0)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,1,0)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(0,2,0)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,2,0)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(2,2,0)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,0,1)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(0,2,1)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(1,2,1)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,2,1)*t2_2(2,1)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(2,0,2)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,1,2)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(1,1,2)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(2,2)*t1_2(1))
+		,"T3dg(i,k,j)*T3as(i,j,k)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,72 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  test_for_zero(t3as_2(i,j,k)*(t2_2(k,i)*t1_2(j))
+		- (t3as_2(0,1,0)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,1,0)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(0,2,0)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,2,0)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(2,2,0)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,0,1)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(0,2,1)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(1,2,1)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,2,1)*t2_2(1,2)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(2,0,2)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,1,2)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(1,1,2)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(2,2)*t1_2(1))
+		,"T3as(i,j,k)*T3dg(k,i,j)");
+  test_for_zero((t2_2(k,i)*t1_2(j)*t3as_2(i,j,k))
+		- (t3as_2(0,1,0)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,1,0)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(0,2,0)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,2,0)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(2,2,0)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,0,1)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(0,2,1)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(1,2,1)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,2,1)*t2_2(1,2)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(2,0,2)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,1,2)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(1,1,2)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(2,2)*t1_2(1))
+		,"T3dg(k,i,j)*T3as(i,j,k)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,72 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  test_for_zero(t3as_2(i,j,k)*(t2_2(j,i)*t1_2(k))
+		- (t3as_2(0,1,0)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,1,0)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(0,2,0)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(2,2,0)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,0,1)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,0,1)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(0,2,1)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(1,2,1)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(2,2)*t1_2(1)
+		   + t3as_2(0,0,2)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,0,2)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(2,0,2)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(1,1,2)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,1,2)*t2_2(1,2)*t1_2(2))
+		,"T3as(i,j,k)*T3dg(j,i,k)");
+  test_for_zero((t2_2(j,i)*t1_2(k)*t3as_2(i,j,k))
+		- (t3as_2(0,1,0)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(1,1)*t1_2(0)
+		   + t3as_2(2,1,0)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(0,2,0)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(2,2,0)*t2_2(2,2)*t1_2(0)
+		   + t3as_2(0,0,1)*t2_2(0,0)*t1_2(1)
+		   + t3as_2(1,0,1)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(0,2,1)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(1,2,1)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(2,2)*t1_2(1)
+		   + t3as_2(0,0,2)*t2_2(0,0)*t1_2(2)
+		   + t3as_2(1,0,2)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(2,0,2)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(1,1,2)*t2_2(1,1)*t1_2(2)
+		   + t3as_2(2,1,2)*t2_2(1,2)*t1_2(2))
+		,"T3dg(j,i,k)*T3as(i,j,k)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,72 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  test_for_zero(t3as_2(i,j,k)*(t2_2(k,j)*t1_2(i))
+		- (t3as_2(0,1,0)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(0,2,0)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(2,2,0)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(0,2,1)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(1,2,1)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(1,2)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(2,0,2)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(1,1,2)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(2,1)*t1_2(2))
+		,"T3as(i,j,k)*T3dg(k,j,i)");
+  test_for_zero((t2_2(k,j)*t1_2(i)*t3as_2(i,j,k))
+		- (t3as_2(0,1,0)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(0,2,0)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(2,2,0)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(0,2,1)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(1,2,1)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(1,2)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(2,0,2)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(1,1,2)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(2,1)*t1_2(2))
+		,"T3dg(k,j,i)*T3as(i,j,k)");
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3as/test_T3asXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3as/test_T3asXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,74 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3asXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  test_for_zero(t3as_2(i,j,k)*(t2_2(j,k)*t1_2(i))
+		- (t3as_2(0,1,0)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(0,2,0)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(2,2,0)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(0,2,1)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(1,2,1)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(2,1)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(2,0,2)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(1,1,2)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(1,2)*t1_2(2))
+		,"T3as(i,j,k)*T3dg(j,k,i)");
+  test_for_zero((t2_2(j,k)*t1_2(i)*t3as_2(i,j,k))
+		- (t3as_2(0,1,0)*t2_2(1,0)*t1_2(0)
+		   + t3as_2(1,1,0)*t2_2(1,0)*t1_2(1)
+		   + t3as_2(2,1,0)*t2_2(1,0)*t1_2(2)
+		   + t3as_2(0,2,0)*t2_2(2,0)*t1_2(0)
+		   + t3as_2(1,2,0)*t2_2(2,0)*t1_2(1)
+		   + t3as_2(2,2,0)*t2_2(2,0)*t1_2(2)
+		   + t3as_2(0,0,1)*t2_2(0,1)*t1_2(0)
+		   + t3as_2(1,0,1)*t2_2(0,1)*t1_2(1)
+		   + t3as_2(2,0,1)*t2_2(0,1)*t1_2(2)
+		   + t3as_2(0,2,1)*t2_2(2,1)*t1_2(0)
+		   + t3as_2(1,2,1)*t2_2(2,1)*t1_2(1)
+		   + t3as_2(2,2,1)*t2_2(2,1)*t1_2(2)
+		   + t3as_2(0,0,2)*t2_2(0,2)*t1_2(0)
+		   + t3as_2(1,0,2)*t2_2(0,2)*t1_2(1)
+		   + t3as_2(2,0,2)*t2_2(0,2)*t1_2(2)
+		   + t3as_2(0,1,2)*t2_2(1,2)*t1_2(0)
+		   + t3as_2(1,1,2)*t2_2(1,2)*t1_2(1)
+		   + t3as_2(2,1,2)*t2_2(1,2)*t1_2(2))
+		,"T3dg(j,k,i)*T3as(i,j,k)");
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dg.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dg.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,656 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+extern
+void test_T3dgI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgXXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgCII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+extern
+void test_T3dgCIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
+
+
+void test_T3dg(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  
+  test_T3dgI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXVI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXVII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXVIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXIX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXX(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXXI(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXXII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXXIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+		  t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXXIV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgXXXV(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+
+  test_T3dgCII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dgCIII(T,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,t3dg_1,
+	     t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+
+  cout << endl;
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgCII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgCII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,626 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgCII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		 Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		 Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		 const Tensor2<double,3,3> &t2_3,
+		 Tensor2_symmetric<double,3> &t2s_1,
+		 const Tensor2_symmetric<double,3> &t2s_2,
+		 const Tensor2_symmetric<double,3> &t2s_3,
+		 Tensor3_dg<double,3,3> &t3dg_1,
+		 const Tensor3_dg<double,3,3> &t3dg_2,
+		 const Tensor3_dg<double,3,3> &t3dg_3,
+		 Tensor3_christof<double,3,3> &t3ch_1,
+		 const Tensor3_christof<double,3,3> &t3ch_2,
+		 const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+  
+  t3dg_1(j,k,i)=(t3dg_2(i,j,k) || t3dg_2(i,k,j));
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0) + t3dg_2(0,0,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,0,0)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,0,1) + t3dg_2(0,1,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,0,1)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,0,2) + t3dg_2(0,2,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,0,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(0,1,0) + t3dg_2(0,0,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,1,0)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(0,1,1) + t3dg_2(0,1,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,1,1)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(0,1,2) + t3dg_2(0,2,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,1,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(0,2,0) + t3dg_2(0,0,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,2,0)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(0,2,1) + t3dg_2(0,1,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,2,1)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(0,2,2) + t3dg_2(0,2,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(0,2,2)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(1,0,0) + t3dg_2(1,0,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,0,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(1,0,1) + t3dg_2(1,1,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,0,1)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(1,0,2) + t3dg_2(1,2,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,0,2)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,1,0) + t3dg_2(1,0,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1) + t3dg_2(1,1,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,1,1)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,1,2) + t3dg_2(1,2,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,1,2)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(1,2,0) + t3dg_2(1,0,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,2,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(1,2,1) + t3dg_2(1,1,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,2,1)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(1,2,2) + t3dg_2(1,2,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(1,2,2)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(2,0,0) + t3dg_2(2,0,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,0,0)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(2,0,1) + t3dg_2(2,1,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,0,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(2,0,2) + t3dg_2(2,2,0))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,0,2)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(2,1,0) + t3dg_2(2,0,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,1,0)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(2,1,1) + t3dg_2(2,1,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,1,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(2,1,2) + t3dg_2(2,2,1))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,1,2)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,2,0) + t3dg_2(2,0,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,2,0)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,2,1) + t3dg_2(2,1,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2) + t3dg_2(2,2,2))
+		,"T3dg(i,j,k)||T3dg(i,k,j)(2,2,2)");
+
+  t3dg_1(j,k,i)=(t3dg_2(j,i,k) || t3dg_2(k,i,j));
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0) + t3dg_2(0,0,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,0,0)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,0,1) + t3dg_2(1,0,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,0,1)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,0,2) + t3dg_2(2,0,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,0,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(0,1,0) + t3dg_2(0,0,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,1,0)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(0,1,1) + t3dg_2(1,0,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,1,1)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(0,1,2) + t3dg_2(2,0,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,1,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(0,2,0) + t3dg_2(0,0,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,2,0)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(0,2,1) + t3dg_2(1,0,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,2,1)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(0,2,2) + t3dg_2(2,0,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(0,2,2)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(1,0,0) + t3dg_2(0,1,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,0,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(1,0,1) + t3dg_2(1,1,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,0,1)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(1,0,2) + t3dg_2(2,1,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,0,2)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,1,0) + t3dg_2(0,1,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1) + t3dg_2(1,1,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,1,1)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,1,2) + t3dg_2(2,1,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,1,2)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(1,2,0) + t3dg_2(0,1,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,2,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(1,2,1) + t3dg_2(1,1,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,2,1)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(1,2,2) + t3dg_2(2,1,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(1,2,2)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(2,0,0) + t3dg_2(0,2,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,0,0)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(2,0,1) + t3dg_2(1,2,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,0,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(2,0,2) + t3dg_2(2,2,0))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,0,2)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(2,1,0) + t3dg_2(0,2,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,1,0)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(2,1,1) + t3dg_2(1,2,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,1,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(2,1,2) + t3dg_2(2,2,1))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,1,2)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,2,0) + t3dg_2(0,2,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,2,0)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,2,1) + t3dg_2(1,2,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2) + t3dg_2(2,2,2))
+		,"T3dg(j,i,k)||T3dg(k,i,j)(2,2,2)");
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,k)&t2s_2(i,j);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0)*t2s_2(0,0))
+		,"T3dg(j,i,k)&T2s(i,j)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,1)*t2s_2(0,0))
+		,"T3dg(j,i,k)&T2s(i,j)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,2)*t2s_2(0,0))
+		,"T3dg(j,i,k)&T2s(i,j)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0)*t2s_2(0,1))
+		,"T3dg(j,i,k)&T2s(i,j)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,1)*t2s_2(0,1))
+		,"T3dg(j,i,k)&T2s(i,j)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,2)*t2s_2(0,1))
+		,"T3dg(j,i,k)&T2s(i,j)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0)*t2s_2(0,2))
+		,"T3dg(j,i,k)&T2s(i,j)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,1)*t2s_2(0,2))
+		,"T3dg(j,i,k)&T2s(i,j)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,2)*t2s_2(0,2))
+		,"T3dg(j,i,k)&T2s(i,j)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0)*t2s_2(1,0))
+		,"T3dg(j,i,k)&T2s(i,j)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,1)*t2s_2(1,0))
+		,"T3dg(j,i,k)&T2s(i,j)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,2)*t2s_2(1,0))
+		,"T3dg(j,i,k)&T2s(i,j)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0)*t2s_2(1,1))
+		,"T3dg(j,i,k)&T2s(i,j)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1)*t2s_2(1,1))
+		,"T3dg(j,i,k)&T2s(i,j)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,2)*t2s_2(1,1))
+		,"T3dg(j,i,k)&T2s(i,j)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0)*t2s_2(1,2))
+		,"T3dg(j,i,k)&T2s(i,j)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,1)*t2s_2(1,2))
+		,"T3dg(j,i,k)&T2s(i,j)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,2)*t2s_2(1,2))
+		,"T3dg(j,i,k)&T2s(i,j)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0)*t2s_2(2,0))
+		,"T3dg(j,i,k)&T2s(i,j)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,1)*t2s_2(2,0))
+		,"T3dg(j,i,k)&T2s(i,j)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,2)*t2s_2(2,0))
+		,"T3dg(j,i,k)&T2s(i,j)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0)*t2s_2(2,1))
+		,"T3dg(j,i,k)&T2s(i,j)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,1)*t2s_2(2,1))
+		,"T3dg(j,i,k)&T2s(i,j)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,2)*t2s_2(2,1))
+		,"T3dg(j,i,k)&T2s(i,j)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0)*t2s_2(2,2))
+		,"T3dg(j,i,k)&T2s(i,j)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,1)*t2s_2(2,2))
+		,"T3dg(j,i,k)&T2s(i,j)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(j,i,k)&T2s(i,j)(2,2,2)");
+
+  t3dg_1(i,j,k)=t2s_2(i,j)&t3dg_2(i,j,k);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0)*t2s_2(0,0))
+		,"T2s(i,j)&T3dg(j,i,k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,1)*t2s_2(0,0))
+		,"T2s(i,j)&T3dg(j,i,k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,2)*t2s_2(0,0))
+		,"T2s(i,j)&T3dg(j,i,k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0)*t2s_2(0,1))
+		,"T2s(i,j)&T3dg(j,i,k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,1)*t2s_2(0,1))
+		,"T2s(i,j)&T3dg(j,i,k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,2)*t2s_2(0,1))
+		,"T2s(i,j)&T3dg(j,i,k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0)*t2s_2(0,2))
+		,"T2s(i,j)&T3dg(j,i,k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,1)*t2s_2(0,2))
+		,"T2s(i,j)&T3dg(j,i,k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,2)*t2s_2(0,2))
+		,"T2s(i,j)&T3dg(j,i,k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0)*t2s_2(1,0))
+		,"T2s(i,j)&T3dg(j,i,k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,1)*t2s_2(1,0))
+		,"T2s(i,j)&T3dg(j,i,k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,2)*t2s_2(1,0))
+		,"T2s(i,j)&T3dg(j,i,k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0)*t2s_2(1,1))
+		,"T2s(i,j)&T3dg(j,i,k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1)*t2s_2(1,1))
+		,"T2s(i,j)&T3dg(j,i,k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,2)*t2s_2(1,1))
+		,"T2s(i,j)&T3dg(j,i,k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0)*t2s_2(1,2))
+		,"T2s(i,j)&T3dg(j,i,k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,1)*t2s_2(1,2))
+		,"T2s(i,j)&T3dg(j,i,k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,2)*t2s_2(1,2))
+		,"T2s(i,j)&T3dg(j,i,k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0)*t2s_2(2,0))
+		,"T2s(i,j)&T3dg(j,i,k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,1)*t2s_2(2,0))
+		,"T2s(i,j)&T3dg(j,i,k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,2)*t2s_2(2,0))
+		,"T2s(i,j)&T3dg(j,i,k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0)*t2s_2(2,1))
+		,"T2s(i,j)&T3dg(j,i,k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,1)*t2s_2(2,1))
+		,"T2s(i,j)&T3dg(j,i,k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,2)*t2s_2(2,1))
+		,"T2s(i,j)&T3dg(j,i,k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0)*t2s_2(2,2))
+		,"T2s(i,j)&T3dg(j,i,k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,1)*t2s_2(2,2))
+		,"T2s(i,j)&T3dg(j,i,k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T2s(i,j)&T3dg(j,i,k)(2,2,2)");
+
+  t2_1(i,l)=t3dg_2(i,j,k)*t3dg_3(j,k,l);
+  test_for_zero(t2_1(0,0) - (t3dg_2(0,0,0)*t3dg_3(0,0,0)
+			     + t3dg_2(0,0,1)*t3dg_3(0,1,0)
+			     + t3dg_2(0,0,2)*t3dg_3(0,2,0)
+			     + t3dg_2(0,1,0)*t3dg_3(1,0,0)
+			     + t3dg_2(0,1,1)*t3dg_3(1,1,0)
+			     + t3dg_2(0,1,2)*t3dg_3(1,2,0)
+			     + t3dg_2(0,2,0)*t3dg_3(2,0,0)
+			     + t3dg_2(0,2,1)*t3dg_3(2,1,0)
+			     + t3dg_2(0,2,2)*t3dg_3(2,2,0))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_2(0,0,0)*t3dg_3(0,0,1)
+			     + t3dg_2(0,0,1)*t3dg_3(0,1,1)
+			     + t3dg_2(0,0,2)*t3dg_3(0,2,1)
+			     + t3dg_2(0,1,0)*t3dg_3(1,0,1)
+			     + t3dg_2(0,1,1)*t3dg_3(1,1,1)
+			     + t3dg_2(0,1,2)*t3dg_3(1,2,1)
+			     + t3dg_2(0,2,0)*t3dg_3(2,0,1)
+			     + t3dg_2(0,2,1)*t3dg_3(2,1,1)
+			     + t3dg_2(0,2,2)*t3dg_3(2,2,1))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_2(0,0,0)*t3dg_3(0,0,2)
+			     + t3dg_2(0,0,1)*t3dg_3(0,1,2)
+			     + t3dg_2(0,0,2)*t3dg_3(0,2,2)
+			     + t3dg_2(0,1,0)*t3dg_3(1,0,2)
+			     + t3dg_2(0,1,1)*t3dg_3(1,1,2)
+			     + t3dg_2(0,1,2)*t3dg_3(1,2,2)
+			     + t3dg_2(0,2,0)*t3dg_3(2,0,2)
+			     + t3dg_2(0,2,1)*t3dg_3(2,1,2)
+			     + t3dg_2(0,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_2(1,0,0)*t3dg_3(0,0,0)
+			     + t3dg_2(1,0,1)*t3dg_3(0,1,0)
+			     + t3dg_2(1,0,2)*t3dg_3(0,2,0)
+			     + t3dg_2(1,1,0)*t3dg_3(1,0,0)
+			     + t3dg_2(1,1,1)*t3dg_3(1,1,0)
+			     + t3dg_2(1,1,2)*t3dg_3(1,2,0)
+			     + t3dg_2(1,2,0)*t3dg_3(2,0,0)
+			     + t3dg_2(1,2,1)*t3dg_3(2,1,0)
+			     + t3dg_2(1,2,2)*t3dg_3(2,2,0))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_2(1,0,0)*t3dg_3(0,0,1)
+			     + t3dg_2(1,0,1)*t3dg_3(0,1,1)
+			     + t3dg_2(1,0,2)*t3dg_3(0,2,1)
+			     + t3dg_2(1,1,0)*t3dg_3(1,0,1)
+			     + t3dg_2(1,1,1)*t3dg_3(1,1,1)
+			     + t3dg_2(1,1,2)*t3dg_3(1,2,1)
+			     + t3dg_2(1,2,0)*t3dg_3(2,0,1)
+			     + t3dg_2(1,2,1)*t3dg_3(2,1,1)
+			     + t3dg_2(1,2,2)*t3dg_3(2,2,1))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_2(1,0,0)*t3dg_3(0,0,2)
+			     + t3dg_2(1,0,1)*t3dg_3(0,1,2)
+			     + t3dg_2(1,0,2)*t3dg_3(0,2,2)
+			     + t3dg_2(1,1,0)*t3dg_3(1,0,2)
+			     + t3dg_2(1,1,1)*t3dg_3(1,1,2)
+			     + t3dg_2(1,1,2)*t3dg_3(1,2,2)
+			     + t3dg_2(1,2,0)*t3dg_3(2,0,2)
+			     + t3dg_2(1,2,1)*t3dg_3(2,1,2)
+			     + t3dg_2(1,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_2(2,0,0)*t3dg_3(0,0,0)
+			     + t3dg_2(2,0,1)*t3dg_3(0,1,0)
+			     + t3dg_2(2,0,2)*t3dg_3(0,2,0)
+			     + t3dg_2(2,1,0)*t3dg_3(1,0,0)
+			     + t3dg_2(2,1,1)*t3dg_3(1,1,0)
+			     + t3dg_2(2,1,2)*t3dg_3(1,2,0)
+			     + t3dg_2(2,2,0)*t3dg_3(2,0,0)
+			     + t3dg_2(2,2,1)*t3dg_3(2,1,0)
+			     + t3dg_2(2,2,2)*t3dg_3(2,2,0))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_2(2,0,0)*t3dg_3(0,0,1)
+			     + t3dg_2(2,0,1)*t3dg_3(0,1,1)
+			     + t3dg_2(2,0,2)*t3dg_3(0,2,1)
+			     + t3dg_2(2,1,0)*t3dg_3(1,0,1)
+			     + t3dg_2(2,1,1)*t3dg_3(1,1,1)
+			     + t3dg_2(2,1,2)*t3dg_3(1,2,1)
+			     + t3dg_2(2,2,0)*t3dg_3(2,0,1)
+			     + t3dg_2(2,2,1)*t3dg_3(2,1,1)
+			     + t3dg_2(2,2,2)*t3dg_3(2,2,1))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_2(2,0,0)*t3dg_3(0,0,2)
+			     + t3dg_2(2,0,1)*t3dg_3(0,1,2)
+			     + t3dg_2(2,0,2)*t3dg_3(0,2,2)
+			     + t3dg_2(2,1,0)*t3dg_3(1,0,2)
+			     + t3dg_2(2,1,1)*t3dg_3(1,1,2)
+			     + t3dg_2(2,1,2)*t3dg_3(1,2,2)
+			     + t3dg_2(2,2,0)*t3dg_3(2,0,2)
+			     + t3dg_2(2,2,1)*t3dg_3(2,1,2)
+			     + t3dg_2(2,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(j,k,l)(2,2)");
+
+  t2_1(i,l)=t3dg_2(j,k,l)*t3dg_3(i,j,k);
+  test_for_zero(t2_1(0,0) - (t3dg_3(0,0,0)*t3dg_2(0,0,0)
+			     + t3dg_3(0,0,1)*t3dg_2(0,1,0)
+			     + t3dg_3(0,0,2)*t3dg_2(0,2,0)
+			     + t3dg_3(0,1,0)*t3dg_2(1,0,0)
+			     + t3dg_3(0,1,1)*t3dg_2(1,1,0)
+			     + t3dg_3(0,1,2)*t3dg_2(1,2,0)
+			     + t3dg_3(0,2,0)*t3dg_2(2,0,0)
+			     + t3dg_3(0,2,1)*t3dg_2(2,1,0)
+			     + t3dg_3(0,2,2)*t3dg_2(2,2,0))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_3(0,0,0)*t3dg_2(0,0,1)
+			     + t3dg_3(0,0,1)*t3dg_2(0,1,1)
+			     + t3dg_3(0,0,2)*t3dg_2(0,2,1)
+			     + t3dg_3(0,1,0)*t3dg_2(1,0,1)
+			     + t3dg_3(0,1,1)*t3dg_2(1,1,1)
+			     + t3dg_3(0,1,2)*t3dg_2(1,2,1)
+			     + t3dg_3(0,2,0)*t3dg_2(2,0,1)
+			     + t3dg_3(0,2,1)*t3dg_2(2,1,1)
+			     + t3dg_3(0,2,2)*t3dg_2(2,2,1))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_3(0,0,0)*t3dg_2(0,0,2)
+			     + t3dg_3(0,0,1)*t3dg_2(0,1,2)
+			     + t3dg_3(0,0,2)*t3dg_2(0,2,2)
+			     + t3dg_3(0,1,0)*t3dg_2(1,0,2)
+			     + t3dg_3(0,1,1)*t3dg_2(1,1,2)
+			     + t3dg_3(0,1,2)*t3dg_2(1,2,2)
+			     + t3dg_3(0,2,0)*t3dg_2(2,0,2)
+			     + t3dg_3(0,2,1)*t3dg_2(2,1,2)
+			     + t3dg_3(0,2,2)*t3dg_2(2,2,2))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_3(1,0,0)*t3dg_2(0,0,0)
+			     + t3dg_3(1,0,1)*t3dg_2(0,1,0)
+			     + t3dg_3(1,0,2)*t3dg_2(0,2,0)
+			     + t3dg_3(1,1,0)*t3dg_2(1,0,0)
+			     + t3dg_3(1,1,1)*t3dg_2(1,1,0)
+			     + t3dg_3(1,1,2)*t3dg_2(1,2,0)
+			     + t3dg_3(1,2,0)*t3dg_2(2,0,0)
+			     + t3dg_3(1,2,1)*t3dg_2(2,1,0)
+			     + t3dg_3(1,2,2)*t3dg_2(2,2,0))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_3(1,0,0)*t3dg_2(0,0,1)
+			     + t3dg_3(1,0,1)*t3dg_2(0,1,1)
+			     + t3dg_3(1,0,2)*t3dg_2(0,2,1)
+			     + t3dg_3(1,1,0)*t3dg_2(1,0,1)
+			     + t3dg_3(1,1,1)*t3dg_2(1,1,1)
+			     + t3dg_3(1,1,2)*t3dg_2(1,2,1)
+			     + t3dg_3(1,2,0)*t3dg_2(2,0,1)
+			     + t3dg_3(1,2,1)*t3dg_2(2,1,1)
+			     + t3dg_3(1,2,2)*t3dg_2(2,2,1))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_3(1,0,0)*t3dg_2(0,0,2)
+			     + t3dg_3(1,0,1)*t3dg_2(0,1,2)
+			     + t3dg_3(1,0,2)*t3dg_2(0,2,2)
+			     + t3dg_3(1,1,0)*t3dg_2(1,0,2)
+			     + t3dg_3(1,1,1)*t3dg_2(1,1,2)
+			     + t3dg_3(1,1,2)*t3dg_2(1,2,2)
+			     + t3dg_3(1,2,0)*t3dg_2(2,0,2)
+			     + t3dg_3(1,2,1)*t3dg_2(2,1,2)
+			     + t3dg_3(1,2,2)*t3dg_2(2,2,2))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_3(2,0,0)*t3dg_2(0,0,0)
+			     + t3dg_3(2,0,1)*t3dg_2(0,1,0)
+			     + t3dg_3(2,0,2)*t3dg_2(0,2,0)
+			     + t3dg_3(2,1,0)*t3dg_2(1,0,0)
+			     + t3dg_3(2,1,1)*t3dg_2(1,1,0)
+			     + t3dg_3(2,1,2)*t3dg_2(1,2,0)
+			     + t3dg_3(2,2,0)*t3dg_2(2,0,0)
+			     + t3dg_3(2,2,1)*t3dg_2(2,1,0)
+			     + t3dg_3(2,2,2)*t3dg_2(2,2,0))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_3(2,0,0)*t3dg_2(0,0,1)
+			     + t3dg_3(2,0,1)*t3dg_2(0,1,1)
+			     + t3dg_3(2,0,2)*t3dg_2(0,2,1)
+			     + t3dg_3(2,1,0)*t3dg_2(1,0,1)
+			     + t3dg_3(2,1,1)*t3dg_2(1,1,1)
+			     + t3dg_3(2,1,2)*t3dg_2(1,2,1)
+			     + t3dg_3(2,2,0)*t3dg_2(2,0,1)
+			     + t3dg_3(2,2,1)*t3dg_2(2,1,1)
+			     + t3dg_3(2,2,2)*t3dg_2(2,2,1))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_3(2,0,0)*t3dg_2(0,0,2)
+			     + t3dg_3(2,0,1)*t3dg_2(0,1,2)
+			     + t3dg_3(2,0,2)*t3dg_2(0,2,2)
+			     + t3dg_3(2,1,0)*t3dg_2(1,0,2)
+			     + t3dg_3(2,1,1)*t3dg_2(1,1,2)
+			     + t3dg_3(2,1,2)*t3dg_2(1,2,2)
+			     + t3dg_3(2,2,0)*t3dg_2(2,0,2)
+			     + t3dg_3(2,2,1)*t3dg_2(2,1,2)
+			     + t3dg_3(2,2,2)*t3dg_2(2,2,2))
+		,"T3dg(j,k,l)*T3dg(i,j,k)(2,2)");
+
+
+  t2_1(i,l)=t3dg_2(i,j,k)*t3dg_3(k,l,j);
+  test_for_zero(t2_1(0,0) - (t3dg_2(0,0,0)*t3dg_3(0,0,0)
+			     + t3dg_2(0,0,1)*t3dg_3(1,0,0)
+			     + t3dg_2(0,0,2)*t3dg_3(2,0,0)
+			     + t3dg_2(0,1,0)*t3dg_3(0,0,1)
+			     + t3dg_2(0,1,1)*t3dg_3(1,0,1)
+			     + t3dg_2(0,1,2)*t3dg_3(2,0,1)
+			     + t3dg_2(0,2,0)*t3dg_3(0,0,2)
+			     + t3dg_2(0,2,1)*t3dg_3(1,0,2)
+			     + t3dg_2(0,2,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_2(0,0,0)*t3dg_3(0,1,0)
+			     + t3dg_2(0,0,1)*t3dg_3(1,1,0)
+			     + t3dg_2(0,0,2)*t3dg_3(2,1,0)
+			     + t3dg_2(0,1,0)*t3dg_3(0,1,1)
+			     + t3dg_2(0,1,1)*t3dg_3(1,1,1)
+			     + t3dg_2(0,1,2)*t3dg_3(2,1,1)
+			     + t3dg_2(0,2,0)*t3dg_3(0,1,2)
+			     + t3dg_2(0,2,1)*t3dg_3(1,1,2)
+			     + t3dg_2(0,2,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_2(0,0,0)*t3dg_3(0,2,0)
+			     + t3dg_2(0,0,1)*t3dg_3(1,2,0)
+			     + t3dg_2(0,0,2)*t3dg_3(2,2,0)
+			     + t3dg_2(0,1,0)*t3dg_3(0,2,1)
+			     + t3dg_2(0,1,1)*t3dg_3(1,2,1)
+			     + t3dg_2(0,1,2)*t3dg_3(2,2,1)
+			     + t3dg_2(0,2,0)*t3dg_3(0,2,2)
+			     + t3dg_2(0,2,1)*t3dg_3(1,2,2)
+			     + t3dg_2(0,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_2(1,0,0)*t3dg_3(0,0,0)
+			     + t3dg_2(1,0,1)*t3dg_3(1,0,0)
+			     + t3dg_2(1,0,2)*t3dg_3(2,0,0)
+			     + t3dg_2(1,1,0)*t3dg_3(0,0,1)
+			     + t3dg_2(1,1,1)*t3dg_3(1,0,1)
+			     + t3dg_2(1,1,2)*t3dg_3(2,0,1)
+			     + t3dg_2(1,2,0)*t3dg_3(0,0,2)
+			     + t3dg_2(1,2,1)*t3dg_3(1,0,2)
+			     + t3dg_2(1,2,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_2(1,0,0)*t3dg_3(0,1,0)
+			     + t3dg_2(1,0,1)*t3dg_3(1,1,0)
+			     + t3dg_2(1,0,2)*t3dg_3(2,1,0)
+			     + t3dg_2(1,1,0)*t3dg_3(0,1,1)
+			     + t3dg_2(1,1,1)*t3dg_3(1,1,1)
+			     + t3dg_2(1,1,2)*t3dg_3(2,1,1)
+			     + t3dg_2(1,2,0)*t3dg_3(0,1,2)
+			     + t3dg_2(1,2,1)*t3dg_3(1,1,2)
+			     + t3dg_2(1,2,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_2(1,0,0)*t3dg_3(0,2,0)
+			     + t3dg_2(1,0,1)*t3dg_3(1,2,0)
+			     + t3dg_2(1,0,2)*t3dg_3(2,2,0)
+			     + t3dg_2(1,1,0)*t3dg_3(0,2,1)
+			     + t3dg_2(1,1,1)*t3dg_3(1,2,1)
+			     + t3dg_2(1,1,2)*t3dg_3(2,2,1)
+			     + t3dg_2(1,2,0)*t3dg_3(0,2,2)
+			     + t3dg_2(1,2,1)*t3dg_3(1,2,2)
+			     + t3dg_2(1,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_2(2,0,0)*t3dg_3(0,0,0)
+			     + t3dg_2(2,0,1)*t3dg_3(1,0,0)
+			     + t3dg_2(2,0,2)*t3dg_3(2,0,0)
+			     + t3dg_2(2,1,0)*t3dg_3(0,0,1)
+			     + t3dg_2(2,1,1)*t3dg_3(1,0,1)
+			     + t3dg_2(2,1,2)*t3dg_3(2,0,1)
+			     + t3dg_2(2,2,0)*t3dg_3(0,0,2)
+			     + t3dg_2(2,2,1)*t3dg_3(1,0,2)
+			     + t3dg_2(2,2,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_2(2,0,0)*t3dg_3(0,1,0)
+			     + t3dg_2(2,0,1)*t3dg_3(1,1,0)
+			     + t3dg_2(2,0,2)*t3dg_3(2,1,0)
+			     + t3dg_2(2,1,0)*t3dg_3(0,1,1)
+			     + t3dg_2(2,1,1)*t3dg_3(1,1,1)
+			     + t3dg_2(2,1,2)*t3dg_3(2,1,1)
+			     + t3dg_2(2,2,0)*t3dg_3(0,1,2)
+			     + t3dg_2(2,2,1)*t3dg_3(1,1,2)
+			     + t3dg_2(2,2,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_2(2,0,0)*t3dg_3(0,2,0)
+			     + t3dg_2(2,0,1)*t3dg_3(1,2,0)
+			     + t3dg_2(2,0,2)*t3dg_3(2,2,0)
+			     + t3dg_2(2,1,0)*t3dg_3(0,2,1)
+			     + t3dg_2(2,1,1)*t3dg_3(1,2,1)
+			     + t3dg_2(2,1,2)*t3dg_3(2,2,1)
+			     + t3dg_2(2,2,0)*t3dg_3(0,2,2)
+			     + t3dg_2(2,2,1)*t3dg_3(1,2,2)
+			     + t3dg_2(2,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(k,l,j)(2,2)");
+
+  t2_1(i,l)=t3dg_2(k,l,j)*t3dg_3(i,j,k);
+  test_for_zero(t2_1(0,0) - (t3dg_3(0,0,0)*t3dg_2(0,0,0)
+			     + t3dg_3(0,0,1)*t3dg_2(1,0,0)
+			     + t3dg_3(0,0,2)*t3dg_2(2,0,0)
+			     + t3dg_3(0,1,0)*t3dg_2(0,0,1)
+			     + t3dg_3(0,1,1)*t3dg_2(1,0,1)
+			     + t3dg_3(0,1,2)*t3dg_2(2,0,1)
+			     + t3dg_3(0,2,0)*t3dg_2(0,0,2)
+			     + t3dg_3(0,2,1)*t3dg_2(1,0,2)
+			     + t3dg_3(0,2,2)*t3dg_2(2,0,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_3(0,0,0)*t3dg_2(0,1,0)
+			     + t3dg_3(0,0,1)*t3dg_2(1,1,0)
+			     + t3dg_3(0,0,2)*t3dg_2(2,1,0)
+			     + t3dg_3(0,1,0)*t3dg_2(0,1,1)
+			     + t3dg_3(0,1,1)*t3dg_2(1,1,1)
+			     + t3dg_3(0,1,2)*t3dg_2(2,1,1)
+			     + t3dg_3(0,2,0)*t3dg_2(0,1,2)
+			     + t3dg_3(0,2,1)*t3dg_2(1,1,2)
+			     + t3dg_3(0,2,2)*t3dg_2(2,1,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_3(0,0,0)*t3dg_2(0,2,0)
+			     + t3dg_3(0,0,1)*t3dg_2(1,2,0)
+			     + t3dg_3(0,0,2)*t3dg_2(2,2,0)
+			     + t3dg_3(0,1,0)*t3dg_2(0,2,1)
+			     + t3dg_3(0,1,1)*t3dg_2(1,2,1)
+			     + t3dg_3(0,1,2)*t3dg_2(2,2,1)
+			     + t3dg_3(0,2,0)*t3dg_2(0,2,2)
+			     + t3dg_3(0,2,1)*t3dg_2(1,2,2)
+			     + t3dg_3(0,2,2)*t3dg_2(2,2,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_3(1,0,0)*t3dg_2(0,0,0)
+			     + t3dg_3(1,0,1)*t3dg_2(1,0,0)
+			     + t3dg_3(1,0,2)*t3dg_2(2,0,0)
+			     + t3dg_3(1,1,0)*t3dg_2(0,0,1)
+			     + t3dg_3(1,1,1)*t3dg_2(1,0,1)
+			     + t3dg_3(1,1,2)*t3dg_2(2,0,1)
+			     + t3dg_3(1,2,0)*t3dg_2(0,0,2)
+			     + t3dg_3(1,2,1)*t3dg_2(1,0,2)
+			     + t3dg_3(1,2,2)*t3dg_2(2,0,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_3(1,0,0)*t3dg_2(0,1,0)
+			     + t3dg_3(1,0,1)*t3dg_2(1,1,0)
+			     + t3dg_3(1,0,2)*t3dg_2(2,1,0)
+			     + t3dg_3(1,1,0)*t3dg_2(0,1,1)
+			     + t3dg_3(1,1,1)*t3dg_2(1,1,1)
+			     + t3dg_3(1,1,2)*t3dg_2(2,1,1)
+			     + t3dg_3(1,2,0)*t3dg_2(0,1,2)
+			     + t3dg_3(1,2,1)*t3dg_2(1,1,2)
+			     + t3dg_3(1,2,2)*t3dg_2(2,1,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_3(1,0,0)*t3dg_2(0,2,0)
+			     + t3dg_3(1,0,1)*t3dg_2(1,2,0)
+			     + t3dg_3(1,0,2)*t3dg_2(2,2,0)
+			     + t3dg_3(1,1,0)*t3dg_2(0,2,1)
+			     + t3dg_3(1,1,1)*t3dg_2(1,2,1)
+			     + t3dg_3(1,1,2)*t3dg_2(2,2,1)
+			     + t3dg_3(1,2,0)*t3dg_2(0,2,2)
+			     + t3dg_3(1,2,1)*t3dg_2(1,2,2)
+			     + t3dg_3(1,2,2)*t3dg_2(2,2,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_3(2,0,0)*t3dg_2(0,0,0)
+			     + t3dg_3(2,0,1)*t3dg_2(1,0,0)
+			     + t3dg_3(2,0,2)*t3dg_2(2,0,0)
+			     + t3dg_3(2,1,0)*t3dg_2(0,0,1)
+			     + t3dg_3(2,1,1)*t3dg_2(1,0,1)
+			     + t3dg_3(2,1,2)*t3dg_2(2,0,1)
+			     + t3dg_3(2,2,0)*t3dg_2(0,0,2)
+			     + t3dg_3(2,2,1)*t3dg_2(1,0,2)
+			     + t3dg_3(2,2,2)*t3dg_2(2,0,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_3(2,0,0)*t3dg_2(0,1,0)
+			     + t3dg_3(2,0,1)*t3dg_2(1,1,0)
+			     + t3dg_3(2,0,2)*t3dg_2(2,1,0)
+			     + t3dg_3(2,1,0)*t3dg_2(0,1,1)
+			     + t3dg_3(2,1,1)*t3dg_2(1,1,1)
+			     + t3dg_3(2,1,2)*t3dg_2(2,1,1)
+			     + t3dg_3(2,2,0)*t3dg_2(0,1,2)
+			     + t3dg_3(2,2,1)*t3dg_2(1,1,2)
+			     + t3dg_3(2,2,2)*t3dg_2(2,1,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_3(2,0,0)*t3dg_2(0,2,0)
+			     + t3dg_3(2,0,1)*t3dg_2(1,2,0)
+			     + t3dg_3(2,0,2)*t3dg_2(2,2,0)
+			     + t3dg_3(2,1,0)*t3dg_2(0,2,1)
+			     + t3dg_3(2,1,1)*t3dg_2(1,2,1)
+			     + t3dg_3(2,1,2)*t3dg_2(2,2,1)
+			     + t3dg_3(2,2,0)*t3dg_2(0,2,2)
+			     + t3dg_3(2,2,1)*t3dg_2(1,2,2)
+			     + t3dg_3(2,2,2)*t3dg_2(2,2,2))
+		,"T3dg(k,l,j)*T3dg(i,j,k)(2,2)");
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgCIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgCIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,1288 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgCIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		  Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		  Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		  const Tensor2<double,3,3> &t2_3,
+		  Tensor2_symmetric<double,3> &t2s_1,
+		  const Tensor2_symmetric<double,3> &t2s_2,
+		  const Tensor2_symmetric<double,3> &t2s_3,
+		  Tensor3_dg<double,3,3> &t3dg_1,
+		  const Tensor3_dg<double,3,3> &t3dg_2,
+		  const Tensor3_dg<double,3,3> &t3dg_3,
+		  Tensor3_christof<double,3,3> &t3ch_1,
+		  const Tensor3_christof<double,3,3> &t3ch_2,
+		  const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,0,0)
+		- (t3dg_2(0,0,0)+t3dg_3(0,0,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,0,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,0,1)
+		- (t3dg_2(0,0,1)+t3dg_3(1,0,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,0,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,0,2)
+		- (t3dg_2(0,0,2)+t3dg_3(2,0,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,0,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,1,0)
+		- (t3dg_2(0,1,0)+t3dg_3(0,1,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,1,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,1,1)
+		- (t3dg_2(0,1,1)+t3dg_3(1,1,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,1,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,1,2)
+		- (t3dg_2(0,1,2)+t3dg_3(2,1,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,1,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,2,0)
+		- (t3dg_2(0,2,0)+t3dg_3(0,2,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,2,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,2,1)
+		- (t3dg_2(0,2,1)+t3dg_3(1,2,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,2,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(0,2,2)
+		- (t3dg_2(0,2,2)+t3dg_3(2,2,0))
+		,"T3dg(i,j,k)+T3(k,j,i)(0,2,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,0,0)
+		- (t3dg_2(1,0,0)+t3dg_3(0,0,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,0,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,0,1)
+		- (t3dg_2(1,0,1)+t3dg_3(1,0,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,0,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,0,2)
+		- (t3dg_2(1,0,2)+t3dg_3(2,0,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,0,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,1,0)
+		- (t3dg_2(1,1,0)+t3dg_3(0,1,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,1,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,1,1)
+		- (t3dg_2(1,1,1)+t3dg_3(1,1,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,1,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,1,2)
+		- (t3dg_2(1,1,2)+t3dg_3(2,1,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,1,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,2,0)
+		- (t3dg_2(1,2,0)+t3dg_3(0,2,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,2,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,2,1)
+		- (t3dg_2(1,2,1)+t3dg_3(1,2,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,2,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(1,2,2)
+		- (t3dg_2(1,2,2)+t3dg_3(2,2,1))
+		,"T3dg(i,j,k)+T3(k,j,i)(1,2,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,0,0)
+		- (t3dg_2(2,0,0)+t3dg_3(0,0,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,0,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,0,1)
+		- (t3dg_2(2,0,1)+t3dg_3(1,0,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,0,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,0,2)
+		- (t3dg_2(2,0,2)+t3dg_3(2,0,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,0,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,1,0)
+		- (t3dg_2(2,1,0)+t3dg_3(0,1,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,1,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,1,1)
+		- (t3dg_2(2,1,1)+t3dg_3(1,1,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,1,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,1,2)
+		- (t3dg_2(2,1,2)+t3dg_3(2,1,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,1,2)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,2,0)
+		- (t3dg_2(2,2,0)+t3dg_3(0,2,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,2,0)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,2,1)
+		- (t3dg_2(2,2,1)+t3dg_3(1,2,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,2,1)");
+  test_for_zero((t3dg_2(i,j,k)+t3dg_3(k,j,i))(2,2,2)
+		- (t3dg_2(2,2,2)+t3dg_3(2,2,2))
+		,"T3dg(i,j,k)+T3(k,j,i)(2,2,2)");
+
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,0,0)
+		- (t3dg_2(0,0,0)-t3dg_3(0,0,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,0,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,0,1)
+		- (t3dg_2(0,0,1)-t3dg_3(1,0,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,0,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,0,2)
+		- (t3dg_2(0,0,2)-t3dg_3(2,0,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,0,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,1,0)
+		- (t3dg_2(0,1,0)-t3dg_3(0,1,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,1,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,1,1)
+		- (t3dg_2(0,1,1)-t3dg_3(1,1,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,1,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,1,2)
+		- (t3dg_2(0,1,2)-t3dg_3(2,1,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,1,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,2,0)
+		- (t3dg_2(0,2,0)-t3dg_3(0,2,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,2,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,2,1)
+		- (t3dg_2(0,2,1)-t3dg_3(1,2,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,2,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(0,2,2)
+		- (t3dg_2(0,2,2)-t3dg_3(2,2,0))
+		,"T3dg(i,j,k)-T3(k,j,i)(0,2,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,0,0)
+		- (t3dg_2(1,0,0)-t3dg_3(0,0,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,0,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,0,1)
+		- (t3dg_2(1,0,1)-t3dg_3(1,0,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,0,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,0,2)
+		- (t3dg_2(1,0,2)-t3dg_3(2,0,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,0,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,1,0)
+		- (t3dg_2(1,1,0)-t3dg_3(0,1,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,1,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,1,1)
+		- (t3dg_2(1,1,1)-t3dg_3(1,1,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,1,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,1,2)
+		- (t3dg_2(1,1,2)-t3dg_3(2,1,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,1,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,2,0)
+		- (t3dg_2(1,2,0)-t3dg_3(0,2,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,2,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,2,1)
+		- (t3dg_2(1,2,1)-t3dg_3(1,2,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,2,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(1,2,2)
+		- (t3dg_2(1,2,2)-t3dg_3(2,2,1))
+		,"T3dg(i,j,k)-T3(k,j,i)(1,2,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,0,0)
+		- (t3dg_2(2,0,0)-t3dg_3(0,0,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,0,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,0,1)
+		- (t3dg_2(2,0,1)-t3dg_3(1,0,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,0,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,0,2)
+		- (t3dg_2(2,0,2)-t3dg_3(2,0,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,0,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,1,0)
+		- (t3dg_2(2,1,0)-t3dg_3(0,1,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,1,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,1,1)
+		- (t3dg_2(2,1,1)-t3dg_3(1,1,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,1,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,1,2)
+		- (t3dg_2(2,1,2)-t3dg_3(2,1,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,1,2)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,2,0)
+		- (t3dg_2(2,2,0)-t3dg_3(0,2,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,2,0)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,2,1)
+		- (t3dg_2(2,2,1)-t3dg_3(1,2,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,2,1)");
+  test_for_zero((t3dg_2(i,j,k)-t3dg_3(k,j,i))(2,2,2)
+		- (t3dg_2(2,2,2)-t3dg_3(2,2,2))
+		,"T3dg(i,j,k)-T3(k,j,i)(2,2,2)");
+
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,0,0)
+		- (t3dg_2(0,0,0)*t2_2(0,0)
+		   + t3dg_2(0,1,0)*t2_2(1,0)
+		   + t3dg_2(0,2,0)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(0,0,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,0,1)
+		- (t3dg_2(0,0,0)*t2_2(0,1)
+		   + t3dg_2(0,1,0)*t2_2(1,1)
+		   + t3dg_2(0,2,0)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(0,0,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,0,2)
+		- (t3dg_2(0,0,0)*t2_2(0,2)
+		   + t3dg_2(0,1,0)*t2_2(1,2)
+		   + t3dg_2(0,2,0)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(0,0,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,1,0)
+		- (t3dg_2(0,0,1)*t2_2(0,0)
+		   + t3dg_2(0,1,1)*t2_2(1,0)
+		   + t3dg_2(0,2,1)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(0,1,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,1,1)
+		- (t3dg_2(0,0,1)*t2_2(0,1)
+		   + t3dg_2(0,1,1)*t2_2(1,1)
+		   + t3dg_2(0,2,1)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(0,1,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,1,2)
+		- (t3dg_2(0,0,1)*t2_2(0,2)
+		   + t3dg_2(0,1,1)*t2_2(1,2)
+		   + t3dg_2(0,2,1)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(0,1,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,2,0)
+		- (t3dg_2(0,0,2)*t2_2(0,0)
+		   + t3dg_2(0,1,2)*t2_2(1,0)
+		   + t3dg_2(0,2,2)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(0,2,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,2,1)
+		- (t3dg_2(0,0,2)*t2_2(0,1)
+		   + t3dg_2(0,1,2)*t2_2(1,1)
+		   + t3dg_2(0,2,2)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(0,2,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(0,2,2)
+		- (t3dg_2(0,0,2)*t2_2(0,2)
+		   + t3dg_2(0,1,2)*t2_2(1,2)
+		   + t3dg_2(0,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(0,2,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,0,0)
+		- (t3dg_2(1,0,0)*t2_2(0,0)
+		   + t3dg_2(1,1,0)*t2_2(1,0)
+		   + t3dg_2(1,2,0)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(1,0,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,0,1)
+		- (t3dg_2(1,0,0)*t2_2(0,1)
+		   + t3dg_2(1,1,0)*t2_2(1,1)
+		   + t3dg_2(1,2,0)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(1,0,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,0,2)
+		- (t3dg_2(1,0,0)*t2_2(0,2)
+		   + t3dg_2(1,1,0)*t2_2(1,2)
+		   + t3dg_2(1,2,0)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(1,0,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,1,0)
+		- (t3dg_2(1,0,1)*t2_2(0,0)
+		   + t3dg_2(1,1,1)*t2_2(1,0)
+		   + t3dg_2(1,2,1)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(1,1,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,1,1)
+		- (t3dg_2(1,0,1)*t2_2(0,1)
+		   + t3dg_2(1,1,1)*t2_2(1,1)
+		   + t3dg_2(1,2,1)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(1,1,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,1,2)
+		- (t3dg_2(1,0,1)*t2_2(0,2)
+		   + t3dg_2(1,1,1)*t2_2(1,2)
+		   + t3dg_2(1,2,1)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(1,1,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,2,0)
+		- (t3dg_2(1,0,2)*t2_2(0,0)
+		   + t3dg_2(1,1,2)*t2_2(1,0)
+		   + t3dg_2(1,2,2)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(1,2,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,2,1)
+		- (t3dg_2(1,0,2)*t2_2(0,1)
+		   + t3dg_2(1,1,2)*t2_2(1,1)
+		   + t3dg_2(1,2,2)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(1,2,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(1,2,2)
+		- (t3dg_2(1,0,2)*t2_2(0,2)
+		   + t3dg_2(1,1,2)*t2_2(1,2)
+		   + t3dg_2(1,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(1,2,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,0,0)
+		- (t3dg_2(2,0,0)*t2_2(0,0)
+		   + t3dg_2(2,1,0)*t2_2(1,0)
+		   + t3dg_2(2,2,0)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(2,0,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,0,1)
+		- (t3dg_2(2,0,0)*t2_2(0,1)
+		   + t3dg_2(2,1,0)*t2_2(1,1)
+		   + t3dg_2(2,2,0)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(2,0,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,0,2)
+		- (t3dg_2(2,0,0)*t2_2(0,2)
+		   + t3dg_2(2,1,0)*t2_2(1,2)
+		   + t3dg_2(2,2,0)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(2,0,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,1,0)
+		- (t3dg_2(2,0,1)*t2_2(0,0)
+		   + t3dg_2(2,1,1)*t2_2(1,0)
+		   + t3dg_2(2,2,1)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(2,1,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,1,1)
+		- (t3dg_2(2,0,1)*t2_2(0,1)
+		   + t3dg_2(2,1,1)*t2_2(1,1)
+		   + t3dg_2(2,2,1)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(2,1,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,1,2)
+		- (t3dg_2(2,0,1)*t2_2(0,2)
+		   + t3dg_2(2,1,1)*t2_2(1,2)
+		   + t3dg_2(2,2,1)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(2,1,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,2,0)
+		- (t3dg_2(2,0,2)*t2_2(0,0)
+		   + t3dg_2(2,1,2)*t2_2(1,0)
+		   + t3dg_2(2,2,2)*t2_2(2,0))
+		,"T3dg(i,j,k)*T2(j,l)(2,2,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,2,1)
+		- (t3dg_2(2,0,2)*t2_2(0,1)
+		   + t3dg_2(2,1,2)*t2_2(1,1)
+		   + t3dg_2(2,2,2)*t2_2(2,1))
+		,"T3dg(i,j,k)*T2(j,l)(2,2,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2_2(j,l))(2,2,2)
+		- (t3dg_2(2,0,2)*t2_2(0,2)
+		   + t3dg_2(2,1,2)*t2_2(1,2)
+		   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,l)(2,2,2)");
+
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,0,0)
+		- (t3dg_3(0,0,0)*t2_2(0,0)
+		   + t3dg_3(0,1,0)*t2_2(0,1)
+		   + t3dg_3(0,2,0)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,0,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,0,1)
+		- (t3dg_3(0,0,0)*t2_2(1,0)
+		   + t3dg_3(0,1,0)*t2_2(1,1)
+		   + t3dg_3(0,2,0)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,0,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,0,2)
+		- (t3dg_3(0,0,0)*t2_2(2,0)
+		   + t3dg_3(0,1,0)*t2_2(2,1)
+		   + t3dg_3(0,2,0)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,0,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,1,0)
+		- (t3dg_3(0,0,1)*t2_2(0,0)
+		   + t3dg_3(0,1,1)*t2_2(0,1)
+		   + t3dg_3(0,2,1)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,1,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,1,1)
+		- (t3dg_3(0,0,1)*t2_2(1,0)
+		   + t3dg_3(0,1,1)*t2_2(1,1)
+		   + t3dg_3(0,2,1)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,1,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,1,2)
+		- (t3dg_3(0,0,1)*t2_2(2,0)
+		   + t3dg_3(0,1,1)*t2_2(2,1)
+		   + t3dg_3(0,2,1)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,1,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,2,0)
+		- (t3dg_3(0,0,2)*t2_2(0,0)
+		   + t3dg_3(0,1,2)*t2_2(0,1)
+		   + t3dg_3(0,2,2)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,2,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,2,1)
+		- (t3dg_3(0,0,2)*t2_2(1,0)
+		   + t3dg_3(0,1,2)*t2_2(1,1)
+		   + t3dg_3(0,2,2)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,2,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(0,2,2)
+		- (t3dg_3(0,0,2)*t2_2(2,0)
+		   + t3dg_3(0,1,2)*t2_2(2,1)
+		   + t3dg_3(0,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(0,2,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,0,0)
+		- (t3dg_3(1,0,0)*t2_2(0,0)
+		   + t3dg_3(1,1,0)*t2_2(0,1)
+		   + t3dg_3(1,2,0)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,0,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,0,1)
+		- (t3dg_3(1,0,0)*t2_2(1,0)
+		   + t3dg_3(1,1,0)*t2_2(1,1)
+		   + t3dg_3(1,2,0)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,0,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,0,2)
+		- (t3dg_3(1,0,0)*t2_2(2,0)
+		   + t3dg_3(1,1,0)*t2_2(2,1)
+		   + t3dg_3(1,2,0)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,0,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,1,0)
+		- (t3dg_3(1,0,1)*t2_2(0,0)
+		   + t3dg_3(1,1,1)*t2_2(0,1)
+		   + t3dg_3(1,2,1)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,1,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,1,1)
+		- (t3dg_3(1,0,1)*t2_2(1,0)
+		   + t3dg_3(1,1,1)*t2_2(1,1)
+		   + t3dg_3(1,2,1)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,1,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,1,2)
+		- (t3dg_3(1,0,1)*t2_2(2,0)
+		   + t3dg_3(1,1,1)*t2_2(2,1)
+		   + t3dg_3(1,2,1)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,1,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,2,0)
+		- (t3dg_3(1,0,2)*t2_2(0,0)
+		   + t3dg_3(1,1,2)*t2_2(0,1)
+		   + t3dg_3(1,2,2)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,2,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,2,1)
+		- (t3dg_3(1,0,2)*t2_2(1,0)
+		   + t3dg_3(1,1,2)*t2_2(1,1)
+		   + t3dg_3(1,2,2)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,2,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(1,2,2)
+		- (t3dg_3(1,0,2)*t2_2(2,0)
+		   + t3dg_3(1,1,2)*t2_2(2,1)
+		   + t3dg_3(1,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(1,2,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,0,0)
+		- (t3dg_3(2,0,0)*t2_2(0,0)
+		   + t3dg_3(2,1,0)*t2_2(0,1)
+		   + t3dg_3(2,2,0)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,0,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,0,1)
+		- (t3dg_3(2,0,0)*t2_2(1,0)
+		   + t3dg_3(2,1,0)*t2_2(1,1)
+		   + t3dg_3(2,2,0)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,0,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,0,2)
+		- (t3dg_3(2,0,0)*t2_2(2,0)
+		   + t3dg_3(2,1,0)*t2_2(2,1)
+		   + t3dg_3(2,2,0)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,0,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,1,0)
+		- (t3dg_3(2,0,1)*t2_2(0,0)
+		   + t3dg_3(2,1,1)*t2_2(0,1)
+		   + t3dg_3(2,2,1)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,1,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,1,1)
+		- (t3dg_3(2,0,1)*t2_2(1,0)
+		   + t3dg_3(2,1,1)*t2_2(1,1)
+		   + t3dg_3(2,2,1)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,1,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,1,2)
+		- (t3dg_3(2,0,1)*t2_2(2,0)
+		   + t3dg_3(2,1,1)*t2_2(2,1)
+		   + t3dg_3(2,2,1)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,1,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,2,0)
+		- (t3dg_3(2,0,2)*t2_2(0,0)
+		   + t3dg_3(2,1,2)*t2_2(0,1)
+		   + t3dg_3(2,2,2)*t2_2(0,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,2,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,2,1)
+		- (t3dg_3(2,0,2)*t2_2(1,0)
+		   + t3dg_3(2,1,2)*t2_2(1,1)
+		   + t3dg_3(2,2,2)*t2_2(1,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,2,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2_2(l,j))(2,2,2)
+		- (t3dg_3(2,0,2)*t2_2(2,0)
+		   + t3dg_3(2,1,2)*t2_2(2,1)
+		   + t3dg_3(2,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(l,j)(2,2,2)");
+
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,0,0)
+		- (t3dg_3(0,0,0)*t2_2(0,0)
+		   + t3dg_3(0,1,0)*t2_2(1,0)
+		   + t3dg_3(0,2,0)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(0,0,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,0,1)
+		- (t3dg_3(0,0,0)*t2_2(0,1)
+		   + t3dg_3(0,1,0)*t2_2(1,1)
+		   + t3dg_3(0,2,0)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(0,0,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,0,2)
+		- (t3dg_3(0,0,0)*t2_2(0,2)
+		   + t3dg_3(0,1,0)*t2_2(1,2)
+		   + t3dg_3(0,2,0)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(0,0,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,1,0)
+		- (t3dg_3(0,0,1)*t2_2(0,0)
+		   + t3dg_3(0,1,1)*t2_2(1,0)
+		   + t3dg_3(0,2,1)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(0,1,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,1,1)
+		- (t3dg_3(0,0,1)*t2_2(0,1)
+		   + t3dg_3(0,1,1)*t2_2(1,1)
+		   + t3dg_3(0,2,1)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(0,1,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,1,2)
+		- (t3dg_3(0,0,1)*t2_2(0,2)
+		   + t3dg_3(0,1,1)*t2_2(1,2)
+		   + t3dg_3(0,2,1)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(0,1,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,2,0)
+		- (t3dg_3(0,0,2)*t2_2(0,0)
+		   + t3dg_3(0,1,2)*t2_2(1,0)
+		   + t3dg_3(0,2,2)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(0,2,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,2,1)
+		- (t3dg_3(0,0,2)*t2_2(0,1)
+		   + t3dg_3(0,1,2)*t2_2(1,1)
+		   + t3dg_3(0,2,2)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(0,2,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(0,2,2)
+		- (t3dg_3(0,0,2)*t2_2(0,2)
+		   + t3dg_3(0,1,2)*t2_2(1,2)
+		   + t3dg_3(0,2,2)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(0,2,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,0,0)
+		- (t3dg_3(1,0,0)*t2_2(0,0)
+		   + t3dg_3(1,1,0)*t2_2(1,0)
+		   + t3dg_3(1,2,0)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(1,0,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,0,1)
+		- (t3dg_3(1,0,0)*t2_2(0,1)
+		   + t3dg_3(1,1,0)*t2_2(1,1)
+		   + t3dg_3(1,2,0)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(1,0,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,0,2)
+		- (t3dg_3(1,0,0)*t2_2(0,2)
+		   + t3dg_3(1,1,0)*t2_2(1,2)
+		   + t3dg_3(1,2,0)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(1,0,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,1,0)
+		- (t3dg_3(1,0,1)*t2_2(0,0)
+		   + t3dg_3(1,1,1)*t2_2(1,0)
+		   + t3dg_3(1,2,1)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(1,1,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,1,1)
+		- (t3dg_3(1,0,1)*t2_2(0,1)
+		   + t3dg_3(1,1,1)*t2_2(1,1)
+		   + t3dg_3(1,2,1)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(1,1,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,1,2)
+		- (t3dg_3(1,0,1)*t2_2(0,2)
+		   + t3dg_3(1,1,1)*t2_2(1,2)
+		   + t3dg_3(1,2,1)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(1,1,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,2,0)
+		- (t3dg_3(1,0,2)*t2_2(0,0)
+		   + t3dg_3(1,1,2)*t2_2(1,0)
+		   + t3dg_3(1,2,2)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(1,2,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,2,1)
+		- (t3dg_3(1,0,2)*t2_2(0,1)
+		   + t3dg_3(1,1,2)*t2_2(1,1)
+		   + t3dg_3(1,2,2)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(1,2,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(1,2,2)
+		- (t3dg_3(1,0,2)*t2_2(0,2)
+		   + t3dg_3(1,1,2)*t2_2(1,2)
+		   + t3dg_3(1,2,2)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(1,2,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,0,0)
+		- (t3dg_3(2,0,0)*t2_2(0,0)
+		   + t3dg_3(2,1,0)*t2_2(1,0)
+		   + t3dg_3(2,2,0)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(2,0,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,0,1)
+		- (t3dg_3(2,0,0)*t2_2(0,1)
+		   + t3dg_3(2,1,0)*t2_2(1,1)
+		   + t3dg_3(2,2,0)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(2,0,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,0,2)
+		- (t3dg_3(2,0,0)*t2_2(0,2)
+		   + t3dg_3(2,1,0)*t2_2(1,2)
+		   + t3dg_3(2,2,0)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(2,0,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,1,0)
+		- (t3dg_3(2,0,1)*t2_2(0,0)
+		   + t3dg_3(2,1,1)*t2_2(1,0)
+		   + t3dg_3(2,2,1)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(2,1,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,1,1)
+		- (t3dg_3(2,0,1)*t2_2(0,1)
+		   + t3dg_3(2,1,1)*t2_2(1,1)
+		   + t3dg_3(2,2,1)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(2,1,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,1,2)
+		- (t3dg_3(2,0,1)*t2_2(0,2)
+		   + t3dg_3(2,1,1)*t2_2(1,2)
+		   + t3dg_3(2,2,1)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(2,1,2)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,2,0)
+		- (t3dg_3(2,0,2)*t2_2(0,0)
+		   + t3dg_3(2,1,2)*t2_2(1,0)
+		   + t3dg_3(2,2,2)*t2_2(2,0))
+		,"T2(j,l)*T3dg(i,j,k)(2,2,0)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,2,1)
+		- (t3dg_3(2,0,2)*t2_2(0,1)
+		   + t3dg_3(2,1,2)*t2_2(1,1)
+		   + t3dg_3(2,2,2)*t2_2(2,1))
+		,"T2(j,l)*T3dg(i,j,k)(2,2,1)");
+  test_for_zero((t2_2(j,l)*t3dg_3(i,j,k))(2,2,2)
+		- (t3dg_3(2,0,2)*t2_2(0,2)
+		   + t3dg_3(2,1,2)*t2_2(1,2)
+		   + t3dg_3(2,2,2)*t2_2(2,2))
+		,"T2(j,l)*T3dg(i,j,k)(2,2,2)");
+
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,0,0)
+		- (t3dg_3(0,0,0)*t2_2(0,0)
+		   + t3dg_3(0,1,0)*t2_2(0,1)
+		   + t3dg_3(0,2,0)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,0,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,0,1)
+		- (t3dg_3(0,0,0)*t2_2(1,0)
+		   + t3dg_3(0,1,0)*t2_2(1,1)
+		   + t3dg_3(0,2,0)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,0,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,0,2)
+		- (t3dg_3(0,0,0)*t2_2(2,0)
+		   + t3dg_3(0,1,0)*t2_2(2,1)
+		   + t3dg_3(0,2,0)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,0,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,1,0)
+		- (t3dg_3(0,0,1)*t2_2(0,0)
+		   + t3dg_3(0,1,1)*t2_2(0,1)
+		   + t3dg_3(0,2,1)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,1,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,1,1)
+		- (t3dg_3(0,0,1)*t2_2(1,0)
+		   + t3dg_3(0,1,1)*t2_2(1,1)
+		   + t3dg_3(0,2,1)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,1,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,1,2)
+		- (t3dg_3(0,0,1)*t2_2(2,0)
+		   + t3dg_3(0,1,1)*t2_2(2,1)
+		   + t3dg_3(0,2,1)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,1,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,2,0)
+		- (t3dg_3(0,0,2)*t2_2(0,0)
+		   + t3dg_3(0,1,2)*t2_2(0,1)
+		   + t3dg_3(0,2,2)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,2,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,2,1)
+		- (t3dg_3(0,0,2)*t2_2(1,0)
+		   + t3dg_3(0,1,2)*t2_2(1,1)
+		   + t3dg_3(0,2,2)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,2,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(0,2,2)
+		- (t3dg_3(0,0,2)*t2_2(2,0)
+		   + t3dg_3(0,1,2)*t2_2(2,1)
+		   + t3dg_3(0,2,2)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(0,2,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,0,0)
+		- (t3dg_3(1,0,0)*t2_2(0,0)
+		   + t3dg_3(1,1,0)*t2_2(0,1)
+		   + t3dg_3(1,2,0)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,0,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,0,1)
+		- (t3dg_3(1,0,0)*t2_2(1,0)
+		   + t3dg_3(1,1,0)*t2_2(1,1)
+		   + t3dg_3(1,2,0)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,0,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,0,2)
+		- (t3dg_3(1,0,0)*t2_2(2,0)
+		   + t3dg_3(1,1,0)*t2_2(2,1)
+		   + t3dg_3(1,2,0)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,0,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,1,0)
+		- (t3dg_3(1,0,1)*t2_2(0,0)
+		   + t3dg_3(1,1,1)*t2_2(0,1)
+		   + t3dg_3(1,2,1)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,1,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,1,1)
+		- (t3dg_3(1,0,1)*t2_2(1,0)
+		   + t3dg_3(1,1,1)*t2_2(1,1)
+		   + t3dg_3(1,2,1)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,1,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,1,2)
+		- (t3dg_3(1,0,1)*t2_2(2,0)
+		   + t3dg_3(1,1,1)*t2_2(2,1)
+		   + t3dg_3(1,2,1)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,1,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,2,0)
+		- (t3dg_3(1,0,2)*t2_2(0,0)
+		   + t3dg_3(1,1,2)*t2_2(0,1)
+		   + t3dg_3(1,2,2)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,2,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,2,1)
+		- (t3dg_3(1,0,2)*t2_2(1,0)
+		   + t3dg_3(1,1,2)*t2_2(1,1)
+		   + t3dg_3(1,2,2)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,2,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(1,2,2)
+		- (t3dg_3(1,0,2)*t2_2(2,0)
+		   + t3dg_3(1,1,2)*t2_2(2,1)
+		   + t3dg_3(1,2,2)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(1,2,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,0,0)
+		- (t3dg_3(2,0,0)*t2_2(0,0)
+		   + t3dg_3(2,1,0)*t2_2(0,1)
+		   + t3dg_3(2,2,0)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,0,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,0,1)
+		- (t3dg_3(2,0,0)*t2_2(1,0)
+		   + t3dg_3(2,1,0)*t2_2(1,1)
+		   + t3dg_3(2,2,0)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,0,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,0,2)
+		- (t3dg_3(2,0,0)*t2_2(2,0)
+		   + t3dg_3(2,1,0)*t2_2(2,1)
+		   + t3dg_3(2,2,0)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,0,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,1,0)
+		- (t3dg_3(2,0,1)*t2_2(0,0)
+		   + t3dg_3(2,1,1)*t2_2(0,1)
+		   + t3dg_3(2,2,1)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,1,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,1,1)
+		- (t3dg_3(2,0,1)*t2_2(1,0)
+		   + t3dg_3(2,1,1)*t2_2(1,1)
+		   + t3dg_3(2,2,1)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,1,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,1,2)
+		- (t3dg_3(2,0,1)*t2_2(2,0)
+		   + t3dg_3(2,1,1)*t2_2(2,1)
+		   + t3dg_3(2,2,1)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,1,2)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,2,0)
+		- (t3dg_3(2,0,2)*t2_2(0,0)
+		   + t3dg_3(2,1,2)*t2_2(0,1)
+		   + t3dg_3(2,2,2)*t2_2(0,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,2,0)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,2,1)
+		- (t3dg_3(2,0,2)*t2_2(1,0)
+		   + t3dg_3(2,1,2)*t2_2(1,1)
+		   + t3dg_3(2,2,2)*t2_2(1,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,2,1)");
+  test_for_zero((t2_2(l,j)*t3dg_3(i,j,k))(2,2,2)
+		- (t3dg_3(2,0,2)*t2_2(2,0)
+		   + t3dg_3(2,1,2)*t2_2(2,1)
+		   + t3dg_3(2,2,2)*t2_2(2,2))
+		,"T2(l,j)*T3dg(i,j,k)(2,2,2)");
+
+
+
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,0,0)
+		- (t3dg_2(0,0,0)*t2s_2(0,0)
+		   + t3dg_2(0,1,0)*t2s_2(1,0)
+		   + t3dg_2(0,2,0)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(0,0,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,0,1)
+		- (t3dg_2(0,0,0)*t2s_2(0,1)
+		   + t3dg_2(0,1,0)*t2s_2(1,1)
+		   + t3dg_2(0,2,0)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(0,0,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,0,2)
+		- (t3dg_2(0,0,0)*t2s_2(0,2)
+		   + t3dg_2(0,1,0)*t2s_2(1,2)
+		   + t3dg_2(0,2,0)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(0,0,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,1,0)
+		- (t3dg_2(0,0,1)*t2s_2(0,0)
+		   + t3dg_2(0,1,1)*t2s_2(1,0)
+		   + t3dg_2(0,2,1)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(0,1,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,1,1)
+		- (t3dg_2(0,0,1)*t2s_2(0,1)
+		   + t3dg_2(0,1,1)*t2s_2(1,1)
+		   + t3dg_2(0,2,1)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(0,1,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,1,2)
+		- (t3dg_2(0,0,1)*t2s_2(0,2)
+		   + t3dg_2(0,1,1)*t2s_2(1,2)
+		   + t3dg_2(0,2,1)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(0,1,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,2,0)
+		- (t3dg_2(0,0,2)*t2s_2(0,0)
+		   + t3dg_2(0,1,2)*t2s_2(1,0)
+		   + t3dg_2(0,2,2)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(0,2,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,2,1)
+		- (t3dg_2(0,0,2)*t2s_2(0,1)
+		   + t3dg_2(0,1,2)*t2s_2(1,1)
+		   + t3dg_2(0,2,2)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(0,2,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(0,2,2)
+		- (t3dg_2(0,0,2)*t2s_2(0,2)
+		   + t3dg_2(0,1,2)*t2s_2(1,2)
+		   + t3dg_2(0,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(0,2,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,0,0)
+		- (t3dg_2(1,0,0)*t2s_2(0,0)
+		   + t3dg_2(1,1,0)*t2s_2(1,0)
+		   + t3dg_2(1,2,0)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(1,0,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,0,1)
+		- (t3dg_2(1,0,0)*t2s_2(0,1)
+		   + t3dg_2(1,1,0)*t2s_2(1,1)
+		   + t3dg_2(1,2,0)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(1,0,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,0,2)
+		- (t3dg_2(1,0,0)*t2s_2(0,2)
+		   + t3dg_2(1,1,0)*t2s_2(1,2)
+		   + t3dg_2(1,2,0)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(1,0,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,1,0)
+		- (t3dg_2(1,0,1)*t2s_2(0,0)
+		   + t3dg_2(1,1,1)*t2s_2(1,0)
+		   + t3dg_2(1,2,1)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(1,1,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,1,1)
+		- (t3dg_2(1,0,1)*t2s_2(0,1)
+		   + t3dg_2(1,1,1)*t2s_2(1,1)
+		   + t3dg_2(1,2,1)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(1,1,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,1,2)
+		- (t3dg_2(1,0,1)*t2s_2(0,2)
+		   + t3dg_2(1,1,1)*t2s_2(1,2)
+		   + t3dg_2(1,2,1)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(1,1,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,2,0)
+		- (t3dg_2(1,0,2)*t2s_2(0,0)
+		   + t3dg_2(1,1,2)*t2s_2(1,0)
+		   + t3dg_2(1,2,2)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(1,2,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,2,1)
+		- (t3dg_2(1,0,2)*t2s_2(0,1)
+		   + t3dg_2(1,1,2)*t2s_2(1,1)
+		   + t3dg_2(1,2,2)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(1,2,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(1,2,2)
+		- (t3dg_2(1,0,2)*t2s_2(0,2)
+		   + t3dg_2(1,1,2)*t2s_2(1,2)
+		   + t3dg_2(1,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(1,2,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,0,0)
+		- (t3dg_2(2,0,0)*t2s_2(0,0)
+		   + t3dg_2(2,1,0)*t2s_2(1,0)
+		   + t3dg_2(2,2,0)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(2,0,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,0,1)
+		- (t3dg_2(2,0,0)*t2s_2(0,1)
+		   + t3dg_2(2,1,0)*t2s_2(1,1)
+		   + t3dg_2(2,2,0)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(2,0,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,0,2)
+		- (t3dg_2(2,0,0)*t2s_2(0,2)
+		   + t3dg_2(2,1,0)*t2s_2(1,2)
+		   + t3dg_2(2,2,0)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(2,0,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,1,0)
+		- (t3dg_2(2,0,1)*t2s_2(0,0)
+		   + t3dg_2(2,1,1)*t2s_2(1,0)
+		   + t3dg_2(2,2,1)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(2,1,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,1,1)
+		- (t3dg_2(2,0,1)*t2s_2(0,1)
+		   + t3dg_2(2,1,1)*t2s_2(1,1)
+		   + t3dg_2(2,2,1)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(2,1,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,1,2)
+		- (t3dg_2(2,0,1)*t2s_2(0,2)
+		   + t3dg_2(2,1,1)*t2s_2(1,2)
+		   + t3dg_2(2,2,1)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(2,1,2)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,2,0)
+		- (t3dg_2(2,0,2)*t2s_2(0,0)
+		   + t3dg_2(2,1,2)*t2s_2(1,0)
+		   + t3dg_2(2,2,2)*t2s_2(2,0))
+		,"T3dg(i,j,k)*T2s(j,l)(2,2,0)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,2,1)
+		- (t3dg_2(2,0,2)*t2s_2(0,1)
+		   + t3dg_2(2,1,2)*t2s_2(1,1)
+		   + t3dg_2(2,2,2)*t2s_2(2,1))
+		,"T3dg(i,j,k)*T2s(j,l)(2,2,1)");
+  test_for_zero((t3dg_2(i,j,k)*t2s_2(j,l))(2,2,2)
+		- (t3dg_2(2,0,2)*t2s_2(0,2)
+		   + t3dg_2(2,1,2)*t2s_2(1,2)
+		   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,l)(2,2,2)");
+
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,0,0)
+		- (t3dg_3(0,0,0)*t2s_2(0,0)
+		   + t3dg_3(0,1,0)*t2s_2(0,1)
+		   + t3dg_3(0,2,0)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,0,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,0,1)
+		- (t3dg_3(0,0,0)*t2s_2(1,0)
+		   + t3dg_3(0,1,0)*t2s_2(1,1)
+		   + t3dg_3(0,2,0)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,0,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,0,2)
+		- (t3dg_3(0,0,0)*t2s_2(2,0)
+		   + t3dg_3(0,1,0)*t2s_2(2,1)
+		   + t3dg_3(0,2,0)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,0,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,1,0)
+		- (t3dg_3(0,0,1)*t2s_2(0,0)
+		   + t3dg_3(0,1,1)*t2s_2(0,1)
+		   + t3dg_3(0,2,1)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,1,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,1,1)
+		- (t3dg_3(0,0,1)*t2s_2(1,0)
+		   + t3dg_3(0,1,1)*t2s_2(1,1)
+		   + t3dg_3(0,2,1)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,1,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,1,2)
+		- (t3dg_3(0,0,1)*t2s_2(2,0)
+		   + t3dg_3(0,1,1)*t2s_2(2,1)
+		   + t3dg_3(0,2,1)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,1,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,2,0)
+		- (t3dg_3(0,0,2)*t2s_2(0,0)
+		   + t3dg_3(0,1,2)*t2s_2(0,1)
+		   + t3dg_3(0,2,2)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,2,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,2,1)
+		- (t3dg_3(0,0,2)*t2s_2(1,0)
+		   + t3dg_3(0,1,2)*t2s_2(1,1)
+		   + t3dg_3(0,2,2)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,2,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(0,2,2)
+		- (t3dg_3(0,0,2)*t2s_2(2,0)
+		   + t3dg_3(0,1,2)*t2s_2(2,1)
+		   + t3dg_3(0,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(0,2,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,0,0)
+		- (t3dg_3(1,0,0)*t2s_2(0,0)
+		   + t3dg_3(1,1,0)*t2s_2(0,1)
+		   + t3dg_3(1,2,0)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,0,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,0,1)
+		- (t3dg_3(1,0,0)*t2s_2(1,0)
+		   + t3dg_3(1,1,0)*t2s_2(1,1)
+		   + t3dg_3(1,2,0)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,0,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,0,2)
+		- (t3dg_3(1,0,0)*t2s_2(2,0)
+		   + t3dg_3(1,1,0)*t2s_2(2,1)
+		   + t3dg_3(1,2,0)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,0,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,1,0)
+		- (t3dg_3(1,0,1)*t2s_2(0,0)
+		   + t3dg_3(1,1,1)*t2s_2(0,1)
+		   + t3dg_3(1,2,1)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,1,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,1,1)
+		- (t3dg_3(1,0,1)*t2s_2(1,0)
+		   + t3dg_3(1,1,1)*t2s_2(1,1)
+		   + t3dg_3(1,2,1)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,1,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,1,2)
+		- (t3dg_3(1,0,1)*t2s_2(2,0)
+		   + t3dg_3(1,1,1)*t2s_2(2,1)
+		   + t3dg_3(1,2,1)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,1,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,2,0)
+		- (t3dg_3(1,0,2)*t2s_2(0,0)
+		   + t3dg_3(1,1,2)*t2s_2(0,1)
+		   + t3dg_3(1,2,2)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,2,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,2,1)
+		- (t3dg_3(1,0,2)*t2s_2(1,0)
+		   + t3dg_3(1,1,2)*t2s_2(1,1)
+		   + t3dg_3(1,2,2)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,2,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(1,2,2)
+		- (t3dg_3(1,0,2)*t2s_2(2,0)
+		   + t3dg_3(1,1,2)*t2s_2(2,1)
+		   + t3dg_3(1,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(1,2,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,0,0)
+		- (t3dg_3(2,0,0)*t2s_2(0,0)
+		   + t3dg_3(2,1,0)*t2s_2(0,1)
+		   + t3dg_3(2,2,0)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,0,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,0,1)
+		- (t3dg_3(2,0,0)*t2s_2(1,0)
+		   + t3dg_3(2,1,0)*t2s_2(1,1)
+		   + t3dg_3(2,2,0)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,0,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,0,2)
+		- (t3dg_3(2,0,0)*t2s_2(2,0)
+		   + t3dg_3(2,1,0)*t2s_2(2,1)
+		   + t3dg_3(2,2,0)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,0,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,1,0)
+		- (t3dg_3(2,0,1)*t2s_2(0,0)
+		   + t3dg_3(2,1,1)*t2s_2(0,1)
+		   + t3dg_3(2,2,1)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,1,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,1,1)
+		- (t3dg_3(2,0,1)*t2s_2(1,0)
+		   + t3dg_3(2,1,1)*t2s_2(1,1)
+		   + t3dg_3(2,2,1)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,1,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,1,2)
+		- (t3dg_3(2,0,1)*t2s_2(2,0)
+		   + t3dg_3(2,1,1)*t2s_2(2,1)
+		   + t3dg_3(2,2,1)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,1,2)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,2,0)
+		- (t3dg_3(2,0,2)*t2s_2(0,0)
+		   + t3dg_3(2,1,2)*t2s_2(0,1)
+		   + t3dg_3(2,2,2)*t2s_2(0,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,2,0)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,2,1)
+		- (t3dg_3(2,0,2)*t2s_2(1,0)
+		   + t3dg_3(2,1,2)*t2s_2(1,1)
+		   + t3dg_3(2,2,2)*t2s_2(1,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,2,1)");
+  test_for_zero((t3dg_3(i,j,k)*t2s_2(l,j))(2,2,2)
+		- (t3dg_3(2,0,2)*t2s_2(2,0)
+		   + t3dg_3(2,1,2)*t2s_2(2,1)
+		   + t3dg_3(2,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(l,j)(2,2,2)");
+
+
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,0,0)
+		- (t3dg_3(0,0,0)*t2s_2(0,0)
+		   + t3dg_3(0,1,0)*t2s_2(1,0)
+		   + t3dg_3(0,2,0)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(0,0,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,0,1)
+		- (t3dg_3(0,0,0)*t2s_2(0,1)
+		   + t3dg_3(0,1,0)*t2s_2(1,1)
+		   + t3dg_3(0,2,0)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(0,0,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,0,2)
+		- (t3dg_3(0,0,0)*t2s_2(0,2)
+		   + t3dg_3(0,1,0)*t2s_2(1,2)
+		   + t3dg_3(0,2,0)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(0,0,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,1,0)
+		- (t3dg_3(0,0,1)*t2s_2(0,0)
+		   + t3dg_3(0,1,1)*t2s_2(1,0)
+		   + t3dg_3(0,2,1)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(0,1,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,1,1)
+		- (t3dg_3(0,0,1)*t2s_2(0,1)
+		   + t3dg_3(0,1,1)*t2s_2(1,1)
+		   + t3dg_3(0,2,1)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(0,1,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,1,2)
+		- (t3dg_3(0,0,1)*t2s_2(0,2)
+		   + t3dg_3(0,1,1)*t2s_2(1,2)
+		   + t3dg_3(0,2,1)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(0,1,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,2,0)
+		- (t3dg_3(0,0,2)*t2s_2(0,0)
+		   + t3dg_3(0,1,2)*t2s_2(1,0)
+		   + t3dg_3(0,2,2)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(0,2,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,2,1)
+		- (t3dg_3(0,0,2)*t2s_2(0,1)
+		   + t3dg_3(0,1,2)*t2s_2(1,1)
+		   + t3dg_3(0,2,2)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(0,2,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(0,2,2)
+		- (t3dg_3(0,0,2)*t2s_2(0,2)
+		   + t3dg_3(0,1,2)*t2s_2(1,2)
+		   + t3dg_3(0,2,2)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(0,2,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,0,0)
+		- (t3dg_3(1,0,0)*t2s_2(0,0)
+		   + t3dg_3(1,1,0)*t2s_2(1,0)
+		   + t3dg_3(1,2,0)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(1,0,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,0,1)
+		- (t3dg_3(1,0,0)*t2s_2(0,1)
+		   + t3dg_3(1,1,0)*t2s_2(1,1)
+		   + t3dg_3(1,2,0)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(1,0,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,0,2)
+		- (t3dg_3(1,0,0)*t2s_2(0,2)
+		   + t3dg_3(1,1,0)*t2s_2(1,2)
+		   + t3dg_3(1,2,0)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(1,0,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,1,0)
+		- (t3dg_3(1,0,1)*t2s_2(0,0)
+		   + t3dg_3(1,1,1)*t2s_2(1,0)
+		   + t3dg_3(1,2,1)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(1,1,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,1,1)
+		- (t3dg_3(1,0,1)*t2s_2(0,1)
+		   + t3dg_3(1,1,1)*t2s_2(1,1)
+		   + t3dg_3(1,2,1)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(1,1,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,1,2)
+		- (t3dg_3(1,0,1)*t2s_2(0,2)
+		   + t3dg_3(1,1,1)*t2s_2(1,2)
+		   + t3dg_3(1,2,1)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(1,1,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,2,0)
+		- (t3dg_3(1,0,2)*t2s_2(0,0)
+		   + t3dg_3(1,1,2)*t2s_2(1,0)
+		   + t3dg_3(1,2,2)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(1,2,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,2,1)
+		- (t3dg_3(1,0,2)*t2s_2(0,1)
+		   + t3dg_3(1,1,2)*t2s_2(1,1)
+		   + t3dg_3(1,2,2)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(1,2,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(1,2,2)
+		- (t3dg_3(1,0,2)*t2s_2(0,2)
+		   + t3dg_3(1,1,2)*t2s_2(1,2)
+		   + t3dg_3(1,2,2)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(1,2,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,0,0)
+		- (t3dg_3(2,0,0)*t2s_2(0,0)
+		   + t3dg_3(2,1,0)*t2s_2(1,0)
+		   + t3dg_3(2,2,0)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(2,0,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,0,1)
+		- (t3dg_3(2,0,0)*t2s_2(0,1)
+		   + t3dg_3(2,1,0)*t2s_2(1,1)
+		   + t3dg_3(2,2,0)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(2,0,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,0,2)
+		- (t3dg_3(2,0,0)*t2s_2(0,2)
+		   + t3dg_3(2,1,0)*t2s_2(1,2)
+		   + t3dg_3(2,2,0)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(2,0,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,1,0)
+		- (t3dg_3(2,0,1)*t2s_2(0,0)
+		   + t3dg_3(2,1,1)*t2s_2(1,0)
+		   + t3dg_3(2,2,1)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(2,1,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,1,1)
+		- (t3dg_3(2,0,1)*t2s_2(0,1)
+		   + t3dg_3(2,1,1)*t2s_2(1,1)
+		   + t3dg_3(2,2,1)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(2,1,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,1,2)
+		- (t3dg_3(2,0,1)*t2s_2(0,2)
+		   + t3dg_3(2,1,1)*t2s_2(1,2)
+		   + t3dg_3(2,2,1)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(2,1,2)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,2,0)
+		- (t3dg_3(2,0,2)*t2s_2(0,0)
+		   + t3dg_3(2,1,2)*t2s_2(1,0)
+		   + t3dg_3(2,2,2)*t2s_2(2,0))
+		,"T2s(j,l)*T3dg(i,j,k)(2,2,0)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,2,1)
+		- (t3dg_3(2,0,2)*t2s_2(0,1)
+		   + t3dg_3(2,1,2)*t2s_2(1,1)
+		   + t3dg_3(2,2,2)*t2s_2(2,1))
+		,"T2s(j,l)*T3dg(i,j,k)(2,2,1)");
+  test_for_zero((t2s_2(j,l)*t3dg_3(i,j,k))(2,2,2)
+		- (t3dg_3(2,0,2)*t2s_2(0,2)
+		   + t3dg_3(2,1,2)*t2s_2(1,2)
+		   + t3dg_3(2,2,2)*t2s_2(2,2))
+		,"T2s(j,l)*T3dg(i,j,k)(2,2,2)");
+
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,0,0)
+		- (t3dg_3(0,0,0)*t2s_2(0,0)
+		   + t3dg_3(0,1,0)*t2s_2(0,1)
+		   + t3dg_3(0,2,0)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,0,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,0,1)
+		- (t3dg_3(0,0,0)*t2s_2(1,0)
+		   + t3dg_3(0,1,0)*t2s_2(1,1)
+		   + t3dg_3(0,2,0)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,0,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,0,2)
+		- (t3dg_3(0,0,0)*t2s_2(2,0)
+		   + t3dg_3(0,1,0)*t2s_2(2,1)
+		   + t3dg_3(0,2,0)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,0,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,1,0)
+		- (t3dg_3(0,0,1)*t2s_2(0,0)
+		   + t3dg_3(0,1,1)*t2s_2(0,1)
+		   + t3dg_3(0,2,1)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,1,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,1,1)
+		- (t3dg_3(0,0,1)*t2s_2(1,0)
+		   + t3dg_3(0,1,1)*t2s_2(1,1)
+		   + t3dg_3(0,2,1)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,1,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,1,2)
+		- (t3dg_3(0,0,1)*t2s_2(2,0)
+		   + t3dg_3(0,1,1)*t2s_2(2,1)
+		   + t3dg_3(0,2,1)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,1,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,2,0)
+		- (t3dg_3(0,0,2)*t2s_2(0,0)
+		   + t3dg_3(0,1,2)*t2s_2(0,1)
+		   + t3dg_3(0,2,2)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,2,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,2,1)
+		- (t3dg_3(0,0,2)*t2s_2(1,0)
+		   + t3dg_3(0,1,2)*t2s_2(1,1)
+		   + t3dg_3(0,2,2)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,2,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(0,2,2)
+		- (t3dg_3(0,0,2)*t2s_2(2,0)
+		   + t3dg_3(0,1,2)*t2s_2(2,1)
+		   + t3dg_3(0,2,2)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(0,2,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,0,0)
+		- (t3dg_3(1,0,0)*t2s_2(0,0)
+		   + t3dg_3(1,1,0)*t2s_2(0,1)
+		   + t3dg_3(1,2,0)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,0,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,0,1)
+		- (t3dg_3(1,0,0)*t2s_2(1,0)
+		   + t3dg_3(1,1,0)*t2s_2(1,1)
+		   + t3dg_3(1,2,0)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,0,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,0,2)
+		- (t3dg_3(1,0,0)*t2s_2(2,0)
+		   + t3dg_3(1,1,0)*t2s_2(2,1)
+		   + t3dg_3(1,2,0)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,0,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,1,0)
+		- (t3dg_3(1,0,1)*t2s_2(0,0)
+		   + t3dg_3(1,1,1)*t2s_2(0,1)
+		   + t3dg_3(1,2,1)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,1,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,1,1)
+		- (t3dg_3(1,0,1)*t2s_2(1,0)
+		   + t3dg_3(1,1,1)*t2s_2(1,1)
+		   + t3dg_3(1,2,1)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,1,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,1,2)
+		- (t3dg_3(1,0,1)*t2s_2(2,0)
+		   + t3dg_3(1,1,1)*t2s_2(2,1)
+		   + t3dg_3(1,2,1)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,1,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,2,0)
+		- (t3dg_3(1,0,2)*t2s_2(0,0)
+		   + t3dg_3(1,1,2)*t2s_2(0,1)
+		   + t3dg_3(1,2,2)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,2,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,2,1)
+		- (t3dg_3(1,0,2)*t2s_2(1,0)
+		   + t3dg_3(1,1,2)*t2s_2(1,1)
+		   + t3dg_3(1,2,2)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,2,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(1,2,2)
+		- (t3dg_3(1,0,2)*t2s_2(2,0)
+		   + t3dg_3(1,1,2)*t2s_2(2,1)
+		   + t3dg_3(1,2,2)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(1,2,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,0,0)
+		- (t3dg_3(2,0,0)*t2s_2(0,0)
+		   + t3dg_3(2,1,0)*t2s_2(0,1)
+		   + t3dg_3(2,2,0)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,0,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,0,1)
+		- (t3dg_3(2,0,0)*t2s_2(1,0)
+		   + t3dg_3(2,1,0)*t2s_2(1,1)
+		   + t3dg_3(2,2,0)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,0,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,0,2)
+		- (t3dg_3(2,0,0)*t2s_2(2,0)
+		   + t3dg_3(2,1,0)*t2s_2(2,1)
+		   + t3dg_3(2,2,0)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,0,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,1,0)
+		- (t3dg_3(2,0,1)*t2s_2(0,0)
+		   + t3dg_3(2,1,1)*t2s_2(0,1)
+		   + t3dg_3(2,2,1)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,1,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,1,1)
+		- (t3dg_3(2,0,1)*t2s_2(1,0)
+		   + t3dg_3(2,1,1)*t2s_2(1,1)
+		   + t3dg_3(2,2,1)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,1,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,1,2)
+		- (t3dg_3(2,0,1)*t2s_2(2,0)
+		   + t3dg_3(2,1,1)*t2s_2(2,1)
+		   + t3dg_3(2,2,1)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,1,2)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,2,0)
+		- (t3dg_3(2,0,2)*t2s_2(0,0)
+		   + t3dg_3(2,1,2)*t2s_2(0,1)
+		   + t3dg_3(2,2,2)*t2s_2(0,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,2,0)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,2,1)
+		- (t3dg_3(2,0,2)*t2s_2(1,0)
+		   + t3dg_3(2,1,2)*t2s_2(1,1)
+		   + t3dg_3(2,2,2)*t2s_2(1,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,2,1)");
+  test_for_zero((t2s_2(l,j)*t3dg_3(i,j,k))(2,2,2)
+		- (t3dg_3(2,0,2)*t2s_2(2,0)
+		   + t3dg_3(2,1,2)*t2s_2(2,1)
+		   + t3dg_3(2,2,2)*t2s_2(2,2))
+		,"T2s(l,j)*T3dg(i,j,k)(2,2,2)");
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,56 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(i,j,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0) + t3dg_2(0,1,1) + t3dg_2(0,2,2))
+		,"T3dg(i,j,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0) + t3dg_2(1,1,1) + t3dg_2(1,2,2))
+		,"T3dg(i,j,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0) + t3dg_2(2,1,1) + t3dg_2(2,2,2))
+		,"T3dg(i,j,j)(2)");
+  t1_1(i)=t3dg_2(j,i,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0) + t3dg_2(1,0,1) + t3dg_2(2,0,2))
+		,"T3dg(j,i,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0) + t3dg_2(1,1,1) + t3dg_2(2,1,2))
+		,"T3dg(j,i,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0) + t3dg_2(1,2,1) + t3dg_2(2,2,2))
+		,"T3dg(j,i,j)(2)");
+  t1_1(i)=t3dg_2(j,j,i);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0) + t3dg_2(1,1,0) + t3dg_2(2,2,0))
+		,"T3dg(j,j,i)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1) + t3dg_2(1,1,1) + t3dg_2(2,2,1))
+		,"T3dg(j,j,i)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2) + t3dg_2(1,1,2) + t3dg_2(2,2,2))
+		,"T3dg(j,j,i)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,75 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+
+  /* First Number<> tests */
+
+  t3dg_1(i,j,N0)=t2s_1(i,j);
+  t3dg_1(i,j,N1)=t2s_2(i,j);
+  t3dg_1(i,j,N2)=t2s_3(i,j);
+  test_for_zero(t3dg_1(0,0,0)-t2s_1(0,0)
+		,"T3dg(i,j,N)=T2s(i,j)(0,0,0)");
+  test_for_zero(t3dg_1(0,1,0)-t2s_1(0,1)
+		,"T3dg(i,j,N)=T2s(i,j)(0,1,0)");
+  test_for_zero(t3dg_1(0,2,0)-t2s_1(0,2)
+		,"T3dg(i,j,N)=T2s(i,j)(0,2,0)");
+  test_for_zero(t3dg_1(1,1,0)-t2s_1(1,1)
+		,"T3dg(i,j,N)=T2s(i,j)(1,1,0)");
+  test_for_zero(t3dg_1(1,2,0)-t2s_1(1,2)
+		,"T3dg(i,j,N)=T2s(i,j)(1,2,0)");
+  test_for_zero(t3dg_1(2,2,0)-t2s_1(2,2)
+		,"T3dg(i,j,N)=T2s(i,j)(2,2,0)");
+  test_for_zero(t3dg_1(0,0,1)-t2s_2(0,0)
+		,"T3dg(i,j,N)=T2s(i,j)(0,0,1)");
+  test_for_zero(t3dg_1(0,1,1)-t2s_2(0,1)
+		,"T3dg(i,j,N)=T2s(i,j)(0,1,1)");
+  test_for_zero(t3dg_1(0,2,1)-t2s_2(0,2)
+		,"T3dg(i,j,N)=T2s(i,j)(0,2,1)");
+  test_for_zero(t3dg_1(1,1,1)-t2s_2(1,1)
+		,"T3dg(i,j,N)=T2s(i,j)(1,1,1)");
+  test_for_zero(t3dg_1(1,2,1)-t2s_2(1,2)
+		,"T3dg(i,j,N)=T2s(i,j)(1,2,1)");
+  test_for_zero(t3dg_1(2,2,1)-t2s_2(2,2)
+		,"T3dg(i,j,N)=T2s(i,j)(2,2,1)");
+  test_for_zero(t3dg_1(0,0,2)-t2s_3(0,0)
+		,"T3dg(i,j,N)=T2s(i,j)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,2)-t2s_3(0,1)
+		,"T3dg(i,j,N)=T2s(i,j)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,2)-t2s_3(0,2)
+		,"T3dg(i,j,N)=T2s(i,j)(0,2,2)");
+  test_for_zero(t3dg_1(1,1,2)-t2s_3(1,1)
+		,"T3dg(i,j,N)=T2s(i,j)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,2)-t2s_3(1,2)
+		,"T3dg(i,j,N)=T2s(i,j)(1,2,2)");
+  test_for_zero(t3dg_1(2,2,2)-t2s_3(2,2)
+		,"T3dg(i,j,N)=T2s(i,j)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,94 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+
+
+  t2s_1(i,j)=t3dg_2(i,j,N0);
+  test_for_zero(t3dg_2(0,0,0)-t2s_1(0,0)
+		,"T2s(i,j)=T3dg(i,j,N)(0,0,0)");
+  test_for_zero(t3dg_2(0,1,0)-t2s_1(0,1)
+		,"T2s(i,j)=T3dg(i,j,N)(0,0,1)");
+  test_for_zero(t3dg_2(0,2,0)-t2s_1(0,2)
+		,"T2s(i,j)=T3dg(i,j,N)(0,0,2)");
+  test_for_zero(t3dg_2(1,0,0)-t2s_1(1,0)
+		,"T2s(i,j)=T3dg(i,j,N)(0,1,0)");
+  test_for_zero(t3dg_2(1,1,0)-t2s_1(1,1)
+		,"T2s(i,j)=T3dg(i,j,N)(0,1,1)");
+  test_for_zero(t3dg_2(1,2,0)-t2s_1(1,2)
+		,"T2s(i,j)=T3dg(i,j,N)(0,1,2)");
+  test_for_zero(t3dg_2(2,0,0)-t2s_1(2,0)
+		,"T2s(i,j)=T3dg(i,j,N)(0,2,0)");
+  test_for_zero(t3dg_2(2,1,0)-t2s_1(2,1)
+		,"T2s(i,j)=T3dg(i,j,N)(0,2,1)");
+  test_for_zero(t3dg_2(2,2,0)-t2s_1(2,2)
+		,"T2s(i,j)=T3dg(i,j,N)(0,2,2)");
+
+  t2s_1(i,j)=t3dg_2(i,j,N1);
+  test_for_zero(t3dg_2(0,0,1)-t2s_1(0,0)
+		,"T2s(i,j)=T3dg(i,j,N)(1,0,0)");
+  test_for_zero(t3dg_2(0,1,1)-t2s_1(0,1)
+		,"T2s(i,j)=T3dg(i,j,N)(1,0,1)");
+  test_for_zero(t3dg_2(0,2,1)-t2s_1(0,2)
+		,"T2s(i,j)=T3dg(i,j,N)(1,0,2)");
+  test_for_zero(t3dg_2(1,0,1)-t2s_1(1,0)
+		,"T2s(i,j)=T3dg(i,j,N)(1,1,0)");
+  test_for_zero(t3dg_2(1,1,1)-t2s_1(1,1)
+		,"T2s(i,j)=T3dg(i,j,N)(1,1,1)");
+  test_for_zero(t3dg_2(1,2,1)-t2s_1(1,2)
+		,"T2s(i,j)=T3dg(i,j,N)(1,1,2)");
+  test_for_zero(t3dg_2(2,0,1)-t2s_1(2,0)
+		,"T2s(i,j)=T3dg(i,j,N)(1,2,0)");
+  test_for_zero(t3dg_2(2,1,1)-t2s_1(2,1)
+		,"T2s(i,j)=T3dg(i,j,N)(1,2,1)");
+  test_for_zero(t3dg_2(2,2,1)-t2s_1(2,2)
+		,"T2s(i,j)=T3dg(i,j,N)(1,2,2)");
+
+  t2s_1(i,j)=t3dg_2(i,j,N2);
+  test_for_zero(t3dg_2(0,0,2)-t2s_1(0,0)
+		,"T2s(i,j)=T3dg(i,j,N)(2,0,0)");
+  test_for_zero(t3dg_2(0,1,2)-t2s_1(0,1)
+		,"T2s(i,j)=T3dg(i,j,N)(2,0,1)");
+  test_for_zero(t3dg_2(0,2,2)-t2s_1(0,2)
+		,"T2s(i,j)=T3dg(i,j,N)(2,0,2)");
+  test_for_zero(t3dg_2(1,0,2)-t2s_1(1,0)
+		,"T2s(i,j)=T3dg(i,j,N)(2,1,0)");
+  test_for_zero(t3dg_2(1,1,2)-t2s_1(1,1)
+		,"T2s(i,j)=T3dg(i,j,N)(2,1,1)");
+  test_for_zero(t3dg_2(1,2,2)-t2s_1(1,2)
+		,"T2s(i,j)=T3dg(i,j,N)(2,1,2)");
+  test_for_zero(t3dg_2(2,0,2)-t2s_1(2,0)
+		,"T2s(i,j)=T3dg(i,j,N)(2,2,0)");
+  test_for_zero(t3dg_2(2,1,2)-t2s_1(2,1)
+		,"T2s(i,j)=T3dg(i,j,N)(2,2,1)");
+  test_for_zero(t3dg_2(2,2,2)-t2s_1(2,2)
+		,"T2s(i,j)=T3dg(i,j,N)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,94 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t2_1(i,j)=t3dg_2(N0,i,j);
+  test_for_zero(t3dg_2(0,0,0)-t2_1(0,0)
+		,"T2(i,j)=T3dg(N,i,j)(0,0,0)");
+  test_for_zero(t3dg_2(0,0,1)-t2_1(0,1)
+		,"T2(i,j)=T3dg(N,i,j)(0,0,1)");
+  test_for_zero(t3dg_2(0,0,2)-t2_1(0,2)
+		,"T2(i,j)=T3dg(N,i,j)(0,0,2)");
+  test_for_zero(t3dg_2(0,1,0)-t2_1(1,0)
+		,"T2(i,j)=T3dg(N,i,j)(0,1,0)");
+  test_for_zero(t3dg_2(0,1,1)-t2_1(1,1)
+		,"T2(i,j)=T3dg(N,i,j)(0,1,1)");
+  test_for_zero(t3dg_2(0,1,2)-t2_1(1,2)
+		,"T2(i,j)=T3dg(N,i,j)(0,1,2)");
+  test_for_zero(t3dg_2(0,2,0)-t2_1(2,0)
+		,"T2(i,j)=T3dg(N,i,j)(0,2,0)");
+  test_for_zero(t3dg_2(0,2,1)-t2_1(2,1)
+		,"T2(i,j)=T3dg(N,i,j)(0,2,1)");
+  test_for_zero(t3dg_2(0,2,2)-t2_1(2,2)
+		,"T2(i,j)=T3dg(N,i,j)(0,2,2)");
+
+  t2_1(i,j)=t3dg_2(N1,i,j);
+  test_for_zero(t3dg_2(1,0,0)-t2_1(0,0)
+		,"T2(i,j)=T3dg(N,i,j)(1,0,0)");
+  test_for_zero(t3dg_2(1,0,1)-t2_1(0,1)
+		,"T2(i,j)=T3dg(N,i,j)(1,0,1)");
+  test_for_zero(t3dg_2(1,0,2)-t2_1(0,2)
+		,"T2(i,j)=T3dg(N,i,j)(1,0,2)");
+  test_for_zero(t3dg_2(1,1,0)-t2_1(1,0)
+		,"T2(i,j)=T3dg(N,i,j)(1,1,0)");
+  test_for_zero(t3dg_2(1,1,1)-t2_1(1,1)
+		,"T2(i,j)=T3dg(N,i,j)(1,1,1)");
+  test_for_zero(t3dg_2(1,1,2)-t2_1(1,2)
+		,"T2(i,j)=T3dg(N,i,j)(1,1,2)");
+  test_for_zero(t3dg_2(1,2,0)-t2_1(2,0)
+		,"T2(i,j)=T3dg(N,i,j)(1,2,0)");
+  test_for_zero(t3dg_2(1,2,1)-t2_1(2,1)
+		,"T2(i,j)=T3dg(N,i,j)(1,2,1)");
+  test_for_zero(t3dg_2(1,2,2)-t2_1(2,2)
+		,"T2(i,j)=T3dg(N,i,j)(1,2,2)");
+
+  t2_1(i,j)=t3dg_2(N2,i,j);
+  test_for_zero(t3dg_2(2,0,0)-t2_1(0,0)
+		,"T2(i,j)=T3dg(N,i,j)(2,0,0)");
+  test_for_zero(t3dg_2(2,0,1)-t2_1(0,1)
+		,"T2(i,j)=T3dg(N,i,j)(2,0,1)");
+  test_for_zero(t3dg_2(2,0,2)-t2_1(0,2)
+		,"T2(i,j)=T3dg(N,i,j)(2,0,2)");
+  test_for_zero(t3dg_2(2,1,0)-t2_1(1,0)
+		,"T2(i,j)=T3dg(N,i,j)(2,1,0)");
+  test_for_zero(t3dg_2(2,1,1)-t2_1(1,1)
+		,"T2(i,j)=T3dg(N,i,j)(2,1,1)");
+  test_for_zero(t3dg_2(2,1,2)-t2_1(1,2)
+		,"T2(i,j)=T3dg(N,i,j)(2,1,2)");
+  test_for_zero(t3dg_2(2,2,0)-t2_1(2,0)
+		,"T2(i,j)=T3dg(N,i,j)(2,2,0)");
+  test_for_zero(t3dg_2(2,2,1)-t2_1(2,1)
+		,"T2(i,j)=T3dg(N,i,j)(2,2,1)");
+  test_for_zero(t3dg_2(2,2,2)-t2_1(2,2)
+		,"T2(i,j)=T3dg(N,i,j)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,90 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t2s_2(i,j)*t1_2(k);
+  test_for_zero(t3dg_1(0,0,0) - t2s_2(0,0)*t1_2(0)
+		,"T2s(i,j)*T1(k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - t2s_2(0,0)*t1_2(1)
+		,"T2s(i,j)*T1(k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - t2s_2(0,0)*t1_2(2)
+		,"T2s(i,j)*T1(k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - t2s_2(0,1)*t1_2(0)
+		,"T2s(i,j)*T1(k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - t2s_2(0,1)*t1_2(1)
+		,"T2s(i,j)*T1(k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - t2s_2(0,1)*t1_2(2)
+		,"T2s(i,j)*T1(k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - t2s_2(0,2)*t1_2(0)
+		,"T2s(i,j)*T1(k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - t2s_2(0,2)*t1_2(1)
+		,"T2s(i,j)*T1(k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - t2s_2(0,2)*t1_2(2)
+		,"T2s(i,j)*T1(k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - t2s_2(1,0)*t1_2(0)
+		,"T2s(i,j)*T1(k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - t2s_2(1,0)*t1_2(1)
+		,"T2s(i,j)*T1(k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - t2s_2(1,0)*t1_2(2)
+		,"T2s(i,j)*T1(k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - t2s_2(1,1)*t1_2(0)
+		,"T2s(i,j)*T1(k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - t2s_2(1,1)*t1_2(1)
+		,"T2s(i,j)*T1(k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - t2s_2(1,1)*t1_2(2)
+		,"T2s(i,j)*T1(k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - t2s_2(1,2)*t1_2(0)
+		,"T2s(i,j)*T1(k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - t2s_2(1,2)*t1_2(1)
+		,"T2s(i,j)*T1(k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - t2s_2(1,2)*t1_2(2)
+		,"T2s(i,j)*T1(k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - t2s_2(2,0)*t1_2(0)
+		,"T2s(i,j)*T1(k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - t2s_2(2,0)*t1_2(1)
+		,"T2s(i,j)*T1(k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - t2s_2(2,0)*t1_2(2)
+		,"T2s(i,j)*T1(k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - t2s_2(2,1)*t1_2(0)
+		,"T2s(i,j)*T1(k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - t2s_2(2,1)*t1_2(1)
+		,"T2s(i,j)*T1(k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - t2s_2(2,1)*t1_2(2)
+		,"T2s(i,j)*T1(k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - t2s_2(2,2)*t1_2(0)
+		,"T2s(i,j)*T1(k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - t2s_2(2,2)*t1_2(1)
+		,"T2s(i,j)*T1(k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - t2s_2(2,2)*t1_2(2)
+		,"T2s(i,j)*T1(k)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,94 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t2_1(i,j)=t3dg_2(i,N0,j);
+  test_for_zero(t3dg_2(0,0,0)-t2_1(0,0)
+		,"T2(i,j)=T3dg(i,N,j)(0,0,0)");
+  test_for_zero(t3dg_2(0,0,1)-t2_1(0,1)
+		,"T2(i,j)=T3dg(i,N,j)(0,0,1)");
+  test_for_zero(t3dg_2(0,0,2)-t2_1(0,2)
+		,"T2(i,j)=T3dg(i,N,j)(0,0,2)");
+  test_for_zero(t3dg_2(1,0,0)-t2_1(1,0)
+		,"T2(i,j)=T3dg(i,N,j)(0,1,0)");
+  test_for_zero(t3dg_2(1,0,1)-t2_1(1,1)
+		,"T2(i,j)=T3dg(i,N,j)(0,1,1)");
+  test_for_zero(t3dg_2(1,0,2)-t2_1(1,2)
+		,"T2(i,j)=T3dg(i,N,j)(0,1,2)");
+  test_for_zero(t3dg_2(2,0,0)-t2_1(2,0)
+		,"T2(i,j)=T3dg(i,N,j)(0,2,0)");
+  test_for_zero(t3dg_2(2,0,1)-t2_1(2,1)
+		,"T2(i,j)=T3dg(i,N,j)(0,2,1)");
+  test_for_zero(t3dg_2(2,0,2)-t2_1(2,2)
+		,"T2(i,j)=T3dg(i,N,j)(0,2,2)");
+
+  t2_1(i,j)=t3dg_2(i,N1,j);
+  test_for_zero(t3dg_2(0,1,0)-t2_1(0,0)
+		,"T2(i,j)=T3dg(i,N,j)(1,0,0)");
+  test_for_zero(t3dg_2(0,1,1)-t2_1(0,1)
+		,"T2(i,j)=T3dg(i,N,j)(1,0,1)");
+  test_for_zero(t3dg_2(0,1,2)-t2_1(0,2)
+		,"T2(i,j)=T3dg(i,N,j)(1,0,2)");
+  test_for_zero(t3dg_2(1,1,0)-t2_1(1,0)
+		,"T2(i,j)=T3dg(i,N,j)(1,1,0)");
+  test_for_zero(t3dg_2(1,1,1)-t2_1(1,1)
+		,"T2(i,j)=T3dg(i,N,j)(1,1,1)");
+  test_for_zero(t3dg_2(1,1,2)-t2_1(1,2)
+		,"T2(i,j)=T3dg(i,N,j)(1,1,2)");
+  test_for_zero(t3dg_2(2,1,0)-t2_1(2,0)
+		,"T2(i,j)=T3dg(i,N,j)(1,2,0)");
+  test_for_zero(t3dg_2(2,1,1)-t2_1(2,1)
+		,"T2(i,j)=T3dg(i,N,j)(1,2,1)");
+  test_for_zero(t3dg_2(2,1,2)-t2_1(2,2)
+		,"T2(i,j)=T3dg(i,N,j)(1,2,2)");
+
+  t2_1(i,j)=t3dg_2(i,N2,j);
+  test_for_zero(t3dg_2(0,2,0)-t2_1(0,0)
+		,"T2(i,j)=T3dg(i,N,j)(2,0,0)");
+  test_for_zero(t3dg_2(0,2,1)-t2_1(0,1)
+		,"T2(i,j)=T3dg(i,N,j)(2,0,1)");
+  test_for_zero(t3dg_2(0,2,2)-t2_1(0,2)
+		,"T2(i,j)=T3dg(i,N,j)(2,0,2)");
+  test_for_zero(t3dg_2(1,2,0)-t2_1(1,0)
+		,"T2(i,j)=T3dg(i,N,j)(2,1,0)");
+  test_for_zero(t3dg_2(1,2,1)-t2_1(1,1)
+		,"T2(i,j)=T3dg(i,N,j)(2,1,1)");
+  test_for_zero(t3dg_2(1,2,2)-t2_1(1,2)
+		,"T2(i,j)=T3dg(i,N,j)(2,1,2)");
+  test_for_zero(t3dg_2(2,2,0)-t2_1(2,0)
+		,"T2(i,j)=T3dg(i,N,j)(2,2,0)");
+  test_for_zero(t3dg_2(2,2,1)-t2_1(2,1)
+		,"T2(i,j)=T3dg(i,N,j)(2,2,1)");
+  test_for_zero(t3dg_2(2,2,2)-t2_1(2,2)
+		,"T2(i,j)=T3dg(i,N,j)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,96 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  /* Now, test with actual numbers. */
+
+  t2s_1(i,j)=t3dg_2(i,j,0);
+  test_for_zero(t3dg_2(0,0,0)-t2s_1(0,0)
+		,"T3dg(i,j,Num)(0,0,0)");
+  test_for_zero(t3dg_2(0,1,0)-t2s_1(0,1)
+		,"T3dg(i,j,Num)(0,0,1)");
+  test_for_zero(t3dg_2(0,2,0)-t2s_1(0,2)
+		,"T3dg(i,j,Num)(0,0,2)");
+  test_for_zero(t3dg_2(1,0,0)-t2s_1(1,0)
+		,"T3dg(i,j,Num)(0,1,0)");
+  test_for_zero(t3dg_2(1,1,0)-t2s_1(1,1)
+		,"T3dg(i,j,Num)(0,1,1)");
+  test_for_zero(t3dg_2(1,2,0)-t2s_1(1,2)
+		,"T3dg(i,j,Num)(0,1,2)");
+  test_for_zero(t3dg_2(2,0,0)-t2s_1(2,0)
+		,"T3dg(i,j,Num)(0,2,0)");
+  test_for_zero(t3dg_2(2,1,0)-t2s_1(2,1)
+		,"T3dg(i,j,Num)(0,2,1)");
+  test_for_zero(t3dg_2(2,2,0)-t2s_1(2,2)
+		,"T3dg(i,j,Num)(0,2,2)");
+
+  t2s_1(i,j)=t3dg_2(i,j,1);
+  test_for_zero(t3dg_2(0,0,1)-t2s_1(0,0)
+		,"T3dg(i,j,Num)(1,0,0)");
+  test_for_zero(t3dg_2(0,1,1)-t2s_1(0,1)
+		,"T3dg(i,j,Num)(1,0,1)");
+  test_for_zero(t3dg_2(0,2,1)-t2s_1(0,2)
+		,"T3dg(i,j,Num)(1,0,2)");
+  test_for_zero(t3dg_2(1,0,1)-t2s_1(1,0)
+		,"T3dg(i,j,Num)(1,1,0)");
+  test_for_zero(t3dg_2(1,1,1)-t2s_1(1,1)
+		,"T3dg(i,j,Num)(1,1,1)");
+  test_for_zero(t3dg_2(1,2,1)-t2s_1(1,2)
+		,"T3dg(i,j,Num)(1,1,2)");
+  test_for_zero(t3dg_2(2,0,1)-t2s_1(2,0)
+		,"T3dg(i,j,Num)(1,2,0)");
+  test_for_zero(t3dg_2(2,1,1)-t2s_1(2,1)
+		,"T3dg(i,j,Num)(1,2,1)");
+  test_for_zero(t3dg_2(2,2,1)-t2s_1(2,2)
+		,"T3dg(i,j,Num)(1,2,2)");
+
+  t2s_1(i,j)=t3dg_2(i,j,2);
+  test_for_zero(t3dg_2(0,0,2)-t2s_1(0,0)
+		,"T3dg(i,j,Num)(2,0,0)");
+  test_for_zero(t3dg_2(0,1,2)-t2s_1(0,1)
+		,"T3dg(i,j,Num)(2,0,1)");
+  test_for_zero(t3dg_2(0,2,2)-t2s_1(0,2)
+		,"T3dg(i,j,Num)(2,0,2)");
+  test_for_zero(t3dg_2(1,0,2)-t2s_1(1,0)
+		,"T3dg(i,j,Num)(2,1,0)");
+  test_for_zero(t3dg_2(1,1,2)-t2s_1(1,1)
+		,"T3dg(i,j,Num)(2,1,1)");
+  test_for_zero(t3dg_2(1,2,2)-t2s_1(1,2)
+		,"T3dg(i,j,Num)(2,1,2)");
+  test_for_zero(t3dg_2(2,0,2)-t2s_1(2,0)
+		,"T3dg(i,j,Num)(2,2,0)");
+  test_for_zero(t3dg_2(2,1,2)-t2s_1(2,1)
+		,"T3dg(i,j,Num)(2,2,1)");
+  test_for_zero(t3dg_2(2,2,2)-t2s_1(2,2)
+		,"T3dg(i,j,Num)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,96 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  /* Now, test with actual numbers. */
+
+  t2_1(i,j)=t3dg_2(0,i,j);
+  test_for_zero(t3dg_2(0,0,0)-t2_1(0,0)
+		,"T3dg(Num,i,j)(0,0,0)");
+  test_for_zero(t3dg_2(0,0,1)-t2_1(0,1)
+		,"T3dg(Num,i,j)(0,0,1)");
+  test_for_zero(t3dg_2(0,0,2)-t2_1(0,2)
+		,"T3dg(Num,i,j)(0,0,2)");
+  test_for_zero(t3dg_2(0,1,0)-t2_1(1,0)
+		,"T3dg(Num,i,j)(0,1,0)");
+  test_for_zero(t3dg_2(0,1,1)-t2_1(1,1)
+		,"T3dg(Num,i,j)(0,1,1)");
+  test_for_zero(t3dg_2(0,1,2)-t2_1(1,2)
+		,"T3dg(Num,i,j)(0,1,2)");
+  test_for_zero(t3dg_2(0,2,0)-t2_1(2,0)
+		,"T3dg(Num,i,j)(0,2,0)");
+  test_for_zero(t3dg_2(0,2,1)-t2_1(2,1)
+		,"T3dg(Num,i,j)(0,2,1)");
+  test_for_zero(t3dg_2(0,2,2)-t2_1(2,2)
+		,"T3dg(Num,i,j)(0,2,2)");
+
+  t2_1(i,j)=t3dg_2(1,i,j);
+  test_for_zero(t3dg_2(1,0,0)-t2_1(0,0)
+		,"T3dg(Num,i,j)(1,0,0)");
+  test_for_zero(t3dg_2(1,0,1)-t2_1(0,1)
+		,"T3dg(Num,i,j)(1,0,1)");
+  test_for_zero(t3dg_2(1,0,2)-t2_1(0,2)
+		,"T3dg(Num,i,j)(1,0,2)");
+  test_for_zero(t3dg_2(1,1,0)-t2_1(1,0)
+		,"T3dg(Num,i,j)(1,1,0)");
+  test_for_zero(t3dg_2(1,1,1)-t2_1(1,1)
+		,"T3dg(Num,i,j)(1,1,1)");
+  test_for_zero(t3dg_2(1,1,2)-t2_1(1,2)
+		,"T3dg(Num,i,j)(1,1,2)");
+  test_for_zero(t3dg_2(1,2,0)-t2_1(2,0)
+		,"T3dg(Num,i,j)(1,2,0)");
+  test_for_zero(t3dg_2(1,2,1)-t2_1(2,1)
+		,"T3dg(Num,i,j)(1,2,1)");
+  test_for_zero(t3dg_2(1,2,2)-t2_1(2,2)
+		,"T3dg(Num,i,j)(1,2,2)");
+
+  t2_1(i,j)=t3dg_2(2,i,j);
+  test_for_zero(t3dg_2(2,0,0)-t2_1(0,0)
+		,"T3dg(Num,i,j)(2,0,0)");
+  test_for_zero(t3dg_2(2,0,1)-t2_1(0,1)
+		,"T3dg(Num,i,j)(2,0,1)");
+  test_for_zero(t3dg_2(2,0,2)-t2_1(0,2)
+		,"T3dg(Num,i,j)(2,0,2)");
+  test_for_zero(t3dg_2(2,1,0)-t2_1(1,0)
+		,"T3dg(Num,i,j)(2,1,0)");
+  test_for_zero(t3dg_2(2,1,1)-t2_1(1,1)
+		,"T3dg(Num,i,j)(2,1,1)");
+  test_for_zero(t3dg_2(2,1,2)-t2_1(1,2)
+		,"T3dg(Num,i,j)(2,1,2)");
+  test_for_zero(t3dg_2(2,2,0)-t2_1(2,0)
+		,"T3dg(Num,i,j)(2,2,0)");
+  test_for_zero(t3dg_2(2,2,1)-t2_1(2,1)
+		,"T3dg(Num,i,j)(2,2,1)");
+  test_for_zero(t3dg_2(2,2,2)-t2_1(2,2)
+		,"T3dg(Num,i,j)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,96 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  /* Now, test with actual numbers. */
+
+  t2_1(i,j)=t3dg_2(i,0,j);
+  test_for_zero(t3dg_2(0,0,0)-t2_1(0,0)
+		,"T3dg(i,Num,j)(0,0,0)");
+  test_for_zero(t3dg_2(0,0,1)-t2_1(0,1)
+		,"T3dg(i,Num,j)(0,0,1)");
+  test_for_zero(t3dg_2(0,0,2)-t2_1(0,2)
+		,"T3dg(i,Num,j)(0,0,2)");
+  test_for_zero(t3dg_2(1,0,0)-t2_1(1,0)
+		,"T3dg(i,Num,j)(0,1,0)");
+  test_for_zero(t3dg_2(1,0,1)-t2_1(1,1)
+		,"T3dg(i,Num,j)(0,1,1)");
+  test_for_zero(t3dg_2(1,0,2)-t2_1(1,2)
+		,"T3dg(i,Num,j)(0,1,2)");
+  test_for_zero(t3dg_2(2,0,0)-t2_1(2,0)
+		,"T3dg(i,Num,j)(0,2,0)");
+  test_for_zero(t3dg_2(2,0,1)-t2_1(2,1)
+		,"T3dg(i,Num,j)(0,2,1)");
+  test_for_zero(t3dg_2(2,0,2)-t2_1(2,2)
+		,"T3dg(i,Num,j)(0,2,2)");
+
+  t2_1(i,j)=t3dg_2(i,1,j);
+  test_for_zero(t3dg_2(0,1,0)-t2_1(0,0)
+		,"T3dg(i,Num,j)(1,0,0)");
+  test_for_zero(t3dg_2(0,1,1)-t2_1(0,1)
+		,"T3dg(i,Num,j)(1,0,1)");
+  test_for_zero(t3dg_2(0,1,2)-t2_1(0,2)
+		,"T3dg(i,Num,j)(1,0,2)");
+  test_for_zero(t3dg_2(1,1,0)-t2_1(1,0)
+		,"T3dg(i,Num,j)(1,1,0)");
+  test_for_zero(t3dg_2(1,1,1)-t2_1(1,1)
+		,"T3dg(i,Num,j)(1,1,1)");
+  test_for_zero(t3dg_2(1,1,2)-t2_1(1,2)
+		,"T3dg(i,Num,j)(1,1,2)");
+  test_for_zero(t3dg_2(2,1,0)-t2_1(2,0)
+		,"T3dg(i,Num,j)(1,2,0)");
+  test_for_zero(t3dg_2(2,1,1)-t2_1(2,1)
+		,"T3dg(i,Num,j)(1,2,1)");
+  test_for_zero(t3dg_2(2,1,2)-t2_1(2,2)
+		,"T3dg(i,Num,j)(1,2,2)");
+
+  t2_1(i,j)=t3dg_2(i,2,j);
+  test_for_zero(t3dg_2(0,2,0)-t2_1(0,0)
+		,"T3dg(i,Num,j)(2,0,0)");
+  test_for_zero(t3dg_2(0,2,1)-t2_1(0,1)
+		,"T3dg(i,Num,j)(2,0,1)");
+  test_for_zero(t3dg_2(0,2,2)-t2_1(0,2)
+		,"T3dg(i,Num,j)(2,0,2)");
+  test_for_zero(t3dg_2(1,2,0)-t2_1(1,0)
+		,"T3dg(i,Num,j)(2,1,0)");
+  test_for_zero(t3dg_2(1,2,1)-t2_1(1,1)
+		,"T3dg(i,Num,j)(2,1,1)");
+  test_for_zero(t3dg_2(1,2,2)-t2_1(1,2)
+		,"T3dg(i,Num,j)(2,1,2)");
+  test_for_zero(t3dg_2(2,2,0)-t2_1(2,0)
+		,"T3dg(i,Num,j)(2,2,0)");
+  test_for_zero(t3dg_2(2,2,1)-t2_1(2,1)
+		,"T3dg(i,Num,j)(2,2,1)");
+  test_for_zero(t3dg_2(2,2,2)-t2_1(2,2)
+		,"T3dg(i,Num,j)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,90 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=10;
+  test_for_zero(t3dg_1(0,0,0) - 10
+		,"T3dg=T(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - 10
+		,"T3dg=T(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - 10
+		,"T3dg=T(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - 10
+		,"T3dg=T(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - 10
+		,"T3dg=T(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - 10
+		,"T3dg=T(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - 10
+		,"T3dg=T(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - 10
+		,"T3dg=T(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - 10
+		,"T3dg=T(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - 10
+		,"T3dg=T(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - 10
+		,"T3dg=T(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - 10
+		,"T3dg=T(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - 10
+		,"T3dg=T(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - 10
+		,"T3dg=T(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - 10
+		,"T3dg=T(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - 10
+		,"T3dg=T(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - 10
+		,"T3dg=T(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - 10
+		,"T3dg=T(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - 10
+		,"T3dg=T(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - 10
+		,"T3dg=T(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - 10
+		,"T3dg=T(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - 10
+		,"T3dg=T(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - 10
+		,"T3dg=T(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - 10
+		,"T3dg=T(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - 10
+		,"T3dg=T(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - 10
+		,"T3dg=T(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - 10
+		,"T3dg=T(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,90 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,k)+t3dg_3(i,j,k);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0) + t3dg_3(0,0,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,1) + t3dg_3(0,0,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,2) + t3dg_3(0,0,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0) + t3dg_3(0,1,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,1) + t3dg_3(0,1,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,2) + t3dg_3(0,1,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0) + t3dg_3(0,2,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,1) + t3dg_3(0,2,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,2) + t3dg_3(0,2,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0) + t3dg_3(1,0,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,1) + t3dg_3(1,0,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,2) + t3dg_3(1,0,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0) + t3dg_3(1,1,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1) + t3dg_3(1,1,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,2) + t3dg_3(1,1,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0) + t3dg_3(1,2,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,1) + t3dg_3(1,2,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,2) + t3dg_3(1,2,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0) + t3dg_3(2,0,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,1) + t3dg_3(2,0,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,2) + t3dg_3(2,0,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0) + t3dg_3(2,1,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,1) + t3dg_3(2,1,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,2) + t3dg_3(2,1,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0) + t3dg_3(2,2,0))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,1) + t3dg_3(2,2,1))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2) + t3dg_3(2,2,2))
+		,"T3dg(i,j,k)+T3dg(i,j,k)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,90 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,k)-t3dg_3(i,j,k);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0) - t3dg_3(0,0,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,1) - t3dg_3(0,0,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,2) - t3dg_3(0,0,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0) - t3dg_3(0,1,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,1) - t3dg_3(0,1,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,2) - t3dg_3(0,1,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0) - t3dg_3(0,2,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,1) - t3dg_3(0,2,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,2) - t3dg_3(0,2,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0) - t3dg_3(1,0,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,1) - t3dg_3(1,0,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,2) - t3dg_3(1,0,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0) - t3dg_3(1,1,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1) - t3dg_3(1,1,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,2) - t3dg_3(1,1,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0) - t3dg_3(1,2,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,1) - t3dg_3(1,2,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,2) - t3dg_3(1,2,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0) - t3dg_3(2,0,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,1) - t3dg_3(2,0,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,2) - t3dg_3(2,0,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0) - t3dg_3(2,1,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,1) - t3dg_3(2,1,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,2) - t3dg_3(2,1,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0) - t3dg_3(2,2,0))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,1) - t3dg_3(2,2,1))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2) - t3dg_3(2,2,2))
+		,"T3dg(i,j,k)-T3dg(i,j,k)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,90 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,k)+t3dg_3(j,i,k);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0) + t3dg_3(0,0,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,1) + t3dg_3(0,0,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,2) + t3dg_3(0,0,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0) + t3dg_3(0,1,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,1) + t3dg_3(0,1,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,2) + t3dg_3(0,1,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0) + t3dg_3(0,2,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,1) + t3dg_3(0,2,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,2) + t3dg_3(0,2,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0) + t3dg_3(1,0,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,1) + t3dg_3(1,0,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,2) + t3dg_3(1,0,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0) + t3dg_3(1,1,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1) + t3dg_3(1,1,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,2) + t3dg_3(1,1,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0) + t3dg_3(1,2,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,1) + t3dg_3(1,2,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,2) + t3dg_3(1,2,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0) + t3dg_3(2,0,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,1) + t3dg_3(2,0,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,2) + t3dg_3(2,0,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0) + t3dg_3(2,1,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,1) + t3dg_3(2,1,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,2) + t3dg_3(2,1,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0) + t3dg_3(2,2,0))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,1) + t3dg_3(2,2,1))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2) + t3dg_3(2,2,2))
+		,"T3dg(i,j,k)+T3dg(j,i,k)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,90 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=-t3dg_2(i,j,k);
+  test_for_zero(t3dg_1(0,0,0) + t3dg_2(0,0,0)
+		,"-T3dg(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) + t3dg_2(0,0,1)
+		,"-T3dg(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) + t3dg_2(0,0,2)
+		,"-T3dg(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) + t3dg_2(0,1,0)
+		,"-T3dg(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) + t3dg_2(0,1,1)
+		,"-T3dg(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) + t3dg_2(0,1,2)
+		,"-T3dg(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) + t3dg_2(0,2,0)
+		,"-T3dg(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) + t3dg_2(0,2,1)
+		,"-T3dg(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) + t3dg_2(0,2,2)
+		,"-T3dg(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) + t3dg_2(1,0,0)
+		,"-T3dg(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) + t3dg_2(1,0,1)
+		,"-T3dg(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) + t3dg_2(1,0,2)
+		,"-T3dg(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) + t3dg_2(1,1,0)
+		,"-T3dg(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) + t3dg_2(1,1,1)
+		,"-T3dg(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) + t3dg_2(1,1,2)
+		,"-T3dg(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) + t3dg_2(1,2,0)
+		,"-T3dg(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) + t3dg_2(1,2,1)
+		,"-T3dg(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) + t3dg_2(1,2,2)
+		,"-T3dg(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) + t3dg_2(2,0,0)
+		,"-T3dg(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) + t3dg_2(2,0,1)
+		,"-T3dg(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) + t3dg_2(2,0,2)
+		,"-T3dg(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) + t3dg_2(2,1,0)
+		,"-T3dg(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) + t3dg_2(2,1,1)
+		,"-T3dg(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) + t3dg_2(2,1,2)
+		,"-T3dg(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) + t3dg_2(2,2,0)
+		,"-T3dg(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) + t3dg_2(2,2,1)
+		,"-T3dg(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) + t3dg_2(2,2,2)
+		,"-T3dg(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,110 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t2_1(i,j)=t3dg_2(k,i,j)*t1_2(k);
+  test_for_zero(t2_1(0,0) - (t3dg_2(0,0,0)*t1_2(0)
+			     + t3dg_2(1,0,0)*t1_2(1)
+			     + t3dg_2(2,0,0)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_2(0,0,1)*t1_2(0)
+			     + t3dg_2(1,0,1)*t1_2(1)
+			     + t3dg_2(2,0,1)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_2(0,0,2)*t1_2(0)
+			     + t3dg_2(1,0,2)*t1_2(1)
+			     + t3dg_2(2,0,2)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_2(0,1,0)*t1_2(0)
+			     + t3dg_2(1,1,0)*t1_2(1)
+			     + t3dg_2(2,1,0)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_2(0,1,1)*t1_2(0)
+			     + t3dg_2(1,1,1)*t1_2(1)
+			     + t3dg_2(2,1,1)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_2(0,1,2)*t1_2(0)
+			     + t3dg_2(1,1,2)*t1_2(1)
+			     + t3dg_2(2,1,2)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_2(0,2,0)*t1_2(0)
+			     + t3dg_2(1,2,0)*t1_2(1)
+			     + t3dg_2(2,2,0)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_2(0,2,1)*t1_2(0)
+			     + t3dg_2(1,2,1)*t1_2(1)
+			     + t3dg_2(2,2,1)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_2(0,2,2)*t1_2(0)
+			     + t3dg_2(1,2,2)*t1_2(1)
+			     + t3dg_2(2,2,2)*t1_2(2))
+		,"T3dg(k,i,j)*T1(k)(2,2)");
+
+  t2_1(i,j)=t1_2(k)*t3dg_3(k,i,j);
+  test_for_zero(t2_1(0,0) - (t3dg_3(0,0,0)*t1_2(0)
+			     + t3dg_3(1,0,0)*t1_2(1)
+			     + t3dg_3(2,0,0)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_3(0,0,1)*t1_2(0)
+			     + t3dg_3(1,0,1)*t1_2(1)
+			     + t3dg_3(2,0,1)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_3(0,0,2)*t1_2(0)
+			     + t3dg_3(1,0,2)*t1_2(1)
+			     + t3dg_3(2,0,2)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_3(0,1,0)*t1_2(0)
+			     + t3dg_3(1,1,0)*t1_2(1)
+			     + t3dg_3(2,1,0)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_3(0,1,1)*t1_2(0)
+			     + t3dg_3(1,1,1)*t1_2(1)
+			     + t3dg_3(2,1,1)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_3(0,1,2)*t1_2(0)
+			     + t3dg_3(1,1,2)*t1_2(1)
+			     + t3dg_3(2,1,2)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_3(0,2,0)*t1_2(0)
+			     + t3dg_3(1,2,0)*t1_2(1)
+			     + t3dg_3(2,2,0)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_3(0,2,1)*t1_2(0)
+			     + t3dg_3(1,2,1)*t1_2(1)
+			     + t3dg_3(2,2,1)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_3(0,2,2)*t1_2(0)
+			     + t3dg_3(1,2,2)*t1_2(1)
+			     + t3dg_3(2,2,2)*t1_2(2))
+		,"T1(k)*T3dg(k,i,j)(2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,146 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=(t3dg_2(i,j,k)&t1_2(k));
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0)*t1_2(0))
+		,"T3dg(i,j,k)&T1(k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,1)*t1_2(1))
+		,"T3dg(i,j,k)&T1(k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,2)*t1_2(2))
+		,"T3dg(i,j,k)&T1(k)(2,2,2)");
+
+  t3dg_1(i,j,k)=(t1_2(k)&t3dg_3(i,j,k));
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_3(0,0,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_3(0,0,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_3(0,0,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_3(0,1,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_3(0,1,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_3(0,1,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_3(0,2,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_3(0,2,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_3(0,2,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_3(1,0,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_3(1,0,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_3(1,0,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_3(1,1,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_3(1,1,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_3(1,1,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_3(1,2,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_3(1,2,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_3(1,2,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_3(2,0,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_3(2,0,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_3(2,0,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_3(2,1,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_3(2,1,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_3(2,1,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_3(2,2,0)*t1_2(0))
+		,"T1(k)&T3dg(i,j,k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_3(2,2,1)*t1_2(1))
+		,"T1(k)&T3dg(i,j,k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_3(2,2,2)*t1_2(2))
+		,"T1(k)&T3dg(i,j,k)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,146 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,k)*10;
+  test_for_zero(t3dg_1(0,0,0) - t3dg_2(0,0,0)*10
+		,"T3dg*T(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - t3dg_2(0,0,1)*10
+		,"T3dg*T(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - t3dg_2(0,0,2)*10
+		,"T3dg*T(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - t3dg_2(0,1,0)*10
+		,"T3dg*T(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - t3dg_2(0,1,1)*10
+		,"T3dg*T(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - t3dg_2(0,1,2)*10
+		,"T3dg*T(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - t3dg_2(0,2,0)*10
+		,"T3dg*T(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - t3dg_2(0,2,1)*10
+		,"T3dg*T(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - t3dg_2(0,2,2)*10
+		,"T3dg*T(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - t3dg_2(1,0,0)*10
+		,"T3dg*T(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - t3dg_2(1,0,1)*10
+		,"T3dg*T(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - t3dg_2(1,0,2)*10
+		,"T3dg*T(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - t3dg_2(1,1,0)*10
+		,"T3dg*T(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - t3dg_2(1,1,1)*10
+		,"T3dg*T(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - t3dg_2(1,1,2)*10
+		,"T3dg*T(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - t3dg_2(1,2,0)*10
+		,"T3dg*T(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - t3dg_2(1,2,1)*10
+		,"T3dg*T(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - t3dg_2(1,2,2)*10
+		,"T3dg*T(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - t3dg_2(2,0,0)*10
+		,"T3dg*T(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - t3dg_2(2,0,1)*10
+		,"T3dg*T(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - t3dg_2(2,0,2)*10
+		,"T3dg*T(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - t3dg_2(2,1,0)*10
+		,"T3dg*T(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - t3dg_2(2,1,1)*10
+		,"T3dg*T(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - t3dg_2(2,1,2)*10
+		,"T3dg*T(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - t3dg_2(2,2,0)*10
+		,"T3dg*T(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - t3dg_2(2,2,1)*10
+		,"T3dg*T(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - t3dg_2(2,2,2)*10
+		,"T3dg*T(2,2,2)");
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,k)/10;
+  test_for_zero(t3dg_1(0,0,0) - t3dg_2(0,0,0)/10
+		,"T3dg/T(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - t3dg_2(0,0,1)/10
+		,"T3dg/T(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - t3dg_2(0,0,2)/10
+		,"T3dg/T(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - t3dg_2(0,1,0)/10
+		,"T3dg/T(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - t3dg_2(0,1,1)/10
+		,"T3dg/T(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - t3dg_2(0,1,2)/10
+		,"T3dg/T(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - t3dg_2(0,2,0)/10
+		,"T3dg/T(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - t3dg_2(0,2,1)/10
+		,"T3dg/T(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - t3dg_2(0,2,2)/10
+		,"T3dg/T(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - t3dg_2(1,0,0)/10
+		,"T3dg/T(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - t3dg_2(1,0,1)/10
+		,"T3dg/T(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - t3dg_2(1,0,2)/10
+		,"T3dg/T(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - t3dg_2(1,1,0)/10
+		,"T3dg/T(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - t3dg_2(1,1,1)/10
+		,"T3dg/T(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - t3dg_2(1,1,2)/10
+		,"T3dg/T(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - t3dg_2(1,2,0)/10
+		,"T3dg/T(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - t3dg_2(1,2,1)/10
+		,"T3dg/T(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - t3dg_2(1,2,2)/10
+		,"T3dg/T(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - t3dg_2(2,0,0)/10
+		,"T3dg/T(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - t3dg_2(2,0,1)/10
+		,"T3dg/T(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - t3dg_2(2,0,2)/10
+		,"T3dg/T(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - t3dg_2(2,1,0)/10
+		,"T3dg/T(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - t3dg_2(2,1,1)/10
+		,"T3dg/T(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - t3dg_2(2,1,2)/10
+		,"T3dg/T(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - t3dg_2(2,2,0)/10
+		,"T3dg/T(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - t3dg_2(2,2,1)/10
+		,"T3dg/T(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - t3dg_2(2,2,2)/10
+		,"T3dg/T(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,110 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t2s_1(i,j)=t3dg_2(i,j,k)*t1_2(k);
+  test_for_zero(t2s_1(0,0) - (t3dg_2(0,0,0)*t1_2(0)
+			      + t3dg_2(0,0,1)*t1_2(1)
+			      + t3dg_2(0,0,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t3dg_2(0,1,0)*t1_2(0)
+			      + t3dg_2(0,1,1)*t1_2(1)
+			      + t3dg_2(0,1,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t3dg_2(0,2,0)*t1_2(0)
+			      + t3dg_2(0,2,1)*t1_2(1)
+			      + t3dg_2(0,2,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t3dg_2(1,0,0)*t1_2(0)
+			      + t3dg_2(1,0,1)*t1_2(1)
+			      + t3dg_2(1,0,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t3dg_2(1,1,0)*t1_2(0)
+			      + t3dg_2(1,1,1)*t1_2(1)
+			      + t3dg_2(1,1,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t3dg_2(1,2,0)*t1_2(0)
+			      + t3dg_2(1,2,1)*t1_2(1)
+			      + t3dg_2(1,2,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t3dg_2(2,0,0)*t1_2(0)
+			      + t3dg_2(2,0,1)*t1_2(1)
+			      + t3dg_2(2,0,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t3dg_2(2,1,0)*t1_2(0)
+			      + t3dg_2(2,1,1)*t1_2(1)
+			      + t3dg_2(2,1,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t3dg_2(2,2,0)*t1_2(0)
+			      + t3dg_2(2,2,1)*t1_2(1)
+			      + t3dg_2(2,2,2)*t1_2(2))
+		,"T3dg(i,j,k)*T1(k)(2,2)");
+
+  t2s_1(i,j)=t1_2(k)*t3dg_3(i,j,k);
+  test_for_zero(t2s_1(0,0) - (t3dg_3(0,0,0)*t1_2(0)
+			      + t3dg_3(0,0,1)*t1_2(1)
+			      + t3dg_3(0,0,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t3dg_3(0,1,0)*t1_2(0)
+			      + t3dg_3(0,1,1)*t1_2(1)
+			      + t3dg_3(0,1,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t3dg_3(0,2,0)*t1_2(0)
+			      + t3dg_3(0,2,1)*t1_2(1)
+			      + t3dg_3(0,2,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t3dg_3(1,0,0)*t1_2(0)
+			      + t3dg_3(1,0,1)*t1_2(1)
+			      + t3dg_3(1,0,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t3dg_3(1,1,0)*t1_2(0)
+			      + t3dg_3(1,1,1)*t1_2(1)
+			      + t3dg_3(1,1,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t3dg_3(1,2,0)*t1_2(0)
+			      + t3dg_3(1,2,1)*t1_2(1)
+			      + t3dg_3(1,2,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t3dg_3(2,0,0)*t1_2(0)
+			      + t3dg_3(2,0,1)*t1_2(1)
+			      + t3dg_3(2,0,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t3dg_3(2,1,0)*t1_2(0)
+			      + t3dg_3(2,1,1)*t1_2(1)
+			      + t3dg_3(2,1,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t3dg_3(2,2,0)*t1_2(0)
+			      + t3dg_3(2,2,1)*t1_2(1)
+			      + t3dg_3(2,2,2)*t1_2(2))
+		,"T1(k)*T3dg(i,j,k)(2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,110 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t2_1(i,j)=t3dg_2(i,k,j)*t1_2(k);
+  test_for_zero(t2_1(0,0) - (t3dg_2(0,0,0)*t1_2(0)
+			     + t3dg_2(0,1,0)*t1_2(1)
+			     + t3dg_2(0,2,0)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_2(0,0,1)*t1_2(0)
+			     + t3dg_2(0,1,1)*t1_2(1)
+			     + t3dg_2(0,2,1)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_2(0,0,2)*t1_2(0)
+			     + t3dg_2(0,1,2)*t1_2(1)
+			     + t3dg_2(0,2,2)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_2(1,0,0)*t1_2(0)
+			     + t3dg_2(1,1,0)*t1_2(1)
+			     + t3dg_2(1,2,0)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_2(1,0,1)*t1_2(0)
+			     + t3dg_2(1,1,1)*t1_2(1)
+			     + t3dg_2(1,2,1)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_2(1,0,2)*t1_2(0)
+			     + t3dg_2(1,1,2)*t1_2(1)
+			     + t3dg_2(1,2,2)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_2(2,0,0)*t1_2(0)
+			     + t3dg_2(2,1,0)*t1_2(1)
+			     + t3dg_2(2,2,0)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_2(2,0,1)*t1_2(0)
+			     + t3dg_2(2,1,1)*t1_2(1)
+			     + t3dg_2(2,2,1)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_2(2,0,2)*t1_2(0)
+			     + t3dg_2(2,1,2)*t1_2(1)
+			     + t3dg_2(2,2,2)*t1_2(2))
+		,"T3dg(i,k,j)*T1(k)(2,2)");
+
+  t2_1(i,j)=t1_2(k)*t3dg_3(i,k,j);
+  test_for_zero(t2_1(0,0) - (t3dg_3(0,0,0)*t1_2(0)
+			     + t3dg_3(0,1,0)*t1_2(1)
+			     + t3dg_3(0,2,0)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(0,0)");
+  test_for_zero(t2_1(0,1) - (t3dg_3(0,0,1)*t1_2(0)
+			     + t3dg_3(0,1,1)*t1_2(1)
+			     + t3dg_3(0,2,1)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(0,1)");
+  test_for_zero(t2_1(0,2) - (t3dg_3(0,0,2)*t1_2(0)
+			     + t3dg_3(0,1,2)*t1_2(1)
+			     + t3dg_3(0,2,2)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(0,2)");
+  test_for_zero(t2_1(1,0) - (t3dg_3(1,0,0)*t1_2(0)
+			     + t3dg_3(1,1,0)*t1_2(1)
+			     + t3dg_3(1,2,0)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(1,0)");
+  test_for_zero(t2_1(1,1) - (t3dg_3(1,0,1)*t1_2(0)
+			     + t3dg_3(1,1,1)*t1_2(1)
+			     + t3dg_3(1,2,1)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(1,1)");
+  test_for_zero(t2_1(1,2) - (t3dg_3(1,0,2)*t1_2(0)
+			     + t3dg_3(1,1,2)*t1_2(1)
+			     + t3dg_3(1,2,2)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(1,2)");
+  test_for_zero(t2_1(2,0) - (t3dg_3(2,0,0)*t1_2(0)
+			     + t3dg_3(2,1,0)*t1_2(1)
+			     + t3dg_3(2,2,0)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(2,0)");
+  test_for_zero(t2_1(2,1) - (t3dg_3(2,0,1)*t1_2(0)
+			     + t3dg_3(2,1,1)*t1_2(1)
+			     + t3dg_3(2,2,1)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(2,1)");
+  test_for_zero(t2_1(2,2) - (t3dg_3(2,0,2)*t1_2(0)
+			     + t3dg_3(2,1,2)*t1_2(1)
+			     + t3dg_3(2,2,2)*t1_2(2))
+		,"T1(k)*T3dg(i,k,j)(2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,254 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,l)*t2_2(l,k);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0)*t2_2(0,0)
+				 + t3dg_2(0,0,1)*t2_2(1,0)
+				 + t3dg_2(0,0,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,0)*t2_2(0,1)
+				 + t3dg_2(0,0,1)*t2_2(1,1)
+				 + t3dg_2(0,0,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,0)*t2_2(0,2)
+				 + t3dg_2(0,0,1)*t2_2(1,2)
+				 + t3dg_2(0,0,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0)*t2_2(0,0)
+				 + t3dg_2(0,1,1)*t2_2(1,0)
+				 + t3dg_2(0,1,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,0)*t2_2(0,1)
+				 + t3dg_2(0,1,1)*t2_2(1,1)
+				 + t3dg_2(0,1,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,0)*t2_2(0,2)
+				 + t3dg_2(0,1,1)*t2_2(1,2)
+				 + t3dg_2(0,1,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0)*t2_2(0,0)
+				 + t3dg_2(0,2,1)*t2_2(1,0)
+				 + t3dg_2(0,2,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,0)*t2_2(0,1)
+				 + t3dg_2(0,2,1)*t2_2(1,1)
+				 + t3dg_2(0,2,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,0)*t2_2(0,2)
+				 + t3dg_2(0,2,1)*t2_2(1,2)
+				 + t3dg_2(0,2,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0)*t2_2(0,0)
+				 + t3dg_2(1,0,1)*t2_2(1,0)
+				 + t3dg_2(1,0,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,0)*t2_2(0,1)
+				 + t3dg_2(1,0,1)*t2_2(1,1)
+				 + t3dg_2(1,0,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,0)*t2_2(0,2)
+				 + t3dg_2(1,0,1)*t2_2(1,2)
+				 + t3dg_2(1,0,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0)*t2_2(0,0)
+				 + t3dg_2(1,1,1)*t2_2(1,0)
+				 + t3dg_2(1,1,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,0)*t2_2(0,1)
+				 + t3dg_2(1,1,1)*t2_2(1,1)
+				 + t3dg_2(1,1,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,0)*t2_2(0,2)
+				 + t3dg_2(1,1,1)*t2_2(1,2)
+				 + t3dg_2(1,1,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0)*t2_2(0,0)
+				 + t3dg_2(1,2,1)*t2_2(1,0)
+				 + t3dg_2(1,2,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,0)*t2_2(0,1)
+				 + t3dg_2(1,2,1)*t2_2(1,1)
+				 + t3dg_2(1,2,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,0)*t2_2(0,2)
+				 + t3dg_2(1,2,1)*t2_2(1,2)
+				 + t3dg_2(1,2,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0)*t2_2(0,0)
+				 + t3dg_2(2,0,1)*t2_2(1,0)
+				 + t3dg_2(2,0,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,0)*t2_2(0,1)
+				 + t3dg_2(2,0,1)*t2_2(1,1)
+				 + t3dg_2(2,0,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,0)*t2_2(0,2)
+				 + t3dg_2(2,0,1)*t2_2(1,2)
+				 + t3dg_2(2,0,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0)*t2_2(0,0)
+				 + t3dg_2(2,1,1)*t2_2(1,0)
+				 + t3dg_2(2,1,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,0)*t2_2(0,1)
+				 + t3dg_2(2,1,1)*t2_2(1,1)
+				 + t3dg_2(2,1,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,0)*t2_2(0,2)
+				 + t3dg_2(2,1,1)*t2_2(1,2)
+				 + t3dg_2(2,1,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0)*t2_2(0,0)
+				 + t3dg_2(2,2,1)*t2_2(1,0)
+				 + t3dg_2(2,2,2)*t2_2(2,0))
+		,"T3dg(i,j,l)*T2(l,k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,0)*t2_2(0,1)
+				 + t3dg_2(2,2,1)*t2_2(1,1)
+				 + t3dg_2(2,2,2)*t2_2(2,1))
+		,"T3dg(i,j,l)*T2(l,k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,0)*t2_2(0,2)
+				 + t3dg_2(2,2,1)*t2_2(1,2)
+				 + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(l,k)(2,2,2)");
+
+  t3dg_1(i,j,k)=t2_2(l,k)*t3dg_3(i,j,l);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_3(0,0,0)*t2_2(0,0)
+				 + t3dg_3(0,0,1)*t2_2(1,0)
+				 + t3dg_3(0,0,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_3(0,0,0)*t2_2(0,1)
+				 + t3dg_3(0,0,1)*t2_2(1,1)
+				 + t3dg_3(0,0,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_3(0,0,0)*t2_2(0,2)
+				 + t3dg_3(0,0,1)*t2_2(1,2)
+				 + t3dg_3(0,0,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_3(0,1,0)*t2_2(0,0)
+				 + t3dg_3(0,1,1)*t2_2(1,0)
+				 + t3dg_3(0,1,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_3(0,1,0)*t2_2(0,1)
+				 + t3dg_3(0,1,1)*t2_2(1,1)
+				 + t3dg_3(0,1,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_3(0,1,0)*t2_2(0,2)
+				 + t3dg_3(0,1,1)*t2_2(1,2)
+				 + t3dg_3(0,1,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_3(0,2,0)*t2_2(0,0)
+				 + t3dg_3(0,2,1)*t2_2(1,0)
+				 + t3dg_3(0,2,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_3(0,2,0)*t2_2(0,1)
+				 + t3dg_3(0,2,1)*t2_2(1,1)
+				 + t3dg_3(0,2,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_3(0,2,0)*t2_2(0,2)
+				 + t3dg_3(0,2,1)*t2_2(1,2)
+				 + t3dg_3(0,2,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_3(1,0,0)*t2_2(0,0)
+				 + t3dg_3(1,0,1)*t2_2(1,0)
+				 + t3dg_3(1,0,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_3(1,0,0)*t2_2(0,1)
+				 + t3dg_3(1,0,1)*t2_2(1,1)
+				 + t3dg_3(1,0,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_3(1,0,0)*t2_2(0,2)
+				 + t3dg_3(1,0,1)*t2_2(1,2)
+				 + t3dg_3(1,0,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_3(1,1,0)*t2_2(0,0)
+				 + t3dg_3(1,1,1)*t2_2(1,0)
+				 + t3dg_3(1,1,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_3(1,1,0)*t2_2(0,1)
+				 + t3dg_3(1,1,1)*t2_2(1,1)
+				 + t3dg_3(1,1,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_3(1,1,0)*t2_2(0,2)
+				 + t3dg_3(1,1,1)*t2_2(1,2)
+				 + t3dg_3(1,1,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_3(1,2,0)*t2_2(0,0)
+				 + t3dg_3(1,2,1)*t2_2(1,0)
+				 + t3dg_3(1,2,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_3(1,2,0)*t2_2(0,1)
+				 + t3dg_3(1,2,1)*t2_2(1,1)
+				 + t3dg_3(1,2,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_3(1,2,0)*t2_2(0,2)
+				 + t3dg_3(1,2,1)*t2_2(1,2)
+				 + t3dg_3(1,2,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_3(2,0,0)*t2_2(0,0)
+				 + t3dg_3(2,0,1)*t2_2(1,0)
+				 + t3dg_3(2,0,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_3(2,0,0)*t2_2(0,1)
+				 + t3dg_3(2,0,1)*t2_2(1,1)
+				 + t3dg_3(2,0,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_3(2,0,0)*t2_2(0,2)
+				 + t3dg_3(2,0,1)*t2_2(1,2)
+				 + t3dg_3(2,0,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_3(2,1,0)*t2_2(0,0)
+				 + t3dg_3(2,1,1)*t2_2(1,0)
+				 + t3dg_3(2,1,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_3(2,1,0)*t2_2(0,1)
+				 + t3dg_3(2,1,1)*t2_2(1,1)
+				 + t3dg_3(2,1,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_3(2,1,0)*t2_2(0,2)
+				 + t3dg_3(2,1,1)*t2_2(1,2)
+				 + t3dg_3(2,1,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_3(2,2,0)*t2_2(0,0)
+				 + t3dg_3(2,2,1)*t2_2(1,0)
+				 + t3dg_3(2,2,2)*t2_2(2,0))
+		,"T2(l,k)*T3dg(i,j,l)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_3(2,2,0)*t2_2(0,1)
+				 + t3dg_3(2,2,1)*t2_2(1,1)
+				 + t3dg_3(2,2,2)*t2_2(2,1))
+		,"T2(l,k)*T3dg(i,j,l)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_3(2,2,0)*t2_2(0,2)
+				 + t3dg_3(2,2,1)*t2_2(1,2)
+				 + t3dg_3(2,2,2)*t2_2(2,2))
+		,"T2(l,k)*T3dg(i,j,l)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,254 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,l)*t2_2(k,l);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0)*t2_2(0,0)
+				 + t3dg_2(0,0,1)*t2_2(0,1)
+				 + t3dg_2(0,0,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,0)*t2_2(1,0)
+				 + t3dg_2(0,0,1)*t2_2(1,1)
+				 + t3dg_2(0,0,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,0)*t2_2(2,0)
+				 + t3dg_2(0,0,1)*t2_2(2,1)
+				 + t3dg_2(0,0,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0)*t2_2(0,0)
+				 + t3dg_2(0,1,1)*t2_2(0,1)
+				 + t3dg_2(0,1,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,0)*t2_2(1,0)
+				 + t3dg_2(0,1,1)*t2_2(1,1)
+				 + t3dg_2(0,1,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,0)*t2_2(2,0)
+				 + t3dg_2(0,1,1)*t2_2(2,1)
+				 + t3dg_2(0,1,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0)*t2_2(0,0)
+				 + t3dg_2(0,2,1)*t2_2(0,1)
+				 + t3dg_2(0,2,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,0)*t2_2(1,0)
+				 + t3dg_2(0,2,1)*t2_2(1,1)
+				 + t3dg_2(0,2,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,0)*t2_2(2,0)
+				 + t3dg_2(0,2,1)*t2_2(2,1)
+				 + t3dg_2(0,2,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0)*t2_2(0,0)
+				 + t3dg_2(1,0,1)*t2_2(0,1)
+				 + t3dg_2(1,0,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,0)*t2_2(1,0)
+				 + t3dg_2(1,0,1)*t2_2(1,1)
+				 + t3dg_2(1,0,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,0)*t2_2(2,0)
+				 + t3dg_2(1,0,1)*t2_2(2,1)
+				 + t3dg_2(1,0,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0)*t2_2(0,0)
+				 + t3dg_2(1,1,1)*t2_2(0,1)
+				 + t3dg_2(1,1,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,0)*t2_2(1,0)
+				 + t3dg_2(1,1,1)*t2_2(1,1)
+				 + t3dg_2(1,1,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,0)*t2_2(2,0)
+				 + t3dg_2(1,1,1)*t2_2(2,1)
+				 + t3dg_2(1,1,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0)*t2_2(0,0)
+				 + t3dg_2(1,2,1)*t2_2(0,1)
+				 + t3dg_2(1,2,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,0)*t2_2(1,0)
+				 + t3dg_2(1,2,1)*t2_2(1,1)
+				 + t3dg_2(1,2,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,0)*t2_2(2,0)
+				 + t3dg_2(1,2,1)*t2_2(2,1)
+				 + t3dg_2(1,2,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0)*t2_2(0,0)
+				 + t3dg_2(2,0,1)*t2_2(0,1)
+				 + t3dg_2(2,0,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,0)*t2_2(1,0)
+				 + t3dg_2(2,0,1)*t2_2(1,1)
+				 + t3dg_2(2,0,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,0)*t2_2(2,0)
+				 + t3dg_2(2,0,1)*t2_2(2,1)
+				 + t3dg_2(2,0,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0)*t2_2(0,0)
+				 + t3dg_2(2,1,1)*t2_2(0,1)
+				 + t3dg_2(2,1,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,0)*t2_2(1,0)
+				 + t3dg_2(2,1,1)*t2_2(1,1)
+				 + t3dg_2(2,1,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,0)*t2_2(2,0)
+				 + t3dg_2(2,1,1)*t2_2(2,1)
+				 + t3dg_2(2,1,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0)*t2_2(0,0)
+				 + t3dg_2(2,2,1)*t2_2(0,1)
+				 + t3dg_2(2,2,2)*t2_2(0,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,0)*t2_2(1,0)
+				 + t3dg_2(2,2,1)*t2_2(1,1)
+				 + t3dg_2(2,2,2)*t2_2(1,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,0)*t2_2(2,0)
+				 + t3dg_2(2,2,1)*t2_2(2,1)
+				 + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(i,j,l)*T2(k,l)(2,2,2)");
+
+  t3dg_1(i,j,k)=t2_2(k,l)*t3dg_3(i,j,l);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_3(0,0,0)*t2_2(0,0)
+				 + t3dg_3(0,0,1)*t2_2(0,1)
+				 + t3dg_3(0,0,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_3(0,0,0)*t2_2(1,0)
+				 + t3dg_3(0,0,1)*t2_2(1,1)
+				 + t3dg_3(0,0,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_3(0,0,0)*t2_2(2,0)
+				 + t3dg_3(0,0,1)*t2_2(2,1)
+				 + t3dg_3(0,0,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_3(0,1,0)*t2_2(0,0)
+				 + t3dg_3(0,1,1)*t2_2(0,1)
+				 + t3dg_3(0,1,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_3(0,1,0)*t2_2(1,0)
+				 + t3dg_3(0,1,1)*t2_2(1,1)
+				 + t3dg_3(0,1,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_3(0,1,0)*t2_2(2,0)
+				 + t3dg_3(0,1,1)*t2_2(2,1)
+				 + t3dg_3(0,1,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_3(0,2,0)*t2_2(0,0)
+				 + t3dg_3(0,2,1)*t2_2(0,1)
+				 + t3dg_3(0,2,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_3(0,2,0)*t2_2(1,0)
+				 + t3dg_3(0,2,1)*t2_2(1,1)
+				 + t3dg_3(0,2,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_3(0,2,0)*t2_2(2,0)
+				 + t3dg_3(0,2,1)*t2_2(2,1)
+				 + t3dg_3(0,2,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_3(1,0,0)*t2_2(0,0)
+				 + t3dg_3(1,0,1)*t2_2(0,1)
+				 + t3dg_3(1,0,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_3(1,0,0)*t2_2(1,0)
+				 + t3dg_3(1,0,1)*t2_2(1,1)
+				 + t3dg_3(1,0,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_3(1,0,0)*t2_2(2,0)
+				 + t3dg_3(1,0,1)*t2_2(2,1)
+				 + t3dg_3(1,0,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_3(1,1,0)*t2_2(0,0)
+				 + t3dg_3(1,1,1)*t2_2(0,1)
+				 + t3dg_3(1,1,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_3(1,1,0)*t2_2(1,0)
+				 + t3dg_3(1,1,1)*t2_2(1,1)
+				 + t3dg_3(1,1,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_3(1,1,0)*t2_2(2,0)
+				 + t3dg_3(1,1,1)*t2_2(2,1)
+				 + t3dg_3(1,1,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_3(1,2,0)*t2_2(0,0)
+				 + t3dg_3(1,2,1)*t2_2(0,1)
+				 + t3dg_3(1,2,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_3(1,2,0)*t2_2(1,0)
+				 + t3dg_3(1,2,1)*t2_2(1,1)
+				 + t3dg_3(1,2,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_3(1,2,0)*t2_2(2,0)
+				 + t3dg_3(1,2,1)*t2_2(2,1)
+				 + t3dg_3(1,2,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_3(2,0,0)*t2_2(0,0)
+				 + t3dg_3(2,0,1)*t2_2(0,1)
+				 + t3dg_3(2,0,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_3(2,0,0)*t2_2(1,0)
+				 + t3dg_3(2,0,1)*t2_2(1,1)
+				 + t3dg_3(2,0,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_3(2,0,0)*t2_2(2,0)
+				 + t3dg_3(2,0,1)*t2_2(2,1)
+				 + t3dg_3(2,0,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_3(2,1,0)*t2_2(0,0)
+				 + t3dg_3(2,1,1)*t2_2(0,1)
+				 + t3dg_3(2,1,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_3(2,1,0)*t2_2(1,0)
+				 + t3dg_3(2,1,1)*t2_2(1,1)
+				 + t3dg_3(2,1,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_3(2,1,0)*t2_2(2,0)
+				 + t3dg_3(2,1,1)*t2_2(2,1)
+				 + t3dg_3(2,1,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_3(2,2,0)*t2_2(0,0)
+				 + t3dg_3(2,2,1)*t2_2(0,1)
+				 + t3dg_3(2,2,2)*t2_2(0,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_3(2,2,0)*t2_2(1,0)
+				 + t3dg_3(2,2,1)*t2_2(1,1)
+				 + t3dg_3(2,2,2)*t2_2(1,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_3(2,2,0)*t2_2(2,0)
+				 + t3dg_3(2,2,1)*t2_2(2,1)
+				 + t3dg_3(2,2,2)*t2_2(2,2))
+		,"T2(k,l)*T3dg(i,j,l)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(i,j,k)*t2_2(j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(0,1)
+			   + t3dg_2(0,0,2)*t2_2(0,2)
+			   + t3dg_2(0,1,0)*t2_2(1,0)
+			   + t3dg_2(0,1,1)*t2_2(1,1)
+			   + t3dg_2(0,1,2)*t2_2(1,2)
+			   + t3dg_2(0,2,0)*t2_2(2,0)
+			   + t3dg_2(0,2,1)*t2_2(2,1)
+			   + t3dg_2(0,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2_2(0,0)
+			   + t3dg_2(1,0,1)*t2_2(0,1)
+			   + t3dg_2(1,0,2)*t2_2(0,2)
+			   + t3dg_2(1,1,0)*t2_2(1,0)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(1,2)
+			   + t3dg_2(1,2,0)*t2_2(2,0)
+			   + t3dg_2(1,2,1)*t2_2(2,1)
+			   + t3dg_2(1,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2_2(0,0)
+			   + t3dg_2(2,0,1)*t2_2(0,1)
+			   + t3dg_2(2,0,2)*t2_2(0,2)
+			   + t3dg_2(2,1,0)*t2_2(1,0)
+			   + t3dg_2(2,1,1)*t2_2(1,1)
+			   + t3dg_2(2,1,2)*t2_2(1,2)
+			   + t3dg_2(2,2,0)*t2_2(2,0)
+			   + t3dg_2(2,2,1)*t2_2(2,1)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(j,k)(2)");
+
+  t1_1(i)=t2_2(j,k)*t3dg_2(i,j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(0,1)
+			   + t3dg_2(0,0,2)*t2_2(0,2)
+			   + t3dg_2(0,1,0)*t2_2(1,0)
+			   + t3dg_2(0,1,1)*t2_2(1,1)
+			   + t3dg_2(0,1,2)*t2_2(1,2)
+			   + t3dg_2(0,2,0)*t2_2(2,0)
+			   + t3dg_2(0,2,1)*t2_2(2,1)
+			   + t3dg_2(0,2,2)*t2_2(2,2))
+		,"T2(j,k)*T3dg(i,j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2_2(0,0)
+			   + t3dg_2(1,0,1)*t2_2(0,1)
+			   + t3dg_2(1,0,2)*t2_2(0,2)
+			   + t3dg_2(1,1,0)*t2_2(1,0)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(1,2)
+			   + t3dg_2(1,2,0)*t2_2(2,0)
+			   + t3dg_2(1,2,1)*t2_2(2,1)
+			   + t3dg_2(1,2,2)*t2_2(2,2))
+		,"T2(j,k)*T3dg(i,j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2_2(0,0)
+			   + t3dg_2(2,0,1)*t2_2(0,1)
+			   + t3dg_2(2,0,2)*t2_2(0,2)
+			   + t3dg_2(2,1,0)*t2_2(1,0)
+			   + t3dg_2(2,1,1)*t2_2(1,1)
+			   + t3dg_2(2,1,2)*t2_2(1,2)
+			   + t3dg_2(2,2,0)*t2_2(2,0)
+			   + t3dg_2(2,2,1)*t2_2(2,1)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T2(j,k)*T3dg(i,j,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(i,j,k)*t2_2(k,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(1,0)
+			   + t3dg_2(0,0,2)*t2_2(2,0)
+			   + t3dg_2(0,1,0)*t2_2(0,1)
+			   + t3dg_2(0,1,1)*t2_2(1,1)
+			   + t3dg_2(0,1,2)*t2_2(2,1)
+			   + t3dg_2(0,2,0)*t2_2(0,2)
+			   + t3dg_2(0,2,1)*t2_2(1,2)
+			   + t3dg_2(0,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(k,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2_2(0,0)
+			   + t3dg_2(1,0,1)*t2_2(1,0)
+			   + t3dg_2(1,0,2)*t2_2(2,0)
+			   + t3dg_2(1,1,0)*t2_2(0,1)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(2,1)
+			   + t3dg_2(1,2,0)*t2_2(0,2)
+			   + t3dg_2(1,2,1)*t2_2(1,2)
+			   + t3dg_2(1,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(k,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2_2(0,0)
+			   + t3dg_2(2,0,1)*t2_2(1,0)
+			   + t3dg_2(2,0,2)*t2_2(2,0)
+			   + t3dg_2(2,1,0)*t2_2(0,1)
+			   + t3dg_2(2,1,1)*t2_2(1,1)
+			   + t3dg_2(2,1,2)*t2_2(2,1)
+			   + t3dg_2(2,2,0)*t2_2(0,2)
+			   + t3dg_2(2,2,1)*t2_2(1,2)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(i,j,k)*T2(k,j)(2)");
+
+  t1_1(i)=t2_2(k,j)*t3dg_2(i,j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(1,0)
+			   + t3dg_2(0,0,2)*t2_2(2,0)
+			   + t3dg_2(0,1,0)*t2_2(0,1)
+			   + t3dg_2(0,1,1)*t2_2(1,1)
+			   + t3dg_2(0,1,2)*t2_2(2,1)
+			   + t3dg_2(0,2,0)*t2_2(0,2)
+			   + t3dg_2(0,2,1)*t2_2(1,2)
+			   + t3dg_2(0,2,2)*t2_2(2,2))
+		,"T2(k,j)*T3dg(i,j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2_2(0,0)
+			   + t3dg_2(1,0,1)*t2_2(1,0)
+			   + t3dg_2(1,0,2)*t2_2(2,0)
+			   + t3dg_2(1,1,0)*t2_2(0,1)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(2,1)
+			   + t3dg_2(1,2,0)*t2_2(0,2)
+			   + t3dg_2(1,2,1)*t2_2(1,2)
+			   + t3dg_2(1,2,2)*t2_2(2,2))
+		,"T2(k,j)*T3dg(i,j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2_2(0,0)
+			   + t3dg_2(2,0,1)*t2_2(1,0)
+			   + t3dg_2(2,0,2)*t2_2(2,0)
+			   + t3dg_2(2,1,0)*t2_2(0,1)
+			   + t3dg_2(2,1,1)*t2_2(1,1)
+			   + t3dg_2(2,1,2)*t2_2(2,1)
+			   + t3dg_2(2,2,0)*t2_2(0,2)
+			   + t3dg_2(2,2,1)*t2_2(1,2)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T2(k,j)*T3dg(i,j,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,i,k)*t2_2(j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(0,1)
+			   + t3dg_2(0,0,2)*t2_2(0,2)
+			   + t3dg_2(1,0,0)*t2_2(1,0)
+			   + t3dg_2(1,0,1)*t2_2(1,1)
+			   + t3dg_2(1,0,2)*t2_2(1,2)
+			   + t3dg_2(2,0,0)*t2_2(2,0)
+			   + t3dg_2(2,0,1)*t2_2(2,1)
+			   + t3dg_2(2,0,2)*t2_2(2,2))
+		,"T3dg(j,i,k)*T2(j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(0,1)
+			   + t3dg_2(0,1,2)*t2_2(0,2)
+			   + t3dg_2(1,1,0)*t2_2(1,0)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(1,2)
+			   + t3dg_2(2,1,0)*t2_2(2,0)
+			   + t3dg_2(2,1,1)*t2_2(2,1)
+			   + t3dg_2(2,1,2)*t2_2(2,2))
+		,"T3dg(j,i,k)*T2(j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2_2(0,0)
+			   + t3dg_2(0,2,1)*t2_2(0,1)
+			   + t3dg_2(0,2,2)*t2_2(0,2)
+			   + t3dg_2(1,2,0)*t2_2(1,0)
+			   + t3dg_2(1,2,1)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(1,2)
+			   + t3dg_2(2,2,0)*t2_2(2,0)
+			   + t3dg_2(2,2,1)*t2_2(2,1)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(j,i,k)*T2(j,k)(2)");
+
+  t1_1(i)=t2_2(j,k)*t3dg_2(j,i,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(0,1)
+			   + t3dg_2(0,0,2)*t2_2(0,2)
+			   + t3dg_2(1,0,0)*t2_2(1,0)
+			   + t3dg_2(1,0,1)*t2_2(1,1)
+			   + t3dg_2(1,0,2)*t2_2(1,2)
+			   + t3dg_2(2,0,0)*t2_2(2,0)
+			   + t3dg_2(2,0,1)*t2_2(2,1)
+			   + t3dg_2(2,0,2)*t2_2(2,2))
+		,"T2(j,k)*T3dg(j,i,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(0,1)
+			   + t3dg_2(0,1,2)*t2_2(0,2)
+			   + t3dg_2(1,1,0)*t2_2(1,0)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(1,2)
+			   + t3dg_2(2,1,0)*t2_2(2,0)
+			   + t3dg_2(2,1,1)*t2_2(2,1)
+			   + t3dg_2(2,1,2)*t2_2(2,2))
+		,"T2(j,k)*T3dg(j,i,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2_2(0,0)
+			   + t3dg_2(0,2,1)*t2_2(0,1)
+			   + t3dg_2(0,2,2)*t2_2(0,2)
+			   + t3dg_2(1,2,0)*t2_2(1,0)
+			   + t3dg_2(1,2,1)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(1,2)
+			   + t3dg_2(2,2,0)*t2_2(2,0)
+			   + t3dg_2(2,2,1)*t2_2(2,1)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T2(j,k)*T3dg(j,i,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXIX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXIX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,254 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXIX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,l)*t2s_2(k,l);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+				 + t3dg_2(0,0,1)*t2s_2(0,1)
+				 + t3dg_2(0,0,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,0)*t2s_2(1,0)
+				 + t3dg_2(0,0,1)*t2s_2(1,1)
+				 + t3dg_2(0,0,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,0)*t2s_2(2,0)
+				 + t3dg_2(0,0,1)*t2s_2(2,1)
+				 + t3dg_2(0,0,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0)*t2s_2(0,0)
+				 + t3dg_2(0,1,1)*t2s_2(0,1)
+				 + t3dg_2(0,1,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,0)*t2s_2(1,0)
+				 + t3dg_2(0,1,1)*t2s_2(1,1)
+				 + t3dg_2(0,1,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,0)*t2s_2(2,0)
+				 + t3dg_2(0,1,1)*t2s_2(2,1)
+				 + t3dg_2(0,1,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0)*t2s_2(0,0)
+				 + t3dg_2(0,2,1)*t2s_2(0,1)
+				 + t3dg_2(0,2,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,0)*t2s_2(1,0)
+				 + t3dg_2(0,2,1)*t2s_2(1,1)
+				 + t3dg_2(0,2,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,0)*t2s_2(2,0)
+				 + t3dg_2(0,2,1)*t2s_2(2,1)
+				 + t3dg_2(0,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0)*t2s_2(0,0)
+				 + t3dg_2(1,0,1)*t2s_2(0,1)
+				 + t3dg_2(1,0,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,0)*t2s_2(1,0)
+				 + t3dg_2(1,0,1)*t2s_2(1,1)
+				 + t3dg_2(1,0,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,0)*t2s_2(2,0)
+				 + t3dg_2(1,0,1)*t2s_2(2,1)
+				 + t3dg_2(1,0,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0)*t2s_2(0,0)
+				 + t3dg_2(1,1,1)*t2s_2(0,1)
+				 + t3dg_2(1,1,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,0)*t2s_2(1,0)
+				 + t3dg_2(1,1,1)*t2s_2(1,1)
+				 + t3dg_2(1,1,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,0)*t2s_2(2,0)
+				 + t3dg_2(1,1,1)*t2s_2(2,1)
+				 + t3dg_2(1,1,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0)*t2s_2(0,0)
+				 + t3dg_2(1,2,1)*t2s_2(0,1)
+				 + t3dg_2(1,2,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,0)*t2s_2(1,0)
+				 + t3dg_2(1,2,1)*t2s_2(1,1)
+				 + t3dg_2(1,2,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,0)*t2s_2(2,0)
+				 + t3dg_2(1,2,1)*t2s_2(2,1)
+				 + t3dg_2(1,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0)*t2s_2(0,0)
+				 + t3dg_2(2,0,1)*t2s_2(0,1)
+				 + t3dg_2(2,0,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,0)*t2s_2(1,0)
+				 + t3dg_2(2,0,1)*t2s_2(1,1)
+				 + t3dg_2(2,0,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,0)*t2s_2(2,0)
+				 + t3dg_2(2,0,1)*t2s_2(2,1)
+				 + t3dg_2(2,0,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0)*t2s_2(0,0)
+				 + t3dg_2(2,1,1)*t2s_2(0,1)
+				 + t3dg_2(2,1,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,0)*t2s_2(1,0)
+				 + t3dg_2(2,1,1)*t2s_2(1,1)
+				 + t3dg_2(2,1,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,0)*t2s_2(2,0)
+				 + t3dg_2(2,1,1)*t2s_2(2,1)
+				 + t3dg_2(2,1,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0)*t2s_2(0,0)
+				 + t3dg_2(2,2,1)*t2s_2(0,1)
+				 + t3dg_2(2,2,2)*t2s_2(0,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,0)*t2s_2(1,0)
+				 + t3dg_2(2,2,1)*t2s_2(1,1)
+				 + t3dg_2(2,2,2)*t2s_2(1,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,0)*t2s_2(2,0)
+				 + t3dg_2(2,2,1)*t2s_2(2,1)
+				 + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(k,l)(2,2,2)");
+
+  t3dg_1(i,j,k)=t2s_2(k,l)*t3dg_3(i,j,l);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_3(0,0,0)*t2s_2(0,0)
+				 + t3dg_3(0,0,1)*t2s_2(0,1)
+				 + t3dg_3(0,0,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_3(0,0,0)*t2s_2(1,0)
+				 + t3dg_3(0,0,1)*t2s_2(1,1)
+				 + t3dg_3(0,0,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_3(0,0,0)*t2s_2(2,0)
+				 + t3dg_3(0,0,1)*t2s_2(2,1)
+				 + t3dg_3(0,0,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_3(0,1,0)*t2s_2(0,0)
+				 + t3dg_3(0,1,1)*t2s_2(0,1)
+				 + t3dg_3(0,1,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_3(0,1,0)*t2s_2(1,0)
+				 + t3dg_3(0,1,1)*t2s_2(1,1)
+				 + t3dg_3(0,1,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_3(0,1,0)*t2s_2(2,0)
+				 + t3dg_3(0,1,1)*t2s_2(2,1)
+				 + t3dg_3(0,1,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_3(0,2,0)*t2s_2(0,0)
+				 + t3dg_3(0,2,1)*t2s_2(0,1)
+				 + t3dg_3(0,2,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_3(0,2,0)*t2s_2(1,0)
+				 + t3dg_3(0,2,1)*t2s_2(1,1)
+				 + t3dg_3(0,2,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_3(0,2,0)*t2s_2(2,0)
+				 + t3dg_3(0,2,1)*t2s_2(2,1)
+				 + t3dg_3(0,2,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_3(1,0,0)*t2s_2(0,0)
+				 + t3dg_3(1,0,1)*t2s_2(0,1)
+				 + t3dg_3(1,0,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_3(1,0,0)*t2s_2(1,0)
+				 + t3dg_3(1,0,1)*t2s_2(1,1)
+				 + t3dg_3(1,0,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_3(1,0,0)*t2s_2(2,0)
+				 + t3dg_3(1,0,1)*t2s_2(2,1)
+				 + t3dg_3(1,0,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_3(1,1,0)*t2s_2(0,0)
+				 + t3dg_3(1,1,1)*t2s_2(0,1)
+				 + t3dg_3(1,1,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_3(1,1,0)*t2s_2(1,0)
+				 + t3dg_3(1,1,1)*t2s_2(1,1)
+				 + t3dg_3(1,1,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_3(1,1,0)*t2s_2(2,0)
+				 + t3dg_3(1,1,1)*t2s_2(2,1)
+				 + t3dg_3(1,1,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_3(1,2,0)*t2s_2(0,0)
+				 + t3dg_3(1,2,1)*t2s_2(0,1)
+				 + t3dg_3(1,2,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_3(1,2,0)*t2s_2(1,0)
+				 + t3dg_3(1,2,1)*t2s_2(1,1)
+				 + t3dg_3(1,2,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_3(1,2,0)*t2s_2(2,0)
+				 + t3dg_3(1,2,1)*t2s_2(2,1)
+				 + t3dg_3(1,2,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_3(2,0,0)*t2s_2(0,0)
+				 + t3dg_3(2,0,1)*t2s_2(0,1)
+				 + t3dg_3(2,0,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_3(2,0,0)*t2s_2(1,0)
+				 + t3dg_3(2,0,1)*t2s_2(1,1)
+				 + t3dg_3(2,0,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_3(2,0,0)*t2s_2(2,0)
+				 + t3dg_3(2,0,1)*t2s_2(2,1)
+				 + t3dg_3(2,0,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_3(2,1,0)*t2s_2(0,0)
+				 + t3dg_3(2,1,1)*t2s_2(0,1)
+				 + t3dg_3(2,1,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_3(2,1,0)*t2s_2(1,0)
+				 + t3dg_3(2,1,1)*t2s_2(1,1)
+				 + t3dg_3(2,1,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_3(2,1,0)*t2s_2(2,0)
+				 + t3dg_3(2,1,1)*t2s_2(2,1)
+				 + t3dg_3(2,1,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_3(2,2,0)*t2s_2(0,0)
+				 + t3dg_3(2,2,1)*t2s_2(0,1)
+				 + t3dg_3(2,2,2)*t2s_2(0,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_3(2,2,0)*t2s_2(1,0)
+				 + t3dg_3(2,2,1)*t2s_2(1,1)
+				 + t3dg_3(2,2,2)*t2s_2(1,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_3(2,2,0)*t2s_2(2,0)
+				 + t3dg_3(2,2,1)*t2s_2(2,1)
+				 + t3dg_3(2,2,2)*t2s_2(2,2))
+		,"T2s(k,l)*T3dg(i,j,l)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,i,k)*t2_2(k,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(1,0)
+			   + t3dg_2(0,0,2)*t2_2(2,0)
+			   + t3dg_2(1,0,0)*t2_2(0,1)
+			   + t3dg_2(1,0,1)*t2_2(1,1)
+			   + t3dg_2(1,0,2)*t2_2(2,1)
+			   + t3dg_2(2,0,0)*t2_2(0,2)
+			   + t3dg_2(2,0,1)*t2_2(1,2)
+			   + t3dg_2(2,0,2)*t2_2(2,2))
+		,"T3dg(j,i,k)*T2(k,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(1,0)
+			   + t3dg_2(0,1,2)*t2_2(2,0)
+			   + t3dg_2(1,1,0)*t2_2(0,1)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(2,1)
+			   + t3dg_2(2,1,0)*t2_2(0,2)
+			   + t3dg_2(2,1,1)*t2_2(1,2)
+			   + t3dg_2(2,1,2)*t2_2(2,2))
+		,"T3dg(j,i,k)*T2(k,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2_2(0,0)
+			   + t3dg_2(0,2,1)*t2_2(1,0)
+			   + t3dg_2(0,2,2)*t2_2(2,0)
+			   + t3dg_2(1,2,0)*t2_2(0,1)
+			   + t3dg_2(1,2,1)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(2,1)
+			   + t3dg_2(2,2,0)*t2_2(0,2)
+			   + t3dg_2(2,2,1)*t2_2(1,2)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(j,i,k)*T2(k,j)(2)");
+
+  t1_1(i)=t2_2(k,j)*t3dg_2(j,i,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,0,1)*t2_2(1,0)
+			   + t3dg_2(0,0,2)*t2_2(2,0)
+			   + t3dg_2(1,0,0)*t2_2(0,1)
+			   + t3dg_2(1,0,1)*t2_2(1,1)
+			   + t3dg_2(1,0,2)*t2_2(2,1)
+			   + t3dg_2(2,0,0)*t2_2(0,2)
+			   + t3dg_2(2,0,1)*t2_2(1,2)
+			   + t3dg_2(2,0,2)*t2_2(2,2))
+		,"T2(k,j)*T3dg(j,i,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(1,0)
+			   + t3dg_2(0,1,2)*t2_2(2,0)
+			   + t3dg_2(1,1,0)*t2_2(0,1)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,1,2)*t2_2(2,1)
+			   + t3dg_2(2,1,0)*t2_2(0,2)
+			   + t3dg_2(2,1,1)*t2_2(1,2)
+			   + t3dg_2(2,1,2)*t2_2(2,2))
+		,"T2(k,j)*T3dg(j,i,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2_2(0,0)
+			   + t3dg_2(0,2,1)*t2_2(1,0)
+			   + t3dg_2(0,2,2)*t2_2(2,0)
+			   + t3dg_2(1,2,0)*t2_2(0,1)
+			   + t3dg_2(1,2,1)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(2,1)
+			   + t3dg_2(2,2,0)*t2_2(0,2)
+			   + t3dg_2(2,2,1)*t2_2(1,2)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T2(k,j)*T3dg(j,i,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXVI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXVI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXVI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,k,i)*t2_2(j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,1,0)*t2_2(0,1)
+			   + t3dg_2(0,2,0)*t2_2(0,2)
+			   + t3dg_2(1,0,0)*t2_2(1,0)
+			   + t3dg_2(1,1,0)*t2_2(1,1)
+			   + t3dg_2(1,2,0)*t2_2(1,2)
+			   + t3dg_2(2,0,0)*t2_2(2,0)
+			   + t3dg_2(2,1,0)*t2_2(2,1)
+			   + t3dg_2(2,2,0)*t2_2(2,2))
+		,"T3dg(j,k,i)*T2(j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(0,1)
+			   + t3dg_2(0,2,1)*t2_2(0,2)
+			   + t3dg_2(1,0,1)*t2_2(1,0)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,2,1)*t2_2(1,2)
+			   + t3dg_2(2,0,1)*t2_2(2,0)
+			   + t3dg_2(2,1,1)*t2_2(2,1)
+			   + t3dg_2(2,2,1)*t2_2(2,2))
+		,"T3dg(j,k,i)*T2(j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2_2(0,0)
+			   + t3dg_2(0,1,2)*t2_2(0,1)
+			   + t3dg_2(0,2,2)*t2_2(0,2)
+			   + t3dg_2(1,0,2)*t2_2(1,0)
+			   + t3dg_2(1,1,2)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(1,2)
+			   + t3dg_2(2,0,2)*t2_2(2,0)
+			   + t3dg_2(2,1,2)*t2_2(2,1)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(j,k,i)*T2(j,k)(2)");
+
+  t1_1(i)=t2_2(j,k)*t3dg_2(j,k,i);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,1,0)*t2_2(0,1)
+			   + t3dg_2(0,2,0)*t2_2(0,2)
+			   + t3dg_2(1,0,0)*t2_2(1,0)
+			   + t3dg_2(1,1,0)*t2_2(1,1)
+			   + t3dg_2(1,2,0)*t2_2(1,2)
+			   + t3dg_2(2,0,0)*t2_2(2,0)
+			   + t3dg_2(2,1,0)*t2_2(2,1)
+			   + t3dg_2(2,2,0)*t2_2(2,2))
+		,"T2(j,k)*T3dg(j,k,i)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(0,1)
+			   + t3dg_2(0,2,1)*t2_2(0,2)
+			   + t3dg_2(1,0,1)*t2_2(1,0)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,2,1)*t2_2(1,2)
+			   + t3dg_2(2,0,1)*t2_2(2,0)
+			   + t3dg_2(2,1,1)*t2_2(2,1)
+			   + t3dg_2(2,2,1)*t2_2(2,2))
+		,"T2(j,k)*T3dg(j,k,i)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2_2(0,0)
+			   + t3dg_2(0,1,2)*t2_2(0,1)
+			   + t3dg_2(0,2,2)*t2_2(0,2)
+			   + t3dg_2(1,0,2)*t2_2(1,0)
+			   + t3dg_2(1,1,2)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(1,2)
+			   + t3dg_2(2,0,2)*t2_2(2,0)
+			   + t3dg_2(2,1,2)*t2_2(2,1)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T2(j,k)*T3dg(j,k,i)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXVII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXVII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXVII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,k,i)*t2_2(k,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,1,0)*t2_2(1,0)
+			   + t3dg_2(0,2,0)*t2_2(2,0)
+			   + t3dg_2(1,0,0)*t2_2(0,1)
+			   + t3dg_2(1,1,0)*t2_2(1,1)
+			   + t3dg_2(1,2,0)*t2_2(2,1)
+			   + t3dg_2(2,0,0)*t2_2(0,2)
+			   + t3dg_2(2,1,0)*t2_2(1,2)
+			   + t3dg_2(2,2,0)*t2_2(2,2))
+		,"T3dg(j,k,i)*T2(k,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(1,0)
+			   + t3dg_2(0,2,1)*t2_2(2,0)
+			   + t3dg_2(1,0,1)*t2_2(0,1)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,2,1)*t2_2(2,1)
+			   + t3dg_2(2,0,1)*t2_2(0,2)
+			   + t3dg_2(2,1,1)*t2_2(1,2)
+			   + t3dg_2(2,2,1)*t2_2(2,2))
+		,"T3dg(j,k,i)*T2(k,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2_2(0,0)
+			   + t3dg_2(0,1,2)*t2_2(1,0)
+			   + t3dg_2(0,2,2)*t2_2(2,0)
+			   + t3dg_2(1,0,2)*t2_2(0,1)
+			   + t3dg_2(1,1,2)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(2,1)
+			   + t3dg_2(2,0,2)*t2_2(0,2)
+			   + t3dg_2(2,1,2)*t2_2(1,2)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T3dg(j,k,i)*T2(k,j)(2)");
+
+  t1_1(i)=t2_2(k,j)*t3dg_2(j,k,i);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2_2(0,0)
+			   + t3dg_2(0,1,0)*t2_2(1,0)
+			   + t3dg_2(0,2,0)*t2_2(2,0)
+			   + t3dg_2(1,0,0)*t2_2(0,1)
+			   + t3dg_2(1,1,0)*t2_2(1,1)
+			   + t3dg_2(1,2,0)*t2_2(2,1)
+			   + t3dg_2(2,0,0)*t2_2(0,2)
+			   + t3dg_2(2,1,0)*t2_2(1,2)
+			   + t3dg_2(2,2,0)*t2_2(2,2))
+		,"T2(k,j)*T3dg(j,k,i)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2_2(0,0)
+			   + t3dg_2(0,1,1)*t2_2(1,0)
+			   + t3dg_2(0,2,1)*t2_2(2,0)
+			   + t3dg_2(1,0,1)*t2_2(0,1)
+			   + t3dg_2(1,1,1)*t2_2(1,1)
+			   + t3dg_2(1,2,1)*t2_2(2,1)
+			   + t3dg_2(2,0,1)*t2_2(0,2)
+			   + t3dg_2(2,1,1)*t2_2(1,2)
+			   + t3dg_2(2,2,1)*t2_2(2,2))
+		,"T2(k,j)*T3dg(j,k,i)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2_2(0,0)
+			   + t3dg_2(0,1,2)*t2_2(1,0)
+			   + t3dg_2(0,2,2)*t2_2(2,0)
+			   + t3dg_2(1,0,2)*t2_2(0,1)
+			   + t3dg_2(1,1,2)*t2_2(1,1)
+			   + t3dg_2(1,2,2)*t2_2(2,1)
+			   + t3dg_2(2,0,2)*t2_2(0,2)
+			   + t3dg_2(2,1,2)*t2_2(1,2)
+			   + t3dg_2(2,2,2)*t2_2(2,2))
+		,"T2(k,j)*T3dg(j,k,i)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXVIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXVIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,254 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXVIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t3dg_1(i,j,k)=t3dg_2(i,j,l)*t2s_2(l,k);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+				 + t3dg_2(0,0,1)*t2s_2(1,0)
+				 + t3dg_2(0,0,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_2(0,0,0)*t2s_2(0,1)
+				 + t3dg_2(0,0,1)*t2s_2(1,1)
+				 + t3dg_2(0,0,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_2(0,0,0)*t2s_2(0,2)
+				 + t3dg_2(0,0,1)*t2s_2(1,2)
+				 + t3dg_2(0,0,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_2(0,1,0)*t2s_2(0,0)
+				 + t3dg_2(0,1,1)*t2s_2(1,0)
+				 + t3dg_2(0,1,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_2(0,1,0)*t2s_2(0,1)
+				 + t3dg_2(0,1,1)*t2s_2(1,1)
+				 + t3dg_2(0,1,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_2(0,1,0)*t2s_2(0,2)
+				 + t3dg_2(0,1,1)*t2s_2(1,2)
+				 + t3dg_2(0,1,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_2(0,2,0)*t2s_2(0,0)
+				 + t3dg_2(0,2,1)*t2s_2(1,0)
+				 + t3dg_2(0,2,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_2(0,2,0)*t2s_2(0,1)
+				 + t3dg_2(0,2,1)*t2s_2(1,1)
+				 + t3dg_2(0,2,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_2(0,2,0)*t2s_2(0,2)
+				 + t3dg_2(0,2,1)*t2s_2(1,2)
+				 + t3dg_2(0,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_2(1,0,0)*t2s_2(0,0)
+				 + t3dg_2(1,0,1)*t2s_2(1,0)
+				 + t3dg_2(1,0,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_2(1,0,0)*t2s_2(0,1)
+				 + t3dg_2(1,0,1)*t2s_2(1,1)
+				 + t3dg_2(1,0,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_2(1,0,0)*t2s_2(0,2)
+				 + t3dg_2(1,0,1)*t2s_2(1,2)
+				 + t3dg_2(1,0,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_2(1,1,0)*t2s_2(0,0)
+				 + t3dg_2(1,1,1)*t2s_2(1,0)
+				 + t3dg_2(1,1,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_2(1,1,0)*t2s_2(0,1)
+				 + t3dg_2(1,1,1)*t2s_2(1,1)
+				 + t3dg_2(1,1,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_2(1,1,0)*t2s_2(0,2)
+				 + t3dg_2(1,1,1)*t2s_2(1,2)
+				 + t3dg_2(1,1,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_2(1,2,0)*t2s_2(0,0)
+				 + t3dg_2(1,2,1)*t2s_2(1,0)
+				 + t3dg_2(1,2,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_2(1,2,0)*t2s_2(0,1)
+				 + t3dg_2(1,2,1)*t2s_2(1,1)
+				 + t3dg_2(1,2,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_2(1,2,0)*t2s_2(0,2)
+				 + t3dg_2(1,2,1)*t2s_2(1,2)
+				 + t3dg_2(1,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_2(2,0,0)*t2s_2(0,0)
+				 + t3dg_2(2,0,1)*t2s_2(1,0)
+				 + t3dg_2(2,0,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_2(2,0,0)*t2s_2(0,1)
+				 + t3dg_2(2,0,1)*t2s_2(1,1)
+				 + t3dg_2(2,0,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_2(2,0,0)*t2s_2(0,2)
+				 + t3dg_2(2,0,1)*t2s_2(1,2)
+				 + t3dg_2(2,0,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_2(2,1,0)*t2s_2(0,0)
+				 + t3dg_2(2,1,1)*t2s_2(1,0)
+				 + t3dg_2(2,1,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_2(2,1,0)*t2s_2(0,1)
+				 + t3dg_2(2,1,1)*t2s_2(1,1)
+				 + t3dg_2(2,1,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_2(2,1,0)*t2s_2(0,2)
+				 + t3dg_2(2,1,1)*t2s_2(1,2)
+				 + t3dg_2(2,1,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_2(2,2,0)*t2s_2(0,0)
+				 + t3dg_2(2,2,1)*t2s_2(1,0)
+				 + t3dg_2(2,2,2)*t2s_2(2,0))
+		,"T3dg(i,j,l)*T2s(l,k)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_2(2,2,0)*t2s_2(0,1)
+				 + t3dg_2(2,2,1)*t2s_2(1,1)
+				 + t3dg_2(2,2,2)*t2s_2(2,1))
+		,"T3dg(i,j,l)*T2s(l,k)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_2(2,2,0)*t2s_2(0,2)
+				 + t3dg_2(2,2,1)*t2s_2(1,2)
+				 + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,l)*T2s(l,k)(2,2,2)");
+
+  t3dg_1(i,j,k)=t2s_2(l,k)*t3dg_3(i,j,l);
+  test_for_zero(t3dg_1(0,0,0) - (t3dg_3(0,0,0)*t2s_2(0,0)
+				 + t3dg_3(0,0,1)*t2s_2(1,0)
+				 + t3dg_3(0,0,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t3dg_3(0,0,0)*t2s_2(0,1)
+				 + t3dg_3(0,0,1)*t2s_2(1,1)
+				 + t3dg_3(0,0,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t3dg_3(0,0,0)*t2s_2(0,2)
+				 + t3dg_3(0,0,1)*t2s_2(1,2)
+				 + t3dg_3(0,0,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t3dg_3(0,1,0)*t2s_2(0,0)
+				 + t3dg_3(0,1,1)*t2s_2(1,0)
+				 + t3dg_3(0,1,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t3dg_3(0,1,0)*t2s_2(0,1)
+				 + t3dg_3(0,1,1)*t2s_2(1,1)
+				 + t3dg_3(0,1,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t3dg_3(0,1,0)*t2s_2(0,2)
+				 + t3dg_3(0,1,1)*t2s_2(1,2)
+				 + t3dg_3(0,1,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t3dg_3(0,2,0)*t2s_2(0,0)
+				 + t3dg_3(0,2,1)*t2s_2(1,0)
+				 + t3dg_3(0,2,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t3dg_3(0,2,0)*t2s_2(0,1)
+				 + t3dg_3(0,2,1)*t2s_2(1,1)
+				 + t3dg_3(0,2,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t3dg_3(0,2,0)*t2s_2(0,2)
+				 + t3dg_3(0,2,1)*t2s_2(1,2)
+				 + t3dg_3(0,2,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t3dg_3(1,0,0)*t2s_2(0,0)
+				 + t3dg_3(1,0,1)*t2s_2(1,0)
+				 + t3dg_3(1,0,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t3dg_3(1,0,0)*t2s_2(0,1)
+				 + t3dg_3(1,0,1)*t2s_2(1,1)
+				 + t3dg_3(1,0,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t3dg_3(1,0,0)*t2s_2(0,2)
+				 + t3dg_3(1,0,1)*t2s_2(1,2)
+				 + t3dg_3(1,0,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t3dg_3(1,1,0)*t2s_2(0,0)
+				 + t3dg_3(1,1,1)*t2s_2(1,0)
+				 + t3dg_3(1,1,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t3dg_3(1,1,0)*t2s_2(0,1)
+				 + t3dg_3(1,1,1)*t2s_2(1,1)
+				 + t3dg_3(1,1,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t3dg_3(1,1,0)*t2s_2(0,2)
+				 + t3dg_3(1,1,1)*t2s_2(1,2)
+				 + t3dg_3(1,1,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t3dg_3(1,2,0)*t2s_2(0,0)
+				 + t3dg_3(1,2,1)*t2s_2(1,0)
+				 + t3dg_3(1,2,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t3dg_3(1,2,0)*t2s_2(0,1)
+				 + t3dg_3(1,2,1)*t2s_2(1,1)
+				 + t3dg_3(1,2,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t3dg_3(1,2,0)*t2s_2(0,2)
+				 + t3dg_3(1,2,1)*t2s_2(1,2)
+				 + t3dg_3(1,2,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t3dg_3(2,0,0)*t2s_2(0,0)
+				 + t3dg_3(2,0,1)*t2s_2(1,0)
+				 + t3dg_3(2,0,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t3dg_3(2,0,0)*t2s_2(0,1)
+				 + t3dg_3(2,0,1)*t2s_2(1,1)
+				 + t3dg_3(2,0,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t3dg_3(2,0,0)*t2s_2(0,2)
+				 + t3dg_3(2,0,1)*t2s_2(1,2)
+				 + t3dg_3(2,0,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t3dg_3(2,1,0)*t2s_2(0,0)
+				 + t3dg_3(2,1,1)*t2s_2(1,0)
+				 + t3dg_3(2,1,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t3dg_3(2,1,0)*t2s_2(0,1)
+				 + t3dg_3(2,1,1)*t2s_2(1,1)
+				 + t3dg_3(2,1,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t3dg_3(2,1,0)*t2s_2(0,2)
+				 + t3dg_3(2,1,1)*t2s_2(1,2)
+				 + t3dg_3(2,1,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t3dg_3(2,2,0)*t2s_2(0,0)
+				 + t3dg_3(2,2,1)*t2s_2(1,0)
+				 + t3dg_3(2,2,2)*t2s_2(2,0))
+		,"T2s(l,k)*T3dg(i,j,l)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t3dg_3(2,2,0)*t2s_2(0,1)
+				 + t3dg_3(2,2,1)*t2s_2(1,1)
+				 + t3dg_3(2,2,2)*t2s_2(2,1))
+		,"T2s(l,k)*T3dg(i,j,l)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t3dg_3(2,2,0)*t2s_2(0,2)
+				 + t3dg_3(2,2,1)*t2s_2(1,2)
+				 + t3dg_3(2,2,2)*t2s_2(2,2))
+		,"T2s(l,k)*T3dg(i,j,l)(2,2,2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXX.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXX.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXX(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(i,j,k)*t2s_2(j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(0,1)
+			   + t3dg_2(0,0,2)*t2s_2(0,2)
+			   + t3dg_2(0,1,0)*t2s_2(1,0)
+			   + t3dg_2(0,1,1)*t2s_2(1,1)
+			   + t3dg_2(0,1,2)*t2s_2(1,2)
+			   + t3dg_2(0,2,0)*t2s_2(2,0)
+			   + t3dg_2(0,2,1)*t2s_2(2,1)
+			   + t3dg_2(0,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2s_2(0,0)
+			   + t3dg_2(1,0,1)*t2s_2(0,1)
+			   + t3dg_2(1,0,2)*t2s_2(0,2)
+			   + t3dg_2(1,1,0)*t2s_2(1,0)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(1,2)
+			   + t3dg_2(1,2,0)*t2s_2(2,0)
+			   + t3dg_2(1,2,1)*t2s_2(2,1)
+			   + t3dg_2(1,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2s_2(0,0)
+			   + t3dg_2(2,0,1)*t2s_2(0,1)
+			   + t3dg_2(2,0,2)*t2s_2(0,2)
+			   + t3dg_2(2,1,0)*t2s_2(1,0)
+			   + t3dg_2(2,1,1)*t2s_2(1,1)
+			   + t3dg_2(2,1,2)*t2s_2(1,2)
+			   + t3dg_2(2,2,0)*t2s_2(2,0)
+			   + t3dg_2(2,2,1)*t2s_2(2,1)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(j,k)(2)");
+
+  t1_1(i)=t2s_2(j,k)*t3dg_2(i,j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(0,1)
+			   + t3dg_2(0,0,2)*t2s_2(0,2)
+			   + t3dg_2(0,1,0)*t2s_2(1,0)
+			   + t3dg_2(0,1,1)*t2s_2(1,1)
+			   + t3dg_2(0,1,2)*t2s_2(1,2)
+			   + t3dg_2(0,2,0)*t2s_2(2,0)
+			   + t3dg_2(0,2,1)*t2s_2(2,1)
+			   + t3dg_2(0,2,2)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(i,j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2s_2(0,0)
+			   + t3dg_2(1,0,1)*t2s_2(0,1)
+			   + t3dg_2(1,0,2)*t2s_2(0,2)
+			   + t3dg_2(1,1,0)*t2s_2(1,0)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(1,2)
+			   + t3dg_2(1,2,0)*t2s_2(2,0)
+			   + t3dg_2(1,2,1)*t2s_2(2,1)
+			   + t3dg_2(1,2,2)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(i,j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2s_2(0,0)
+			   + t3dg_2(2,0,1)*t2s_2(0,1)
+			   + t3dg_2(2,0,2)*t2s_2(0,2)
+			   + t3dg_2(2,1,0)*t2s_2(1,0)
+			   + t3dg_2(2,1,1)*t2s_2(1,1)
+			   + t3dg_2(2,1,2)*t2s_2(1,2)
+			   + t3dg_2(2,2,0)*t2s_2(2,0)
+			   + t3dg_2(2,2,1)*t2s_2(2,1)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(i,j,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXXI.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXXI.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXXI(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(i,j,k)*t2s_2(k,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(1,0)
+			   + t3dg_2(0,0,2)*t2s_2(2,0)
+			   + t3dg_2(0,1,0)*t2s_2(0,1)
+			   + t3dg_2(0,1,1)*t2s_2(1,1)
+			   + t3dg_2(0,1,2)*t2s_2(2,1)
+			   + t3dg_2(0,2,0)*t2s_2(0,2)
+			   + t3dg_2(0,2,1)*t2s_2(1,2)
+			   + t3dg_2(0,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(k,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2s_2(0,0)
+			   + t3dg_2(1,0,1)*t2s_2(1,0)
+			   + t3dg_2(1,0,2)*t2s_2(2,0)
+			   + t3dg_2(1,1,0)*t2s_2(0,1)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(2,1)
+			   + t3dg_2(1,2,0)*t2s_2(0,2)
+			   + t3dg_2(1,2,1)*t2s_2(1,2)
+			   + t3dg_2(1,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(k,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2s_2(0,0)
+			   + t3dg_2(2,0,1)*t2s_2(1,0)
+			   + t3dg_2(2,0,2)*t2s_2(2,0)
+			   + t3dg_2(2,1,0)*t2s_2(0,1)
+			   + t3dg_2(2,1,1)*t2s_2(1,1)
+			   + t3dg_2(2,1,2)*t2s_2(2,1)
+			   + t3dg_2(2,2,0)*t2s_2(0,2)
+			   + t3dg_2(2,2,1)*t2s_2(1,2)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(i,j,k)*T2s(k,j)(2)");
+
+  t1_1(i)=t2s_2(k,j)*t3dg_2(i,j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(1,0)
+			   + t3dg_2(0,0,2)*t2s_2(2,0)
+			   + t3dg_2(0,1,0)*t2s_2(0,1)
+			   + t3dg_2(0,1,1)*t2s_2(1,1)
+			   + t3dg_2(0,1,2)*t2s_2(2,1)
+			   + t3dg_2(0,2,0)*t2s_2(0,2)
+			   + t3dg_2(0,2,1)*t2s_2(1,2)
+			   + t3dg_2(0,2,2)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(i,j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(1,0,0)*t2s_2(0,0)
+			   + t3dg_2(1,0,1)*t2s_2(1,0)
+			   + t3dg_2(1,0,2)*t2s_2(2,0)
+			   + t3dg_2(1,1,0)*t2s_2(0,1)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(2,1)
+			   + t3dg_2(1,2,0)*t2s_2(0,2)
+			   + t3dg_2(1,2,1)*t2s_2(1,2)
+			   + t3dg_2(1,2,2)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(i,j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(2,0,0)*t2s_2(0,0)
+			   + t3dg_2(2,0,1)*t2s_2(1,0)
+			   + t3dg_2(2,0,2)*t2s_2(2,0)
+			   + t3dg_2(2,1,0)*t2s_2(0,1)
+			   + t3dg_2(2,1,1)*t2s_2(1,1)
+			   + t3dg_2(2,1,2)*t2s_2(2,1)
+			   + t3dg_2(2,2,0)*t2s_2(0,2)
+			   + t3dg_2(2,2,1)*t2s_2(1,2)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(i,j,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXXII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXXII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXXII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,i,k)*t2s_2(j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(0,1)
+			   + t3dg_2(0,0,2)*t2s_2(0,2)
+			   + t3dg_2(1,0,0)*t2s_2(1,0)
+			   + t3dg_2(1,0,1)*t2s_2(1,1)
+			   + t3dg_2(1,0,2)*t2s_2(1,2)
+			   + t3dg_2(2,0,0)*t2s_2(2,0)
+			   + t3dg_2(2,0,1)*t2s_2(2,1)
+			   + t3dg_2(2,0,2)*t2s_2(2,2))
+		,"T3dg(j,i,k)*T2s(j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(0,1)
+			   + t3dg_2(0,1,2)*t2s_2(0,2)
+			   + t3dg_2(1,1,0)*t2s_2(1,0)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(1,2)
+			   + t3dg_2(2,1,0)*t2s_2(2,0)
+			   + t3dg_2(2,1,1)*t2s_2(2,1)
+			   + t3dg_2(2,1,2)*t2s_2(2,2))
+		,"T3dg(j,i,k)*T2s(j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2s_2(0,0)
+			   + t3dg_2(0,2,1)*t2s_2(0,1)
+			   + t3dg_2(0,2,2)*t2s_2(0,2)
+			   + t3dg_2(1,2,0)*t2s_2(1,0)
+			   + t3dg_2(1,2,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(1,2)
+			   + t3dg_2(2,2,0)*t2s_2(2,0)
+			   + t3dg_2(2,2,1)*t2s_2(2,1)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(j,i,k)*T2s(j,k)(2)");
+
+  t1_1(i)=t2s_2(j,k)*t3dg_2(j,i,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(0,1)
+			   + t3dg_2(0,0,2)*t2s_2(0,2)
+			   + t3dg_2(1,0,0)*t2s_2(1,0)
+			   + t3dg_2(1,0,1)*t2s_2(1,1)
+			   + t3dg_2(1,0,2)*t2s_2(1,2)
+			   + t3dg_2(2,0,0)*t2s_2(2,0)
+			   + t3dg_2(2,0,1)*t2s_2(2,1)
+			   + t3dg_2(2,0,2)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(j,i,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(0,1)
+			   + t3dg_2(0,1,2)*t2s_2(0,2)
+			   + t3dg_2(1,1,0)*t2s_2(1,0)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(1,2)
+			   + t3dg_2(2,1,0)*t2s_2(2,0)
+			   + t3dg_2(2,1,1)*t2s_2(2,1)
+			   + t3dg_2(2,1,2)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(j,i,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2s_2(0,0)
+			   + t3dg_2(0,2,1)*t2s_2(0,1)
+			   + t3dg_2(0,2,2)*t2s_2(0,2)
+			   + t3dg_2(1,2,0)*t2s_2(1,0)
+			   + t3dg_2(1,2,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(1,2)
+			   + t3dg_2(2,2,0)*t2s_2(2,0)
+			   + t3dg_2(2,2,1)*t2s_2(2,1)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(j,i,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXXIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXXIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXXIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,i,k)*t2s_2(k,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(1,0)
+			   + t3dg_2(0,0,2)*t2s_2(2,0)
+			   + t3dg_2(1,0,0)*t2s_2(0,1)
+			   + t3dg_2(1,0,1)*t2s_2(1,1)
+			   + t3dg_2(1,0,2)*t2s_2(2,1)
+			   + t3dg_2(2,0,0)*t2s_2(0,2)
+			   + t3dg_2(2,0,1)*t2s_2(1,2)
+			   + t3dg_2(2,0,2)*t2s_2(2,2))
+		,"T3dg(j,i,k)*T2s(k,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(1,0)
+			   + t3dg_2(0,1,2)*t2s_2(2,0)
+			   + t3dg_2(1,1,0)*t2s_2(0,1)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(2,1)
+			   + t3dg_2(2,1,0)*t2s_2(0,2)
+			   + t3dg_2(2,1,1)*t2s_2(1,2)
+			   + t3dg_2(2,1,2)*t2s_2(2,2))
+		,"T3dg(j,i,k)*T2s(k,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2s_2(0,0)
+			   + t3dg_2(0,2,1)*t2s_2(1,0)
+			   + t3dg_2(0,2,2)*t2s_2(2,0)
+			   + t3dg_2(1,2,0)*t2s_2(0,1)
+			   + t3dg_2(1,2,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(2,1)
+			   + t3dg_2(2,2,0)*t2s_2(0,2)
+			   + t3dg_2(2,2,1)*t2s_2(1,2)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(j,i,k)*T2s(k,j)(2)");
+
+  t1_1(i)=t2s_2(k,j)*t3dg_2(j,i,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,0,1)*t2s_2(1,0)
+			   + t3dg_2(0,0,2)*t2s_2(2,0)
+			   + t3dg_2(1,0,0)*t2s_2(0,1)
+			   + t3dg_2(1,0,1)*t2s_2(1,1)
+			   + t3dg_2(1,0,2)*t2s_2(2,1)
+			   + t3dg_2(2,0,0)*t2s_2(0,2)
+			   + t3dg_2(2,0,1)*t2s_2(1,2)
+			   + t3dg_2(2,0,2)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(j,i,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,1,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(1,0)
+			   + t3dg_2(0,1,2)*t2s_2(2,0)
+			   + t3dg_2(1,1,0)*t2s_2(0,1)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,1,2)*t2s_2(2,1)
+			   + t3dg_2(2,1,0)*t2s_2(0,2)
+			   + t3dg_2(2,1,1)*t2s_2(1,2)
+			   + t3dg_2(2,1,2)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(j,i,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,2,0)*t2s_2(0,0)
+			   + t3dg_2(0,2,1)*t2s_2(1,0)
+			   + t3dg_2(0,2,2)*t2s_2(2,0)
+			   + t3dg_2(1,2,0)*t2s_2(0,1)
+			   + t3dg_2(1,2,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(2,1)
+			   + t3dg_2(2,2,0)*t2s_2(0,2)
+			   + t3dg_2(2,2,1)*t2s_2(1,2)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(j,i,k)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXXIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXXIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXXIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,k,i)*t2s_2(j,k);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,0)*t2s_2(0,1)
+			   + t3dg_2(0,2,0)*t2s_2(0,2)
+			   + t3dg_2(1,0,0)*t2s_2(1,0)
+			   + t3dg_2(1,1,0)*t2s_2(1,1)
+			   + t3dg_2(1,2,0)*t2s_2(1,2)
+			   + t3dg_2(2,0,0)*t2s_2(2,0)
+			   + t3dg_2(2,1,0)*t2s_2(2,1)
+			   + t3dg_2(2,2,0)*t2s_2(2,2))
+		,"T3dg(j,k,i)*T2s(j,k)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(0,1)
+			   + t3dg_2(0,2,1)*t2s_2(0,2)
+			   + t3dg_2(1,0,1)*t2s_2(1,0)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,1)*t2s_2(1,2)
+			   + t3dg_2(2,0,1)*t2s_2(2,0)
+			   + t3dg_2(2,1,1)*t2s_2(2,1)
+			   + t3dg_2(2,2,1)*t2s_2(2,2))
+		,"T3dg(j,k,i)*T2s(j,k)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2s_2(0,0)
+			   + t3dg_2(0,1,2)*t2s_2(0,1)
+			   + t3dg_2(0,2,2)*t2s_2(0,2)
+			   + t3dg_2(1,0,2)*t2s_2(1,0)
+			   + t3dg_2(1,1,2)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(1,2)
+			   + t3dg_2(2,0,2)*t2s_2(2,0)
+			   + t3dg_2(2,1,2)*t2s_2(2,1)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(j,k,i)*T2s(j,k)(2)");
+
+  t1_1(i)=t2s_2(j,k)*t3dg_2(j,k,i);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,0)*t2s_2(0,1)
+			   + t3dg_2(0,2,0)*t2s_2(0,2)
+			   + t3dg_2(1,0,0)*t2s_2(1,0)
+			   + t3dg_2(1,1,0)*t2s_2(1,1)
+			   + t3dg_2(1,2,0)*t2s_2(1,2)
+			   + t3dg_2(2,0,0)*t2s_2(2,0)
+			   + t3dg_2(2,1,0)*t2s_2(2,1)
+			   + t3dg_2(2,2,0)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(j,k,i)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(0,1)
+			   + t3dg_2(0,2,1)*t2s_2(0,2)
+			   + t3dg_2(1,0,1)*t2s_2(1,0)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,1)*t2s_2(1,2)
+			   + t3dg_2(2,0,1)*t2s_2(2,0)
+			   + t3dg_2(2,1,1)*t2s_2(2,1)
+			   + t3dg_2(2,2,1)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(j,k,i)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2s_2(0,0)
+			   + t3dg_2(0,1,2)*t2s_2(0,1)
+			   + t3dg_2(0,2,2)*t2s_2(0,2)
+			   + t3dg_2(1,0,2)*t2s_2(1,0)
+			   + t3dg_2(1,1,2)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(1,2)
+			   + t3dg_2(2,0,2)*t2s_2(2,0)
+			   + t3dg_2(2,1,2)*t2s_2(2,1)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T2s(j,k)*T3dg(j,k,i)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T3dg/test_T3dgXXXV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T3dg/test_T3dgXXXV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,98 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3dgXXXV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_dg tests */
+
+  t1_1(i)=t3dg_2(j,k,i)*t2s_2(k,j);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,0)*t2s_2(1,0)
+			   + t3dg_2(0,2,0)*t2s_2(2,0)
+			   + t3dg_2(1,0,0)*t2s_2(0,1)
+			   + t3dg_2(1,1,0)*t2s_2(1,1)
+			   + t3dg_2(1,2,0)*t2s_2(2,1)
+			   + t3dg_2(2,0,0)*t2s_2(0,2)
+			   + t3dg_2(2,1,0)*t2s_2(1,2)
+			   + t3dg_2(2,2,0)*t2s_2(2,2))
+		,"T3dg(j,k,i)*T2s(k,j)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(1,0)
+			   + t3dg_2(0,2,1)*t2s_2(2,0)
+			   + t3dg_2(1,0,1)*t2s_2(0,1)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,1)*t2s_2(2,1)
+			   + t3dg_2(2,0,1)*t2s_2(0,2)
+			   + t3dg_2(2,1,1)*t2s_2(1,2)
+			   + t3dg_2(2,2,1)*t2s_2(2,2))
+		,"T3dg(j,k,i)*T2s(k,j)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2s_2(0,0)
+			   + t3dg_2(0,1,2)*t2s_2(1,0)
+			   + t3dg_2(0,2,2)*t2s_2(2,0)
+			   + t3dg_2(1,0,2)*t2s_2(0,1)
+			   + t3dg_2(1,1,2)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(2,1)
+			   + t3dg_2(2,0,2)*t2s_2(0,2)
+			   + t3dg_2(2,1,2)*t2s_2(1,2)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T3dg(j,k,i)*T2s(k,j)(2)");
+
+  t1_1(i)=t2s_2(k,j)*t3dg_2(j,k,i);
+  test_for_zero(t1_1(0) - (t3dg_2(0,0,0)*t2s_2(0,0)
+			   + t3dg_2(0,1,0)*t2s_2(1,0)
+			   + t3dg_2(0,2,0)*t2s_2(2,0)
+			   + t3dg_2(1,0,0)*t2s_2(0,1)
+			   + t3dg_2(1,1,0)*t2s_2(1,1)
+			   + t3dg_2(1,2,0)*t2s_2(2,1)
+			   + t3dg_2(2,0,0)*t2s_2(0,2)
+			   + t3dg_2(2,1,0)*t2s_2(1,2)
+			   + t3dg_2(2,2,0)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(j,k,i)(0)");
+  test_for_zero(t1_1(1) - (t3dg_2(0,0,1)*t2s_2(0,0)
+			   + t3dg_2(0,1,1)*t2s_2(1,0)
+			   + t3dg_2(0,2,1)*t2s_2(2,0)
+			   + t3dg_2(1,0,1)*t2s_2(0,1)
+			   + t3dg_2(1,1,1)*t2s_2(1,1)
+			   + t3dg_2(1,2,1)*t2s_2(2,1)
+			   + t3dg_2(2,0,1)*t2s_2(0,2)
+			   + t3dg_2(2,1,1)*t2s_2(1,2)
+			   + t3dg_2(2,2,1)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(j,k,i)(1)");
+  test_for_zero(t1_1(2) - (t3dg_2(0,0,2)*t2s_2(0,0)
+			   + t3dg_2(0,1,2)*t2s_2(1,0)
+			   + t3dg_2(0,2,2)*t2s_2(2,0)
+			   + t3dg_2(1,0,2)*t2s_2(0,1)
+			   + t3dg_2(1,1,2)*t2s_2(1,1)
+			   + t3dg_2(1,2,2)*t2s_2(2,1)
+			   + t3dg_2(2,0,2)*t2s_2(0,2)
+			   + t3dg_2(2,1,2)*t2s_2(1,2)
+			   + t3dg_2(2,2,2)*t2s_2(2,2))
+		,"T2s(k,j)*T3dg(j,k,i)(2)");
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T4ddg/test_T4ddg.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T4ddg/test_T4ddg.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,1272 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T4ddg(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  Tensor4_ddg<double,3,3> t4ddg_1, t4ddg_2, t4ddg_3;
+
+  t4ddg_1(i,j,l,m)=t3dg_2(i,j,k)*t3dg_3(l,m,k);
+  test_for_zero(t4ddg_1(0,0,0,0) - (t3dg_2(0,0,0)*t3dg_3(0,0,0)
+				    + t3dg_2(0,0,1)*t3dg_3(0,0,1)
+				    + t3dg_2(0,0,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t3dg_2(0,0,0)*t3dg_3(0,1,0)
+				    + t3dg_2(0,0,1)*t3dg_3(0,1,1)
+				    + t3dg_2(0,0,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t3dg_2(0,0,0)*t3dg_3(0,2,0)
+				    + t3dg_2(0,0,1)*t3dg_3(0,2,1)
+				    + t3dg_2(0,0,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t3dg_2(0,0,0)*t3dg_3(1,0,0)
+				    + t3dg_2(0,0,1)*t3dg_3(1,0,1)
+				    + t3dg_2(0,0,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t3dg_2(0,0,0)*t3dg_3(1,1,0)
+				    + t3dg_2(0,0,1)*t3dg_3(1,1,1)
+				    + t3dg_2(0,0,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t3dg_2(0,0,0)*t3dg_3(1,2,0)
+				    + t3dg_2(0,0,1)*t3dg_3(1,2,1)
+				    + t3dg_2(0,0,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t3dg_2(0,0,0)*t3dg_3(2,0,0)
+				    + t3dg_2(0,0,1)*t3dg_3(2,0,1)
+				    + t3dg_2(0,0,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t3dg_2(0,0,0)*t3dg_3(2,1,0)
+				    + t3dg_2(0,0,1)*t3dg_3(2,1,1)
+				    + t3dg_2(0,0,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t3dg_2(0,0,0)*t3dg_3(2,2,0)
+				    + t3dg_2(0,0,1)*t3dg_3(2,2,1)
+				    + t3dg_2(0,0,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t3dg_2(0,1,0)*t3dg_3(0,0,0)
+				    + t3dg_2(0,1,1)*t3dg_3(0,0,1)
+				    + t3dg_2(0,1,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t3dg_2(0,1,0)*t3dg_3(0,1,0)
+				    + t3dg_2(0,1,1)*t3dg_3(0,1,1)
+				    + t3dg_2(0,1,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t3dg_2(0,1,0)*t3dg_3(0,2,0)
+				    + t3dg_2(0,1,1)*t3dg_3(0,2,1)
+				    + t3dg_2(0,1,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t3dg_2(0,1,0)*t3dg_3(1,0,0)
+				    + t3dg_2(0,1,1)*t3dg_3(1,0,1)
+				    + t3dg_2(0,1,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t3dg_2(0,1,0)*t3dg_3(1,1,0)
+				    + t3dg_2(0,1,1)*t3dg_3(1,1,1)
+				    + t3dg_2(0,1,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t3dg_2(0,1,0)*t3dg_3(1,2,0)
+				    + t3dg_2(0,1,1)*t3dg_3(1,2,1)
+				    + t3dg_2(0,1,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t3dg_2(0,1,0)*t3dg_3(2,0,0)
+				    + t3dg_2(0,1,1)*t3dg_3(2,0,1)
+				    + t3dg_2(0,1,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t3dg_2(0,1,0)*t3dg_3(2,1,0)
+				    + t3dg_2(0,1,1)*t3dg_3(2,1,1)
+				    + t3dg_2(0,1,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t3dg_2(0,1,0)*t3dg_3(2,2,0)
+				    + t3dg_2(0,1,1)*t3dg_3(2,2,1)
+				    + t3dg_2(0,1,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t3dg_2(0,2,0)*t3dg_3(0,0,0)
+				    + t3dg_2(0,2,1)*t3dg_3(0,0,1)
+				    + t3dg_2(0,2,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t3dg_2(0,2,0)*t3dg_3(0,1,0)
+				    + t3dg_2(0,2,1)*t3dg_3(0,1,1)
+				    + t3dg_2(0,2,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t3dg_2(0,2,0)*t3dg_3(0,2,0)
+				    + t3dg_2(0,2,1)*t3dg_3(0,2,1)
+				    + t3dg_2(0,2,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t3dg_2(0,2,0)*t3dg_3(1,0,0)
+				    + t3dg_2(0,2,1)*t3dg_3(1,0,1)
+				    + t3dg_2(0,2,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t3dg_2(0,2,0)*t3dg_3(1,1,0)
+				    + t3dg_2(0,2,1)*t3dg_3(1,1,1)
+				    + t3dg_2(0,2,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t3dg_2(0,2,0)*t3dg_3(1,2,0)
+				    + t3dg_2(0,2,1)*t3dg_3(1,2,1)
+				    + t3dg_2(0,2,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t3dg_2(0,2,0)*t3dg_3(2,0,0)
+				    + t3dg_2(0,2,1)*t3dg_3(2,0,1)
+				    + t3dg_2(0,2,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t3dg_2(0,2,0)*t3dg_3(2,1,0)
+				    + t3dg_2(0,2,1)*t3dg_3(2,1,1)
+				    + t3dg_2(0,2,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t3dg_2(0,2,0)*t3dg_3(2,2,0)
+				    + t3dg_2(0,2,1)*t3dg_3(2,2,1)
+				    + t3dg_2(0,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t3dg_2(1,0,0)*t3dg_3(0,0,0)
+				    + t3dg_2(1,0,1)*t3dg_3(0,0,1)
+				    + t3dg_2(1,0,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t3dg_2(1,0,0)*t3dg_3(0,1,0)
+				    + t3dg_2(1,0,1)*t3dg_3(0,1,1)
+				    + t3dg_2(1,0,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t3dg_2(1,0,0)*t3dg_3(0,2,0)
+				    + t3dg_2(1,0,1)*t3dg_3(0,2,1)
+				    + t3dg_2(1,0,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t3dg_2(1,0,0)*t3dg_3(1,0,0)
+				    + t3dg_2(1,0,1)*t3dg_3(1,0,1)
+				    + t3dg_2(1,0,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t3dg_2(1,0,0)*t3dg_3(1,1,0)
+				    + t3dg_2(1,0,1)*t3dg_3(1,1,1)
+				    + t3dg_2(1,0,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t3dg_2(1,0,0)*t3dg_3(1,2,0)
+				    + t3dg_2(1,0,1)*t3dg_3(1,2,1)
+				    + t3dg_2(1,0,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t3dg_2(1,0,0)*t3dg_3(2,0,0)
+				    + t3dg_2(1,0,1)*t3dg_3(2,0,1)
+				    + t3dg_2(1,0,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t3dg_2(1,0,0)*t3dg_3(2,1,0)
+				    + t3dg_2(1,0,1)*t3dg_3(2,1,1)
+				    + t3dg_2(1,0,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t3dg_2(1,0,0)*t3dg_3(2,2,0)
+				    + t3dg_2(1,0,1)*t3dg_3(2,2,1)
+				    + t3dg_2(1,0,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t3dg_2(1,1,0)*t3dg_3(0,0,0)
+				    + t3dg_2(1,1,1)*t3dg_3(0,0,1)
+				    + t3dg_2(1,1,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t3dg_2(1,1,0)*t3dg_3(0,1,0)
+				    + t3dg_2(1,1,1)*t3dg_3(0,1,1)
+				    + t3dg_2(1,1,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t3dg_2(1,1,0)*t3dg_3(0,2,0)
+				    + t3dg_2(1,1,1)*t3dg_3(0,2,1)
+				    + t3dg_2(1,1,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t3dg_2(1,1,0)*t3dg_3(1,0,0)
+				    + t3dg_2(1,1,1)*t3dg_3(1,0,1)
+				    + t3dg_2(1,1,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t3dg_2(1,1,0)*t3dg_3(1,1,0)
+				    + t3dg_2(1,1,1)*t3dg_3(1,1,1)
+				    + t3dg_2(1,1,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t3dg_2(1,1,0)*t3dg_3(1,2,0)
+				    + t3dg_2(1,1,1)*t3dg_3(1,2,1)
+				    + t3dg_2(1,1,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t3dg_2(1,1,0)*t3dg_3(2,0,0)
+				    + t3dg_2(1,1,1)*t3dg_3(2,0,1)
+				    + t3dg_2(1,1,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t3dg_2(1,1,0)*t3dg_3(2,1,0)
+				    + t3dg_2(1,1,1)*t3dg_3(2,1,1)
+				    + t3dg_2(1,1,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t3dg_2(1,1,0)*t3dg_3(2,2,0)
+				    + t3dg_2(1,1,1)*t3dg_3(2,2,1)
+				    + t3dg_2(1,1,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t3dg_2(1,2,0)*t3dg_3(0,0,0)
+				    + t3dg_2(1,2,1)*t3dg_3(0,0,1)
+				    + t3dg_2(1,2,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t3dg_2(1,2,0)*t3dg_3(0,1,0)
+				    + t3dg_2(1,2,1)*t3dg_3(0,1,1)
+				    + t3dg_2(1,2,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t3dg_2(1,2,0)*t3dg_3(0,2,0)
+				    + t3dg_2(1,2,1)*t3dg_3(0,2,1)
+				    + t3dg_2(1,2,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t3dg_2(1,2,0)*t3dg_3(1,0,0)
+				    + t3dg_2(1,2,1)*t3dg_3(1,0,1)
+				    + t3dg_2(1,2,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t3dg_2(1,2,0)*t3dg_3(1,1,0)
+				    + t3dg_2(1,2,1)*t3dg_3(1,1,1)
+				    + t3dg_2(1,2,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t3dg_2(1,2,0)*t3dg_3(1,2,0)
+				    + t3dg_2(1,2,1)*t3dg_3(1,2,1)
+				    + t3dg_2(1,2,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t3dg_2(1,2,0)*t3dg_3(2,0,0)
+				    + t3dg_2(1,2,1)*t3dg_3(2,0,1)
+				    + t3dg_2(1,2,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t3dg_2(1,2,0)*t3dg_3(2,1,0)
+				    + t3dg_2(1,2,1)*t3dg_3(2,1,1)
+				    + t3dg_2(1,2,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t3dg_2(1,2,0)*t3dg_3(2,2,0)
+				    + t3dg_2(1,2,1)*t3dg_3(2,2,1)
+				    + t3dg_2(1,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t3dg_2(2,0,0)*t3dg_3(0,0,0)
+				    + t3dg_2(2,0,1)*t3dg_3(0,0,1)
+				    + t3dg_2(2,0,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t3dg_2(2,0,0)*t3dg_3(0,1,0)
+				    + t3dg_2(2,0,1)*t3dg_3(0,1,1)
+				    + t3dg_2(2,0,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t3dg_2(2,0,0)*t3dg_3(0,2,0)
+				    + t3dg_2(2,0,1)*t3dg_3(0,2,1)
+				    + t3dg_2(2,0,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t3dg_2(2,0,0)*t3dg_3(1,0,0)
+				    + t3dg_2(2,0,1)*t3dg_3(1,0,1)
+				    + t3dg_2(2,0,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t3dg_2(2,0,0)*t3dg_3(1,1,0)
+				    + t3dg_2(2,0,1)*t3dg_3(1,1,1)
+				    + t3dg_2(2,0,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t3dg_2(2,0,0)*t3dg_3(1,2,0)
+				    + t3dg_2(2,0,1)*t3dg_3(1,2,1)
+				    + t3dg_2(2,0,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t3dg_2(2,0,0)*t3dg_3(2,0,0)
+				    + t3dg_2(2,0,1)*t3dg_3(2,0,1)
+				    + t3dg_2(2,0,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t3dg_2(2,0,0)*t3dg_3(2,1,0)
+				    + t3dg_2(2,0,1)*t3dg_3(2,1,1)
+				    + t3dg_2(2,0,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t3dg_2(2,0,0)*t3dg_3(2,2,0)
+				    + t3dg_2(2,0,1)*t3dg_3(2,2,1)
+				    + t3dg_2(2,0,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t3dg_2(2,1,0)*t3dg_3(0,0,0)
+				    + t3dg_2(2,1,1)*t3dg_3(0,0,1)
+				    + t3dg_2(2,1,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t3dg_2(2,1,0)*t3dg_3(0,1,0)
+				    + t3dg_2(2,1,1)*t3dg_3(0,1,1)
+				    + t3dg_2(2,1,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t3dg_2(2,1,0)*t3dg_3(0,2,0)
+				    + t3dg_2(2,1,1)*t3dg_3(0,2,1)
+				    + t3dg_2(2,1,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t3dg_2(2,1,0)*t3dg_3(1,0,0)
+				    + t3dg_2(2,1,1)*t3dg_3(1,0,1)
+				    + t3dg_2(2,1,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t3dg_2(2,1,0)*t3dg_3(1,1,0)
+				    + t3dg_2(2,1,1)*t3dg_3(1,1,1)
+				    + t3dg_2(2,1,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t3dg_2(2,1,0)*t3dg_3(1,2,0)
+				    + t3dg_2(2,1,1)*t3dg_3(1,2,1)
+				    + t3dg_2(2,1,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t3dg_2(2,1,0)*t3dg_3(2,0,0)
+				    + t3dg_2(2,1,1)*t3dg_3(2,0,1)
+				    + t3dg_2(2,1,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t3dg_2(2,1,0)*t3dg_3(2,1,0)
+				    + t3dg_2(2,1,1)*t3dg_3(2,1,1)
+				    + t3dg_2(2,1,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t3dg_2(2,1,0)*t3dg_3(2,2,0)
+				    + t3dg_2(2,1,1)*t3dg_3(2,2,1)
+				    + t3dg_2(2,1,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t3dg_2(2,2,0)*t3dg_3(0,0,0)
+				    + t3dg_2(2,2,1)*t3dg_3(0,0,1)
+				    + t3dg_2(2,2,2)*t3dg_3(0,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t3dg_2(2,2,0)*t3dg_3(0,1,0)
+				    + t3dg_2(2,2,1)*t3dg_3(0,1,1)
+				    + t3dg_2(2,2,2)*t3dg_3(0,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t3dg_2(2,2,0)*t3dg_3(0,2,0)
+				    + t3dg_2(2,2,1)*t3dg_3(0,2,1)
+				    + t3dg_2(2,2,2)*t3dg_3(0,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t3dg_2(2,2,0)*t3dg_3(1,0,0)
+				    + t3dg_2(2,2,1)*t3dg_3(1,0,1)
+				    + t3dg_2(2,2,2)*t3dg_3(1,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t3dg_2(2,2,0)*t3dg_3(1,1,0)
+				    + t3dg_2(2,2,1)*t3dg_3(1,1,1)
+				    + t3dg_2(2,2,2)*t3dg_3(1,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t3dg_2(2,2,0)*t3dg_3(1,2,0)
+				    + t3dg_2(2,2,1)*t3dg_3(1,2,1)
+				    + t3dg_2(2,2,2)*t3dg_3(1,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t3dg_2(2,2,0)*t3dg_3(2,0,0)
+				    + t3dg_2(2,2,1)*t3dg_3(2,0,1)
+				    + t3dg_2(2,2,2)*t3dg_3(2,0,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t3dg_2(2,2,0)*t3dg_3(2,1,0)
+				    + t3dg_2(2,2,1)*t3dg_3(2,1,1)
+				    + t3dg_2(2,2,2)*t3dg_3(2,1,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t3dg_2(2,2,0)*t3dg_3(2,2,0)
+				    + t3dg_2(2,2,1)*t3dg_3(2,2,1)
+				    + t3dg_2(2,2,2)*t3dg_3(2,2,2))
+		,"T3dg(i,j,k)*T3dg(l,m,k)(2,2,2,2)");
+
+  t4ddg_2(i,j,l,m)=t2s_2(i,j)*t2s_3(l,m);
+  t4ddg_3(i,j,l,m)=t2s_3(i,j)*t2s_2(l,m);
+  test_for_zero(t4ddg_2(0,0,0,0) - (t2s_2(0,0)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(0,0,0,0)");
+  test_for_zero(t4ddg_2(0,0,0,1) - (t2s_2(0,0)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(0,0,0,1)");
+  test_for_zero(t4ddg_2(0,0,0,2) - (t2s_2(0,0)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(0,0,0,2)");
+  test_for_zero(t4ddg_2(0,0,1,0) - (t2s_2(0,0)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(0,0,1,0)");
+  test_for_zero(t4ddg_2(0,0,1,1) - (t2s_2(0,0)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(0,0,1,1)");
+  test_for_zero(t4ddg_2(0,0,1,2) - (t2s_2(0,0)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(0,0,1,2)");
+  test_for_zero(t4ddg_2(0,0,2,0) - (t2s_2(0,0)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(0,0,2,0)");
+  test_for_zero(t4ddg_2(0,0,2,1) - (t2s_2(0,0)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(0,0,2,1)");
+  test_for_zero(t4ddg_2(0,0,2,2) - (t2s_2(0,0)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(0,0,2,2)");
+  test_for_zero(t4ddg_2(0,1,0,0) - (t2s_2(0,1)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(0,1,0,0)");
+  test_for_zero(t4ddg_2(0,1,0,1) - (t2s_2(0,1)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(0,1,0,1)");
+  test_for_zero(t4ddg_2(0,1,0,2) - (t2s_2(0,1)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(0,1,0,2)");
+  test_for_zero(t4ddg_2(0,1,1,0) - (t2s_2(0,1)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(0,1,1,0)");
+  test_for_zero(t4ddg_2(0,1,1,1) - (t2s_2(0,1)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(0,1,1,1)");
+  test_for_zero(t4ddg_2(0,1,1,2) - (t2s_2(0,1)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(0,1,1,2)");
+  test_for_zero(t4ddg_2(0,1,2,0) - (t2s_2(0,1)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(0,1,2,0)");
+  test_for_zero(t4ddg_2(0,1,2,1) - (t2s_2(0,1)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(0,1,2,1)");
+  test_for_zero(t4ddg_2(0,1,2,2) - (t2s_2(0,1)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(0,1,2,2)");
+  test_for_zero(t4ddg_2(0,2,0,0) - (t2s_2(0,2)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(0,2,0,0)");
+  test_for_zero(t4ddg_2(0,2,0,1) - (t2s_2(0,2)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(0,2,0,1)");
+  test_for_zero(t4ddg_2(0,2,0,2) - (t2s_2(0,2)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(0,2,0,2)");
+  test_for_zero(t4ddg_2(0,2,1,0) - (t2s_2(0,2)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(0,2,1,0)");
+  test_for_zero(t4ddg_2(0,2,1,1) - (t2s_2(0,2)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(0,2,1,1)");
+  test_for_zero(t4ddg_2(0,2,1,2) - (t2s_2(0,2)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(0,2,1,2)");
+  test_for_zero(t4ddg_2(0,2,2,0) - (t2s_2(0,2)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(0,2,2,0)");
+  test_for_zero(t4ddg_2(0,2,2,1) - (t2s_2(0,2)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(0,2,2,1)");
+  test_for_zero(t4ddg_2(0,2,2,2) - (t2s_2(0,2)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(0,2,2,2)");
+  test_for_zero(t4ddg_2(1,0,0,0) - (t2s_2(1,0)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(1,0,0,0)");
+  test_for_zero(t4ddg_2(1,0,0,1) - (t2s_2(1,0)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(1,0,0,1)");
+  test_for_zero(t4ddg_2(1,0,0,2) - (t2s_2(1,0)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(1,0,0,2)");
+  test_for_zero(t4ddg_2(1,0,1,0) - (t2s_2(1,0)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(1,0,1,0)");
+  test_for_zero(t4ddg_2(1,0,1,1) - (t2s_2(1,0)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(1,0,1,1)");
+  test_for_zero(t4ddg_2(1,0,1,2) - (t2s_2(1,0)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(1,0,1,2)");
+  test_for_zero(t4ddg_2(1,0,2,0) - (t2s_2(1,0)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(1,0,2,0)");
+  test_for_zero(t4ddg_2(1,0,2,1) - (t2s_2(1,0)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(1,0,2,1)");
+  test_for_zero(t4ddg_2(1,0,2,2) - (t2s_2(1,0)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(1,0,2,2)");
+  test_for_zero(t4ddg_2(1,1,0,0) - (t2s_2(1,1)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(1,1,0,0)");
+  test_for_zero(t4ddg_2(1,1,0,1) - (t2s_2(1,1)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(1,1,0,1)");
+  test_for_zero(t4ddg_2(1,1,0,2) - (t2s_2(1,1)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(1,1,0,2)");
+  test_for_zero(t4ddg_2(1,1,1,0) - (t2s_2(1,1)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(1,1,1,0)");
+  test_for_zero(t4ddg_2(1,1,1,1) - (t2s_2(1,1)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(1,1,1,1)");
+  test_for_zero(t4ddg_2(1,1,1,2) - (t2s_2(1,1)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(1,1,1,2)");
+  test_for_zero(t4ddg_2(1,1,2,0) - (t2s_2(1,1)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(1,1,2,0)");
+  test_for_zero(t4ddg_2(1,1,2,1) - (t2s_2(1,1)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(1,1,2,1)");
+  test_for_zero(t4ddg_2(1,1,2,2) - (t2s_2(1,1)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(1,1,2,2)");
+  test_for_zero(t4ddg_2(1,2,0,0) - (t2s_2(1,2)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(1,2,0,0)");
+  test_for_zero(t4ddg_2(1,2,0,1) - (t2s_2(1,2)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(1,2,0,1)");
+  test_for_zero(t4ddg_2(1,2,0,2) - (t2s_2(1,2)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(1,2,0,2)");
+  test_for_zero(t4ddg_2(1,2,1,0) - (t2s_2(1,2)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(1,2,1,0)");
+  test_for_zero(t4ddg_2(1,2,1,1) - (t2s_2(1,2)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(1,2,1,1)");
+  test_for_zero(t4ddg_2(1,2,1,2) - (t2s_2(1,2)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(1,2,1,2)");
+  test_for_zero(t4ddg_2(1,2,2,0) - (t2s_2(1,2)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(1,2,2,0)");
+  test_for_zero(t4ddg_2(1,2,2,1) - (t2s_2(1,2)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(1,2,2,1)");
+  test_for_zero(t4ddg_2(1,2,2,2) - (t2s_2(1,2)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(1,2,2,2)");
+  test_for_zero(t4ddg_2(2,0,0,0) - (t2s_2(2,0)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(2,0,0,0)");
+  test_for_zero(t4ddg_2(2,0,0,1) - (t2s_2(2,0)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(2,0,0,1)");
+  test_for_zero(t4ddg_2(2,0,0,2) - (t2s_2(2,0)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(2,0,0,2)");
+  test_for_zero(t4ddg_2(2,0,1,0) - (t2s_2(2,0)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(2,0,1,0)");
+  test_for_zero(t4ddg_2(2,0,1,1) - (t2s_2(2,0)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(2,0,1,1)");
+  test_for_zero(t4ddg_2(2,0,1,2) - (t2s_2(2,0)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(2,0,1,2)");
+  test_for_zero(t4ddg_2(2,0,2,0) - (t2s_2(2,0)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(2,0,2,0)");
+  test_for_zero(t4ddg_2(2,0,2,1) - (t2s_2(2,0)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(2,0,2,1)");
+  test_for_zero(t4ddg_2(2,0,2,2) - (t2s_2(2,0)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(2,0,2,2)");
+  test_for_zero(t4ddg_2(2,1,0,0) - (t2s_2(2,1)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(2,1,0,0)");
+  test_for_zero(t4ddg_2(2,1,0,1) - (t2s_2(2,1)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(2,1,0,1)");
+  test_for_zero(t4ddg_2(2,1,0,2) - (t2s_2(2,1)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(2,1,0,2)");
+  test_for_zero(t4ddg_2(2,1,1,0) - (t2s_2(2,1)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(2,1,1,0)");
+  test_for_zero(t4ddg_2(2,1,1,1) - (t2s_2(2,1)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(2,1,1,1)");
+  test_for_zero(t4ddg_2(2,1,1,2) - (t2s_2(2,1)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(2,1,1,2)");
+  test_for_zero(t4ddg_2(2,1,2,0) - (t2s_2(2,1)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(2,1,2,0)");
+  test_for_zero(t4ddg_2(2,1,2,1) - (t2s_2(2,1)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(2,1,2,1)");
+  test_for_zero(t4ddg_2(2,1,2,2) - (t2s_2(2,1)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(2,1,2,2)");
+  test_for_zero(t4ddg_2(2,2,0,0) - (t2s_2(2,2)*t2s_3(0,0))
+		,"T2s(i,j)*T2s(l,m)(2,2,0,0)");
+  test_for_zero(t4ddg_2(2,2,0,1) - (t2s_2(2,2)*t2s_3(0,1))
+		,"T2s(i,j)*T2s(l,m)(2,2,0,1)");
+  test_for_zero(t4ddg_2(2,2,0,2) - (t2s_2(2,2)*t2s_3(0,2))
+		,"T2s(i,j)*T2s(l,m)(2,2,0,2)");
+  test_for_zero(t4ddg_2(2,2,1,0) - (t2s_2(2,2)*t2s_3(1,0))
+		,"T2s(i,j)*T2s(l,m)(2,2,1,0)");
+  test_for_zero(t4ddg_2(2,2,1,1) - (t2s_2(2,2)*t2s_3(1,1))
+		,"T2s(i,j)*T2s(l,m)(2,2,1,1)");
+  test_for_zero(t4ddg_2(2,2,1,2) - (t2s_2(2,2)*t2s_3(1,2))
+		,"T2s(i,j)*T2s(l,m)(2,2,1,2)");
+  test_for_zero(t4ddg_2(2,2,2,0) - (t2s_2(2,2)*t2s_3(2,0))
+		,"T2s(i,j)*T2s(l,m)(2,2,2,0)");
+  test_for_zero(t4ddg_2(2,2,2,1) - (t2s_2(2,2)*t2s_3(2,1))
+		,"T2s(i,j)*T2s(l,m)(2,2,2,1)");
+  test_for_zero(t4ddg_2(2,2,2,2) - (t2s_2(2,2)*t2s_3(2,2))
+		,"T2s(i,j)*T2s(l,m)(2,2,2,2)");
+
+  test_for_zero(t4ddg_1(i,j,k,l)*t4ddg_2(i,k,j,l)
+		- t4ddg_1(0,0,0,0)*t4ddg_2(0,0,0,0)
+		- t4ddg_1(0,0,0,1)*t4ddg_2(0,0,0,1)
+		- t4ddg_1(0,0,0,2)*t4ddg_2(0,0,0,2)
+		- t4ddg_1(0,0,1,0)*t4ddg_2(0,1,0,0)
+		- t4ddg_1(0,0,1,1)*t4ddg_2(0,1,0,1)
+		- t4ddg_1(0,0,1,2)*t4ddg_2(0,1,0,2)
+		- t4ddg_1(0,0,2,0)*t4ddg_2(0,2,0,0)
+		- t4ddg_1(0,0,2,1)*t4ddg_2(0,2,0,1)
+		- t4ddg_1(0,0,2,2)*t4ddg_2(0,2,0,2)
+		- t4ddg_1(0,1,0,0)*t4ddg_2(0,0,1,0)
+		- t4ddg_1(0,1,0,1)*t4ddg_2(0,0,1,1)
+		- t4ddg_1(0,1,0,2)*t4ddg_2(0,0,1,2)
+		- t4ddg_1(0,1,1,0)*t4ddg_2(0,1,1,0)
+		- t4ddg_1(0,1,1,1)*t4ddg_2(0,1,1,1)
+		- t4ddg_1(0,1,1,2)*t4ddg_2(0,1,1,2)
+		- t4ddg_1(0,1,2,0)*t4ddg_2(0,2,1,0)
+		- t4ddg_1(0,1,2,1)*t4ddg_2(0,2,1,1)
+		- t4ddg_1(0,1,2,2)*t4ddg_2(0,2,1,2)
+		- t4ddg_1(0,2,0,0)*t4ddg_2(0,0,2,0)
+		- t4ddg_1(0,2,0,1)*t4ddg_2(0,0,2,1)
+		- t4ddg_1(0,2,0,2)*t4ddg_2(0,0,2,2)
+		- t4ddg_1(0,2,1,0)*t4ddg_2(0,1,2,0)
+		- t4ddg_1(0,2,1,1)*t4ddg_2(0,1,2,1)
+		- t4ddg_1(0,2,1,2)*t4ddg_2(0,1,2,2)
+		- t4ddg_1(0,2,2,0)*t4ddg_2(0,2,2,0)
+		- t4ddg_1(0,2,2,1)*t4ddg_2(0,2,2,1)
+		- t4ddg_1(0,2,2,2)*t4ddg_2(0,2,2,2)
+
+		- t4ddg_1(1,0,0,0)*t4ddg_2(1,0,0,0)
+		- t4ddg_1(1,0,0,1)*t4ddg_2(1,0,0,1)
+		- t4ddg_1(1,0,0,2)*t4ddg_2(1,0,0,2)
+		- t4ddg_1(1,0,1,0)*t4ddg_2(1,1,0,0)
+		- t4ddg_1(1,0,1,1)*t4ddg_2(1,1,0,1)
+		- t4ddg_1(1,0,1,2)*t4ddg_2(1,1,0,2)
+		- t4ddg_1(1,0,2,0)*t4ddg_2(1,2,0,0)
+		- t4ddg_1(1,0,2,1)*t4ddg_2(1,2,0,1)
+		- t4ddg_1(1,0,2,2)*t4ddg_2(1,2,0,2)
+		- t4ddg_1(1,1,0,0)*t4ddg_2(1,0,1,0)
+		- t4ddg_1(1,1,0,1)*t4ddg_2(1,0,1,1)
+		- t4ddg_1(1,1,0,2)*t4ddg_2(1,0,1,2)
+		- t4ddg_1(1,1,1,0)*t4ddg_2(1,1,1,0)
+		- t4ddg_1(1,1,1,1)*t4ddg_2(1,1,1,1)
+		- t4ddg_1(1,1,1,2)*t4ddg_2(1,1,1,2)
+		- t4ddg_1(1,1,2,0)*t4ddg_2(1,2,1,0)
+		- t4ddg_1(1,1,2,1)*t4ddg_2(1,2,1,1)
+		- t4ddg_1(1,1,2,2)*t4ddg_2(1,2,1,2)
+		- t4ddg_1(1,2,0,0)*t4ddg_2(1,0,2,0)
+		- t4ddg_1(1,2,0,1)*t4ddg_2(1,0,2,1)
+		- t4ddg_1(1,2,0,2)*t4ddg_2(1,0,2,2)
+		- t4ddg_1(1,2,1,0)*t4ddg_2(1,1,2,0)
+		- t4ddg_1(1,2,1,1)*t4ddg_2(1,1,2,1)
+		- t4ddg_1(1,2,1,2)*t4ddg_2(1,1,2,2)
+		- t4ddg_1(1,2,2,0)*t4ddg_2(1,2,2,0)
+		- t4ddg_1(1,2,2,1)*t4ddg_2(1,2,2,1)
+		- t4ddg_1(1,2,2,2)*t4ddg_2(1,2,2,2)
+
+		- t4ddg_1(2,0,0,0)*t4ddg_2(2,0,0,0)
+		- t4ddg_1(2,0,0,1)*t4ddg_2(2,0,0,1)
+		- t4ddg_1(2,0,0,2)*t4ddg_2(2,0,0,2)
+		- t4ddg_1(2,0,1,0)*t4ddg_2(2,1,0,0)
+		- t4ddg_1(2,0,1,1)*t4ddg_2(2,1,0,1)
+		- t4ddg_1(2,0,1,2)*t4ddg_2(2,1,0,2)
+		- t4ddg_1(2,0,2,0)*t4ddg_2(2,2,0,0)
+		- t4ddg_1(2,0,2,1)*t4ddg_2(2,2,0,1)
+		- t4ddg_1(2,0,2,2)*t4ddg_2(2,2,0,2)
+		- t4ddg_1(2,1,0,0)*t4ddg_2(2,0,1,0)
+		- t4ddg_1(2,1,0,1)*t4ddg_2(2,0,1,1)
+		- t4ddg_1(2,1,0,2)*t4ddg_2(2,0,1,2)
+		- t4ddg_1(2,1,1,0)*t4ddg_2(2,1,1,0)
+		- t4ddg_1(2,1,1,1)*t4ddg_2(2,1,1,1)
+		- t4ddg_1(2,1,1,2)*t4ddg_2(2,1,1,2)
+		- t4ddg_1(2,1,2,0)*t4ddg_2(2,2,1,0)
+		- t4ddg_1(2,1,2,1)*t4ddg_2(2,2,1,1)
+		- t4ddg_1(2,1,2,2)*t4ddg_2(2,2,1,2)
+		- t4ddg_1(2,2,0,0)*t4ddg_2(2,0,2,0)
+		- t4ddg_1(2,2,0,1)*t4ddg_2(2,0,2,1)
+		- t4ddg_1(2,2,0,2)*t4ddg_2(2,0,2,2)
+		- t4ddg_1(2,2,1,0)*t4ddg_2(2,1,2,0)
+		- t4ddg_1(2,2,1,1)*t4ddg_2(2,1,2,1)
+		- t4ddg_1(2,2,1,2)*t4ddg_2(2,1,2,2)
+		- t4ddg_1(2,2,2,0)*t4ddg_2(2,2,2,0)
+		- t4ddg_1(2,2,2,1)*t4ddg_2(2,2,2,1)
+		- t4ddg_1(2,2,2,2)*t4ddg_2(2,2,2,2)
+		,"T4ddg(i,j,k,l)*T4ddg(i,j,k,l)");
+
+  t4ddg_1(i,j,k,l)=t4ddg_2(i,j,k,l)+t4ddg_3(i,j,k,l);
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)+t4ddg_3(0,0,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)+t4ddg_3(0,0,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)+t4ddg_3(0,0,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)+t4ddg_3(0,0,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)+t4ddg_3(0,0,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)+t4ddg_3(0,0,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)+t4ddg_3(0,0,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)+t4ddg_3(0,0,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)+t4ddg_3(0,0,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)+t4ddg_3(0,1,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)+t4ddg_3(0,1,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)+t4ddg_3(0,1,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)+t4ddg_3(0,1,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)+t4ddg_3(0,1,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)+t4ddg_3(0,1,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)+t4ddg_3(0,1,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)+t4ddg_3(0,1,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)+t4ddg_3(0,1,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)+t4ddg_3(0,2,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)+t4ddg_3(0,2,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)+t4ddg_3(0,2,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)+t4ddg_3(0,2,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)+t4ddg_3(0,2,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)+t4ddg_3(0,2,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)+t4ddg_3(0,2,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)+t4ddg_3(0,2,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)+t4ddg_3(0,2,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)+t4ddg_3(1,0,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)+t4ddg_3(1,0,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)+t4ddg_3(1,0,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)+t4ddg_3(1,0,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)+t4ddg_3(1,0,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)+t4ddg_3(1,0,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)+t4ddg_3(1,0,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)+t4ddg_3(1,0,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)+t4ddg_3(1,0,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)+t4ddg_3(1,1,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)+t4ddg_3(1,1,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)+t4ddg_3(1,1,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)+t4ddg_3(1,1,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)+t4ddg_3(1,1,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)+t4ddg_3(1,1,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)+t4ddg_3(1,1,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)+t4ddg_3(1,1,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)+t4ddg_3(1,1,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)+t4ddg_3(1,2,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)+t4ddg_3(1,2,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)+t4ddg_3(1,2,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)+t4ddg_3(1,2,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)+t4ddg_3(1,2,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)+t4ddg_3(1,2,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)+t4ddg_3(1,2,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)+t4ddg_3(1,2,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)+t4ddg_3(1,2,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)+t4ddg_3(2,0,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)+t4ddg_3(2,0,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)+t4ddg_3(2,0,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)+t4ddg_3(2,0,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)+t4ddg_3(2,0,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)+t4ddg_3(2,0,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)+t4ddg_3(2,0,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)+t4ddg_3(2,0,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)+t4ddg_3(2,0,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)+t4ddg_3(2,1,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)+t4ddg_3(2,1,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)+t4ddg_3(2,1,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)+t4ddg_3(2,1,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)+t4ddg_3(2,1,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)+t4ddg_3(2,1,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)+t4ddg_3(2,1,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)+t4ddg_3(2,1,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)+t4ddg_3(2,1,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)+t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)+t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)+t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)+t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)+t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)+t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)+t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)+t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)+t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(i,j,k,l)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=t4ddg_2(i,j,k,l)+t4ddg_3(k,l,i,j);
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)+t4ddg_3(0,0,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)+t4ddg_3(0,1,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)+t4ddg_3(0,2,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)+t4ddg_3(1,0,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)+t4ddg_3(1,1,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)+t4ddg_3(1,2,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)+t4ddg_3(2,0,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)+t4ddg_3(2,1,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)+t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)+t4ddg_3(0,0,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)+t4ddg_3(0,1,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)+t4ddg_3(0,2,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)+t4ddg_3(1,0,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)+t4ddg_3(1,1,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)+t4ddg_3(1,2,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)+t4ddg_3(2,0,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)+t4ddg_3(2,1,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)+t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)+t4ddg_3(0,0,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)+t4ddg_3(0,1,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)+t4ddg_3(0,2,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)+t4ddg_3(1,0,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)+t4ddg_3(1,1,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)+t4ddg_3(1,2,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)+t4ddg_3(2,0,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)+t4ddg_3(2,1,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)+t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)+t4ddg_3(0,0,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)+t4ddg_3(0,1,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)+t4ddg_3(0,2,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)+t4ddg_3(1,0,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)+t4ddg_3(1,1,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)+t4ddg_3(1,2,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)+t4ddg_3(2,0,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)+t4ddg_3(2,1,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)+t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)+t4ddg_3(0,0,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)+t4ddg_3(0,1,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)+t4ddg_3(0,2,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)+t4ddg_3(1,0,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)+t4ddg_3(1,1,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)+t4ddg_3(1,2,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)+t4ddg_3(2,0,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)+t4ddg_3(2,1,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)+t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)+t4ddg_3(0,0,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)+t4ddg_3(0,1,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)+t4ddg_3(0,2,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)+t4ddg_3(1,0,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)+t4ddg_3(1,1,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)+t4ddg_3(1,2,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)+t4ddg_3(2,0,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)+t4ddg_3(2,1,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)+t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)+t4ddg_3(0,0,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)+t4ddg_3(0,1,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)+t4ddg_3(0,2,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)+t4ddg_3(1,0,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)+t4ddg_3(1,1,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)+t4ddg_3(1,2,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)+t4ddg_3(2,0,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)+t4ddg_3(2,1,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)+t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)+t4ddg_3(0,0,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)+t4ddg_3(0,1,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)+t4ddg_3(0,2,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)+t4ddg_3(1,0,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)+t4ddg_3(1,1,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)+t4ddg_3(1,2,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)+t4ddg_3(2,0,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)+t4ddg_3(2,1,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)+t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)+t4ddg_3(0,0,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)+t4ddg_3(0,1,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)+t4ddg_3(0,2,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)+t4ddg_3(1,0,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)+t4ddg_3(1,1,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)+t4ddg_3(1,2,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)+t4ddg_3(2,0,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)+t4ddg_3(2,1,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)+t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)+T4ddg(k,l,i,j)(2,2,2,2)");
+
+
+  t4ddg_1(i,j,k,l)=t4ddg_2(i,j,k,l)-t4ddg_3(i,j,k,l);
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)-t4ddg_3(0,0,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)-t4ddg_3(0,0,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)-t4ddg_3(0,0,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)-t4ddg_3(0,0,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)-t4ddg_3(0,0,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)-t4ddg_3(0,0,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)-t4ddg_3(0,0,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)-t4ddg_3(0,0,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)-t4ddg_3(0,0,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)-t4ddg_3(0,1,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)-t4ddg_3(0,1,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)-t4ddg_3(0,1,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)-t4ddg_3(0,1,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)-t4ddg_3(0,1,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)-t4ddg_3(0,1,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)-t4ddg_3(0,1,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)-t4ddg_3(0,1,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)-t4ddg_3(0,1,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)-t4ddg_3(0,2,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)-t4ddg_3(0,2,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)-t4ddg_3(0,2,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)-t4ddg_3(0,2,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)-t4ddg_3(0,2,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)-t4ddg_3(0,2,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)-t4ddg_3(0,2,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)-t4ddg_3(0,2,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)-t4ddg_3(0,2,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)-t4ddg_3(1,0,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)-t4ddg_3(1,0,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)-t4ddg_3(1,0,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)-t4ddg_3(1,0,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)-t4ddg_3(1,0,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)-t4ddg_3(1,0,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)-t4ddg_3(1,0,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)-t4ddg_3(1,0,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)-t4ddg_3(1,0,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)-t4ddg_3(1,1,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)-t4ddg_3(1,1,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)-t4ddg_3(1,1,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)-t4ddg_3(1,1,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)-t4ddg_3(1,1,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)-t4ddg_3(1,1,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)-t4ddg_3(1,1,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)-t4ddg_3(1,1,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)-t4ddg_3(1,1,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)-t4ddg_3(1,2,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)-t4ddg_3(1,2,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)-t4ddg_3(1,2,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)-t4ddg_3(1,2,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)-t4ddg_3(1,2,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)-t4ddg_3(1,2,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)-t4ddg_3(1,2,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)-t4ddg_3(1,2,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)-t4ddg_3(1,2,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)-t4ddg_3(2,0,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)-t4ddg_3(2,0,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)-t4ddg_3(2,0,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)-t4ddg_3(2,0,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)-t4ddg_3(2,0,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)-t4ddg_3(2,0,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)-t4ddg_3(2,0,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)-t4ddg_3(2,0,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)-t4ddg_3(2,0,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)-t4ddg_3(2,1,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)-t4ddg_3(2,1,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)-t4ddg_3(2,1,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)-t4ddg_3(2,1,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)-t4ddg_3(2,1,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)-t4ddg_3(2,1,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)-t4ddg_3(2,1,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)-t4ddg_3(2,1,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)-t4ddg_3(2,1,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)-t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)-t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)-t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)-t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)-t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)-t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)-t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)-t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)-t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)-T4ddg(i,j,k,l)(2,2,2,2)");
+
+  t4ddg_2(i,k,j,l)=t2s_2(i,k)*t2s_2(j,l);
+  t4ddg_3(i,l,j,k)=t2s_2(i,l)*t2s_2(j,k);
+  t4ddg_1(i,j,k,l)=(t4ddg_2(i,k,j,l) || t4ddg_3(i,l,j,k));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)+t4ddg_3(0,0,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)+t4ddg_3(0,1,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)+t4ddg_3(0,2,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,0,1,0)+t4ddg_3(0,0,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,0,1,1)+t4ddg_3(0,1,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,0,1,2)+t4ddg_3(0,2,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,0,2,0)+t4ddg_3(0,0,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,0,2,1)+t4ddg_3(0,1,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,0,2,2)+t4ddg_3(0,2,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,1,0,0)+t4ddg_3(0,0,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,1,0,1)+t4ddg_3(0,1,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,1,0,2)+t4ddg_3(0,2,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)+t4ddg_3(0,0,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)+t4ddg_3(0,1,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)+t4ddg_3(0,2,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,1,2,0)+t4ddg_3(0,0,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,1,2,1)+t4ddg_3(0,1,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,1,2,2)+t4ddg_3(0,2,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,2,0,0)+t4ddg_3(0,0,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,2,0,1)+t4ddg_3(0,1,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,2,0,2)+t4ddg_3(0,2,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,2,1,0)+t4ddg_3(0,0,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,2,1,1)+t4ddg_3(0,1,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,2,1,2)+t4ddg_3(0,2,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)+t4ddg_3(0,0,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)+t4ddg_3(0,1,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)+t4ddg_3(0,2,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)+t4ddg_3(1,0,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)+t4ddg_3(1,1,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)+t4ddg_3(1,2,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,0,1,0)+t4ddg_3(1,0,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,0,1,1)+t4ddg_3(1,1,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,0,1,2)+t4ddg_3(1,2,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,0,2,0)+t4ddg_3(1,0,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,0,2,1)+t4ddg_3(1,1,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,0,2,2)+t4ddg_3(1,2,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,1,0,0)+t4ddg_3(1,0,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,1,0,1)+t4ddg_3(1,1,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,1,0,2)+t4ddg_3(1,2,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)+t4ddg_3(1,0,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)+t4ddg_3(1,1,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)+t4ddg_3(1,2,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,1,2,0)+t4ddg_3(1,0,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,1,2,1)+t4ddg_3(1,1,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,1,2,2)+t4ddg_3(1,2,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,2,0,0)+t4ddg_3(1,0,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,2,0,1)+t4ddg_3(1,1,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,2,0,2)+t4ddg_3(1,2,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,2,1,0)+t4ddg_3(1,0,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,2,1,1)+t4ddg_3(1,1,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,2,1,2)+t4ddg_3(1,2,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)+t4ddg_3(1,0,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)+t4ddg_3(1,1,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)+t4ddg_3(1,2,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)+t4ddg_3(2,0,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)+t4ddg_3(2,1,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)+t4ddg_3(2,2,0,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,0,1,0)+t4ddg_3(2,0,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,0,1,1)+t4ddg_3(2,1,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,0,1,2)+t4ddg_3(2,2,1,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,0,2,0)+t4ddg_3(2,0,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,0,2,1)+t4ddg_3(2,1,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,0,2,2)+t4ddg_3(2,2,2,0))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,1,0,0)+t4ddg_3(2,0,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,1,0,1)+t4ddg_3(2,1,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,1,0,2)+t4ddg_3(2,2,0,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)+t4ddg_3(2,0,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)+t4ddg_3(2,1,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)+t4ddg_3(2,2,1,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,1,2,0)+t4ddg_3(2,0,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,1,2,1)+t4ddg_3(2,1,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,1,2,2)+t4ddg_3(2,2,2,1))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,2,0,0)+t4ddg_3(2,0,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,2,0,1)+t4ddg_3(2,1,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,2,0,2)+t4ddg_3(2,2,0,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,2,1,0)+t4ddg_3(2,0,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,2,1,1)+t4ddg_3(2,1,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,2,1,2)+t4ddg_3(2,2,1,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)+t4ddg_3(2,0,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)+t4ddg_3(2,1,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)+t4ddg_3(2,2,2,2))
+		,"T4ddg(i,k,j,l)||T4ddg(i,l,j,k)(2,2,2,2)");
+
+  cout << endl;
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T4ddg/test_T4ddgII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T4ddg/test_T4ddgII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,849 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T4ddgII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  Tensor4_ddg<double,3,3> t4ddg_1, t4ddg_2, t4ddg_3;
+
+  t4ddg_2(i,k,j,l)=t2s_2(i,k)*t2s_2(j,l);
+  t4ddg_3(i,l,j,k)=t2s_2(i,l)*t2s_2(j,k);
+  t4ddg_1(i,k,m,n)=(t4ddg_2(i,j,k,l) ^ t4ddg_3(j,l,m,n));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,0,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(0,0,0,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(0,0,0,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(0,1,0,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(0,1,0,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(0,1,0,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(0,2,0,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(0,2,0,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(0,2,0,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,0,1,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(0,0,1,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(0,0,1,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(0,1,1,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(0,1,1,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(0,1,1,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(0,2,1,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(0,2,1,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(0,2,1,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,0,2,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(0,0,2,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(0,0,2,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(0,1,2,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(0,1,2,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(0,1,2,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(0,2,2,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(0,2,2,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(0,2,2,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,0,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(1,0,0,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(1,0,0,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(1,1,0,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(1,1,0,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(1,1,0,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(1,2,0,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(1,2,0,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(1,2,0,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,0,1,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(1,0,1,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(1,0,1,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(1,1,1,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(1,1,1,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(1,1,1,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(1,2,1,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(1,2,1,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(1,2,1,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,0,2,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(1,0,2,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(1,0,2,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(1,1,2,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(1,1,2,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(1,1,2,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(1,2,2,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(1,2,2,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(1,2,2,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,0,0)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,0,0)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,0,0)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,0,0)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,0,0)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,0,0)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,0,0)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,0,0)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,0,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,0,1)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,0,1)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,0,1)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,0,1)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,0,1)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,0,1)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,0,1)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,0,1)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,0,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,0,2)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,0,2)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,0,2)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,0,2)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,0,2)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,0,2)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,0,2)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,0,2)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,0,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,1,0)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,1,0)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,1,0)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,1,0)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,1,0)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,1,0)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,1,0)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,1,0)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,1,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,1,1)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,1,1)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,1,1)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,1,1)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,1,1)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,1,1)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,1,1)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,1,1)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,1,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,1,2)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,1,2)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,1,2)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,1,2)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,1,2)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,1,2)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,1,2)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,1,2)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,1,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,0,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(2,0,0,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(2,0,0,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(2,1,0,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(2,1,0,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(2,1,0,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(2,2,0,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(2,2,0,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(2,2,0,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,0,1,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(2,0,1,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(2,0,1,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(2,1,1,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(2,1,1,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(2,1,1,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(2,2,1,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(2,2,1,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(2,2,1,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,2,0)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,2,0)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,2,0)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,2,0)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,2,0)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,2,0)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,2,0)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,2,0)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,2,0))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,2,1)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,2,1)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,2,1)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,2,1)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,2,1)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,2,1)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,2,1)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,2,1)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,2,1))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,0,2,0)*t4ddg_3(0,0,2,2)
+				    + t4ddg_2(2,0,2,1)*t4ddg_3(0,1,2,2)
+				    + t4ddg_2(2,0,2,2)*t4ddg_3(0,2,2,2)
+				    + t4ddg_2(2,1,2,0)*t4ddg_3(1,0,2,2)
+				    + t4ddg_2(2,1,2,1)*t4ddg_3(1,1,2,2)
+				    + t4ddg_2(2,1,2,2)*t4ddg_3(1,2,2,2)
+				    + t4ddg_2(2,2,2,0)*t4ddg_3(2,0,2,2)
+				    + t4ddg_2(2,2,2,1)*t4ddg_3(2,1,2,2)
+				    + t4ddg_2(2,2,2,2)*t4ddg_3(2,2,2,2))
+		,"T4ddg(i,j,k,l)^T4ddg(j,l,m,n)(2,2,2,2)");
+  cout << endl;
+
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T4ddg/test_T4ddgIII.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T4ddg/test_T4ddgIII.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,2058 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T4ddgIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  Tensor4_ddg<double,3,3> t4ddg_1, t4ddg_2, t4ddg_3;
+
+  t4ddg_2(i,k,j,l)=t2s_2(i,k)*t2s_3(j,l);
+  t2_1(i,k)=t4ddg_2(i,j,k,l)*t2s_2(j,l);
+  test_for_zero(t2_1(0,0) - (t4ddg_2(0,0,0,0)*t2s_2(0,0)
+			     + t4ddg_2(0,0,0,1)*t2s_2(0,1)
+			     + t4ddg_2(0,0,0,2)*t2s_2(0,2)
+			     + t4ddg_2(0,1,0,0)*t2s_2(1,0)
+			     + t4ddg_2(0,1,0,1)*t2s_2(1,1)
+			     + t4ddg_2(0,1,0,2)*t2s_2(1,2)
+			     + t4ddg_2(0,2,0,0)*t2s_2(2,0)
+			     + t4ddg_2(0,2,0,1)*t2s_2(2,1)
+			     + t4ddg_2(0,2,0,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(0,0)");
+  test_for_zero(t2_1(0,1) - (t4ddg_2(0,0,1,0)*t2s_2(0,0)
+			     + t4ddg_2(0,0,1,1)*t2s_2(0,1)
+			     + t4ddg_2(0,0,1,2)*t2s_2(0,2)
+			     + t4ddg_2(0,1,1,0)*t2s_2(1,0)
+			     + t4ddg_2(0,1,1,1)*t2s_2(1,1)
+			     + t4ddg_2(0,1,1,2)*t2s_2(1,2)
+			     + t4ddg_2(0,2,1,0)*t2s_2(2,0)
+			     + t4ddg_2(0,2,1,1)*t2s_2(2,1)
+			     + t4ddg_2(0,2,1,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(0,1)");
+  test_for_zero(t2_1(0,2) - (t4ddg_2(0,0,2,0)*t2s_2(0,0)
+			     + t4ddg_2(0,0,2,1)*t2s_2(0,1)
+			     + t4ddg_2(0,0,2,2)*t2s_2(0,2)
+			     + t4ddg_2(0,1,2,0)*t2s_2(1,0)
+			     + t4ddg_2(0,1,2,1)*t2s_2(1,1)
+			     + t4ddg_2(0,1,2,2)*t2s_2(1,2)
+			     + t4ddg_2(0,2,2,0)*t2s_2(2,0)
+			     + t4ddg_2(0,2,2,1)*t2s_2(2,1)
+			     + t4ddg_2(0,2,2,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(0,2)");
+  test_for_zero(t2_1(1,0) - (t4ddg_2(1,0,0,0)*t2s_2(0,0)
+			     + t4ddg_2(1,0,0,1)*t2s_2(0,1)
+			     + t4ddg_2(1,0,0,2)*t2s_2(0,2)
+			     + t4ddg_2(1,1,0,0)*t2s_2(1,0)
+			     + t4ddg_2(1,1,0,1)*t2s_2(1,1)
+			     + t4ddg_2(1,1,0,2)*t2s_2(1,2)
+			     + t4ddg_2(1,2,0,0)*t2s_2(2,0)
+			     + t4ddg_2(1,2,0,1)*t2s_2(2,1)
+			     + t4ddg_2(1,2,0,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(1,0)");
+  test_for_zero(t2_1(1,1) - (t4ddg_2(1,0,1,0)*t2s_2(0,0)
+			     + t4ddg_2(1,0,1,1)*t2s_2(0,1)
+			     + t4ddg_2(1,0,1,2)*t2s_2(0,2)
+			     + t4ddg_2(1,1,1,0)*t2s_2(1,0)
+			     + t4ddg_2(1,1,1,1)*t2s_2(1,1)
+			     + t4ddg_2(1,1,1,2)*t2s_2(1,2)
+			     + t4ddg_2(1,2,1,0)*t2s_2(2,0)
+			     + t4ddg_2(1,2,1,1)*t2s_2(2,1)
+			     + t4ddg_2(1,2,1,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(1,1)");
+  test_for_zero(t2_1(1,2) - (t4ddg_2(1,0,2,0)*t2s_2(0,0)
+			     + t4ddg_2(1,0,2,1)*t2s_2(0,1)
+			     + t4ddg_2(1,0,2,2)*t2s_2(0,2)
+			     + t4ddg_2(1,1,2,0)*t2s_2(1,0)
+			     + t4ddg_2(1,1,2,1)*t2s_2(1,1)
+			     + t4ddg_2(1,1,2,2)*t2s_2(1,2)
+			     + t4ddg_2(1,2,2,0)*t2s_2(2,0)
+			     + t4ddg_2(1,2,2,1)*t2s_2(2,1)
+			     + t4ddg_2(1,2,2,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(1,2)");
+  test_for_zero(t2_1(2,0) - (t4ddg_2(2,0,0,0)*t2s_2(0,0)
+			     + t4ddg_2(2,0,0,1)*t2s_2(0,1)
+			     + t4ddg_2(2,0,0,2)*t2s_2(0,2)
+			     + t4ddg_2(2,1,0,0)*t2s_2(1,0)
+			     + t4ddg_2(2,1,0,1)*t2s_2(1,1)
+			     + t4ddg_2(2,1,0,2)*t2s_2(1,2)
+			     + t4ddg_2(2,2,0,0)*t2s_2(2,0)
+			     + t4ddg_2(2,2,0,1)*t2s_2(2,1)
+			     + t4ddg_2(2,2,0,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(2,0)");
+  test_for_zero(t2_1(2,1) - (t4ddg_2(2,0,1,0)*t2s_2(0,0)
+			     + t4ddg_2(2,0,1,1)*t2s_2(0,1)
+			     + t4ddg_2(2,0,1,2)*t2s_2(0,2)
+			     + t4ddg_2(2,1,1,0)*t2s_2(1,0)
+			     + t4ddg_2(2,1,1,1)*t2s_2(1,1)
+			     + t4ddg_2(2,1,1,2)*t2s_2(1,2)
+			     + t4ddg_2(2,2,1,0)*t2s_2(2,0)
+			     + t4ddg_2(2,2,1,1)*t2s_2(2,1)
+			     + t4ddg_2(2,2,1,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(2,1)");
+  test_for_zero(t2_1(2,2) - (t4ddg_2(2,0,2,0)*t2s_2(0,0)
+			     + t4ddg_2(2,0,2,1)*t2s_2(0,1)
+			     + t4ddg_2(2,0,2,2)*t2s_2(0,2)
+			     + t4ddg_2(2,1,2,0)*t2s_2(1,0)
+			     + t4ddg_2(2,1,2,1)*t2s_2(1,1)
+			     + t4ddg_2(2,1,2,2)*t2s_2(1,2)
+			     + t4ddg_2(2,2,2,0)*t2s_2(2,0)
+			     + t4ddg_2(2,2,2,1)*t2s_2(2,1)
+			     + t4ddg_2(2,2,2,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(j,l)(2,2)");
+
+  t2_1(i,k)=t2s_3(j,l)*t4ddg_2(i,j,k,l);
+  test_for_zero(t2_1(0,0) - (t4ddg_2(0,0,0,0)*t2s_3(0,0)
+			     + t4ddg_2(0,0,0,1)*t2s_3(0,1)
+			     + t4ddg_2(0,0,0,2)*t2s_3(0,2)
+			     + t4ddg_2(0,1,0,0)*t2s_3(1,0)
+			     + t4ddg_2(0,1,0,1)*t2s_3(1,1)
+			     + t4ddg_2(0,1,0,2)*t2s_3(1,2)
+			     + t4ddg_2(0,2,0,0)*t2s_3(2,0)
+			     + t4ddg_2(0,2,0,1)*t2s_3(2,1)
+			     + t4ddg_2(0,2,0,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(0,0)");
+  test_for_zero(t2_1(0,1) - (t4ddg_2(0,0,1,0)*t2s_3(0,0)
+			     + t4ddg_2(0,0,1,1)*t2s_3(0,1)
+			     + t4ddg_2(0,0,1,2)*t2s_3(0,2)
+			     + t4ddg_2(0,1,1,0)*t2s_3(1,0)
+			     + t4ddg_2(0,1,1,1)*t2s_3(1,1)
+			     + t4ddg_2(0,1,1,2)*t2s_3(1,2)
+			     + t4ddg_2(0,2,1,0)*t2s_3(2,0)
+			     + t4ddg_2(0,2,1,1)*t2s_3(2,1)
+			     + t4ddg_2(0,2,1,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(0,1)");
+  test_for_zero(t2_1(0,2) - (t4ddg_2(0,0,2,0)*t2s_3(0,0)
+			     + t4ddg_2(0,0,2,1)*t2s_3(0,1)
+			     + t4ddg_2(0,0,2,2)*t2s_3(0,2)
+			     + t4ddg_2(0,1,2,0)*t2s_3(1,0)
+			     + t4ddg_2(0,1,2,1)*t2s_3(1,1)
+			     + t4ddg_2(0,1,2,2)*t2s_3(1,2)
+			     + t4ddg_2(0,2,2,0)*t2s_3(2,0)
+			     + t4ddg_2(0,2,2,1)*t2s_3(2,1)
+			     + t4ddg_2(0,2,2,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(0,2)");
+  test_for_zero(t2_1(1,0) - (t4ddg_2(1,0,0,0)*t2s_3(0,0)
+			     + t4ddg_2(1,0,0,1)*t2s_3(0,1)
+			     + t4ddg_2(1,0,0,2)*t2s_3(0,2)
+			     + t4ddg_2(1,1,0,0)*t2s_3(1,0)
+			     + t4ddg_2(1,1,0,1)*t2s_3(1,1)
+			     + t4ddg_2(1,1,0,2)*t2s_3(1,2)
+			     + t4ddg_2(1,2,0,0)*t2s_3(2,0)
+			     + t4ddg_2(1,2,0,1)*t2s_3(2,1)
+			     + t4ddg_2(1,2,0,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(1,0)");
+  test_for_zero(t2_1(1,1) - (t4ddg_2(1,0,1,0)*t2s_3(0,0)
+			     + t4ddg_2(1,0,1,1)*t2s_3(0,1)
+			     + t4ddg_2(1,0,1,2)*t2s_3(0,2)
+			     + t4ddg_2(1,1,1,0)*t2s_3(1,0)
+			     + t4ddg_2(1,1,1,1)*t2s_3(1,1)
+			     + t4ddg_2(1,1,1,2)*t2s_3(1,2)
+			     + t4ddg_2(1,2,1,0)*t2s_3(2,0)
+			     + t4ddg_2(1,2,1,1)*t2s_3(2,1)
+			     + t4ddg_2(1,2,1,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(1,1)");
+  test_for_zero(t2_1(1,2) - (t4ddg_2(1,0,2,0)*t2s_3(0,0)
+			     + t4ddg_2(1,0,2,1)*t2s_3(0,1)
+			     + t4ddg_2(1,0,2,2)*t2s_3(0,2)
+			     + t4ddg_2(1,1,2,0)*t2s_3(1,0)
+			     + t4ddg_2(1,1,2,1)*t2s_3(1,1)
+			     + t4ddg_2(1,1,2,2)*t2s_3(1,2)
+			     + t4ddg_2(1,2,2,0)*t2s_3(2,0)
+			     + t4ddg_2(1,2,2,1)*t2s_3(2,1)
+			     + t4ddg_2(1,2,2,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(1,2)");
+  test_for_zero(t2_1(2,0) - (t4ddg_2(2,0,0,0)*t2s_3(0,0)
+			     + t4ddg_2(2,0,0,1)*t2s_3(0,1)
+			     + t4ddg_2(2,0,0,2)*t2s_3(0,2)
+			     + t4ddg_2(2,1,0,0)*t2s_3(1,0)
+			     + t4ddg_2(2,1,0,1)*t2s_3(1,1)
+			     + t4ddg_2(2,1,0,2)*t2s_3(1,2)
+			     + t4ddg_2(2,2,0,0)*t2s_3(2,0)
+			     + t4ddg_2(2,2,0,1)*t2s_3(2,1)
+			     + t4ddg_2(2,2,0,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(2,0)");
+  test_for_zero(t2_1(2,1) - (t4ddg_2(2,0,1,0)*t2s_3(0,0)
+			     + t4ddg_2(2,0,1,1)*t2s_3(0,1)
+			     + t4ddg_2(2,0,1,2)*t2s_3(0,2)
+			     + t4ddg_2(2,1,1,0)*t2s_3(1,0)
+			     + t4ddg_2(2,1,1,1)*t2s_3(1,1)
+			     + t4ddg_2(2,1,1,2)*t2s_3(1,2)
+			     + t4ddg_2(2,2,1,0)*t2s_3(2,0)
+			     + t4ddg_2(2,2,1,1)*t2s_3(2,1)
+			     + t4ddg_2(2,2,1,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(2,1)");
+  test_for_zero(t2_1(2,2) - (t4ddg_2(2,0,2,0)*t2s_3(0,0)
+			     + t4ddg_2(2,0,2,1)*t2s_3(0,1)
+			     + t4ddg_2(2,0,2,2)*t2s_3(0,2)
+			     + t4ddg_2(2,1,2,0)*t2s_3(1,0)
+			     + t4ddg_2(2,1,2,1)*t2s_3(1,1)
+			     + t4ddg_2(2,1,2,2)*t2s_3(1,2)
+			     + t4ddg_2(2,2,2,0)*t2s_3(2,0)
+			     + t4ddg_2(2,2,2,1)*t2s_3(2,1)
+			     + t4ddg_2(2,2,2,2)*t2s_3(2,2))
+		,"T2s(j,l)*T4ddg(i,j,k,l)(2,2)");
+
+  t2s_1(j,l)=t4ddg_2(i,k,j,l)*t2s_2(i,k);
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2s_2(0,0)
+			      + t4ddg_2(0,1,0,0)*t2s_2(0,1)
+			      + t4ddg_2(0,2,0,0)*t2s_2(0,2)
+			      + t4ddg_2(1,0,0,0)*t2s_2(1,0)
+			      + t4ddg_2(1,1,0,0)*t2s_2(1,1)
+			      + t4ddg_2(1,2,0,0)*t2s_2(1,2)
+			      + t4ddg_2(2,0,0,0)*t2s_2(2,0)
+			      + t4ddg_2(2,1,0,0)*t2s_2(2,1)
+			      + t4ddg_2(2,2,0,0)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,0,0,1)*t2s_2(0,0)
+			      + t4ddg_2(0,1,0,1)*t2s_2(0,1)
+			      + t4ddg_2(0,2,0,1)*t2s_2(0,2)
+			      + t4ddg_2(1,0,0,1)*t2s_2(1,0)
+			      + t4ddg_2(1,1,0,1)*t2s_2(1,1)
+			      + t4ddg_2(1,2,0,1)*t2s_2(1,2)
+			      + t4ddg_2(2,0,0,1)*t2s_2(2,0)
+			      + t4ddg_2(2,1,0,1)*t2s_2(2,1)
+			      + t4ddg_2(2,2,0,1)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,0,0,2)*t2s_2(0,0)
+			      + t4ddg_2(0,1,0,2)*t2s_2(0,1)
+			      + t4ddg_2(0,2,0,2)*t2s_2(0,2)
+			      + t4ddg_2(1,0,0,2)*t2s_2(1,0)
+			      + t4ddg_2(1,1,0,2)*t2s_2(1,1)
+			      + t4ddg_2(1,2,0,2)*t2s_2(1,2)
+			      + t4ddg_2(2,0,0,2)*t2s_2(2,0)
+			      + t4ddg_2(2,1,0,2)*t2s_2(2,1)
+			      + t4ddg_2(2,2,0,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(0,0,1,0)*t2s_2(0,0)
+			      + t4ddg_2(0,1,1,0)*t2s_2(0,1)
+			      + t4ddg_2(0,2,1,0)*t2s_2(0,2)
+			      + t4ddg_2(1,0,1,0)*t2s_2(1,0)
+			      + t4ddg_2(1,1,1,0)*t2s_2(1,1)
+			      + t4ddg_2(1,2,1,0)*t2s_2(1,2)
+			      + t4ddg_2(2,0,1,0)*t2s_2(2,0)
+			      + t4ddg_2(2,1,1,0)*t2s_2(2,1)
+			      + t4ddg_2(2,2,1,0)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(0,0,1,1)*t2s_2(0,0)
+			      + t4ddg_2(0,1,1,1)*t2s_2(0,1)
+			      + t4ddg_2(0,2,1,1)*t2s_2(0,2)
+			      + t4ddg_2(1,0,1,1)*t2s_2(1,0)
+			      + t4ddg_2(1,1,1,1)*t2s_2(1,1)
+			      + t4ddg_2(1,2,1,1)*t2s_2(1,2)
+			      + t4ddg_2(2,0,1,1)*t2s_2(2,0)
+			      + t4ddg_2(2,1,1,1)*t2s_2(2,1)
+			      + t4ddg_2(2,2,1,1)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(0,0,1,2)*t2s_2(0,0)
+			      + t4ddg_2(0,1,1,2)*t2s_2(0,1)
+			      + t4ddg_2(0,2,1,2)*t2s_2(0,2)
+			      + t4ddg_2(1,0,1,2)*t2s_2(1,0)
+			      + t4ddg_2(1,1,1,2)*t2s_2(1,1)
+			      + t4ddg_2(1,2,1,2)*t2s_2(1,2)
+			      + t4ddg_2(2,0,1,2)*t2s_2(2,0)
+			      + t4ddg_2(2,1,1,2)*t2s_2(2,1)
+			      + t4ddg_2(2,2,1,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(0,0,2,0)*t2s_2(0,0)
+			      + t4ddg_2(0,1,2,0)*t2s_2(0,1)
+			      + t4ddg_2(0,2,2,0)*t2s_2(0,2)
+			      + t4ddg_2(1,0,2,0)*t2s_2(1,0)
+			      + t4ddg_2(1,1,2,0)*t2s_2(1,1)
+			      + t4ddg_2(1,2,2,0)*t2s_2(1,2)
+			      + t4ddg_2(2,0,2,0)*t2s_2(2,0)
+			      + t4ddg_2(2,1,2,0)*t2s_2(2,1)
+			      + t4ddg_2(2,2,2,0)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(0,0,2,1)*t2s_2(0,0)
+			      + t4ddg_2(0,1,2,1)*t2s_2(0,1)
+			      + t4ddg_2(0,2,2,1)*t2s_2(0,2)
+			      + t4ddg_2(1,0,2,1)*t2s_2(1,0)
+			      + t4ddg_2(1,1,2,1)*t2s_2(1,1)
+			      + t4ddg_2(1,2,2,1)*t2s_2(1,2)
+			      + t4ddg_2(2,0,2,1)*t2s_2(2,0)
+			      + t4ddg_2(2,1,2,1)*t2s_2(2,1)
+			      + t4ddg_2(2,2,2,1)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(0,0,2,2)*t2s_2(0,0)
+			      + t4ddg_2(0,1,2,2)*t2s_2(0,1)
+			      + t4ddg_2(0,2,2,2)*t2s_2(0,2)
+			      + t4ddg_2(1,0,2,2)*t2s_2(1,0)
+			      + t4ddg_2(1,1,2,2)*t2s_2(1,1)
+			      + t4ddg_2(1,2,2,2)*t2s_2(1,2)
+			      + t4ddg_2(2,0,2,2)*t2s_2(2,0)
+			      + t4ddg_2(2,1,2,2)*t2s_2(2,1)
+			      + t4ddg_2(2,2,2,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)*T2s(i,k)(2,2)");
+
+  t2s_1(j,l)=t2s_3(i,k)*t4ddg_2(i,k,j,l);
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2s_3(0,0)
+			      + t4ddg_2(0,1,0,0)*t2s_3(0,1)
+			      + t4ddg_2(0,2,0,0)*t2s_3(0,2)
+			      + t4ddg_2(1,0,0,0)*t2s_3(1,0)
+			      + t4ddg_2(1,1,0,0)*t2s_3(1,1)
+			      + t4ddg_2(1,2,0,0)*t2s_3(1,2)
+			      + t4ddg_2(2,0,0,0)*t2s_3(2,0)
+			      + t4ddg_2(2,1,0,0)*t2s_3(2,1)
+			      + t4ddg_2(2,2,0,0)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,0,0,1)*t2s_3(0,0)
+			      + t4ddg_2(0,1,0,1)*t2s_3(0,1)
+			      + t4ddg_2(0,2,0,1)*t2s_3(0,2)
+			      + t4ddg_2(1,0,0,1)*t2s_3(1,0)
+			      + t4ddg_2(1,1,0,1)*t2s_3(1,1)
+			      + t4ddg_2(1,2,0,1)*t2s_3(1,2)
+			      + t4ddg_2(2,0,0,1)*t2s_3(2,0)
+			      + t4ddg_2(2,1,0,1)*t2s_3(2,1)
+			      + t4ddg_2(2,2,0,1)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,0,0,2)*t2s_3(0,0)
+			      + t4ddg_2(0,1,0,2)*t2s_3(0,1)
+			      + t4ddg_2(0,2,0,2)*t2s_3(0,2)
+			      + t4ddg_2(1,0,0,2)*t2s_3(1,0)
+			      + t4ddg_2(1,1,0,2)*t2s_3(1,1)
+			      + t4ddg_2(1,2,0,2)*t2s_3(1,2)
+			      + t4ddg_2(2,0,0,2)*t2s_3(2,0)
+			      + t4ddg_2(2,1,0,2)*t2s_3(2,1)
+			      + t4ddg_2(2,2,0,2)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(0,0,1,0)*t2s_3(0,0)
+			      + t4ddg_2(0,1,1,0)*t2s_3(0,1)
+			      + t4ddg_2(0,2,1,0)*t2s_3(0,2)
+			      + t4ddg_2(1,0,1,0)*t2s_3(1,0)
+			      + t4ddg_2(1,1,1,0)*t2s_3(1,1)
+			      + t4ddg_2(1,2,1,0)*t2s_3(1,2)
+			      + t4ddg_2(2,0,1,0)*t2s_3(2,0)
+			      + t4ddg_2(2,1,1,0)*t2s_3(2,1)
+			      + t4ddg_2(2,2,1,0)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(0,0,1,1)*t2s_3(0,0)
+			      + t4ddg_2(0,1,1,1)*t2s_3(0,1)
+			      + t4ddg_2(0,2,1,1)*t2s_3(0,2)
+			      + t4ddg_2(1,0,1,1)*t2s_3(1,0)
+			      + t4ddg_2(1,1,1,1)*t2s_3(1,1)
+			      + t4ddg_2(1,2,1,1)*t2s_3(1,2)
+			      + t4ddg_2(2,0,1,1)*t2s_3(2,0)
+			      + t4ddg_2(2,1,1,1)*t2s_3(2,1)
+			      + t4ddg_2(2,2,1,1)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(0,0,1,2)*t2s_3(0,0)
+			      + t4ddg_2(0,1,1,2)*t2s_3(0,1)
+			      + t4ddg_2(0,2,1,2)*t2s_3(0,2)
+			      + t4ddg_2(1,0,1,2)*t2s_3(1,0)
+			      + t4ddg_2(1,1,1,2)*t2s_3(1,1)
+			      + t4ddg_2(1,2,1,2)*t2s_3(1,2)
+			      + t4ddg_2(2,0,1,2)*t2s_3(2,0)
+			      + t4ddg_2(2,1,1,2)*t2s_3(2,1)
+			      + t4ddg_2(2,2,1,2)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(0,0,2,0)*t2s_3(0,0)
+			      + t4ddg_2(0,1,2,0)*t2s_3(0,1)
+			      + t4ddg_2(0,2,2,0)*t2s_3(0,2)
+			      + t4ddg_2(1,0,2,0)*t2s_3(1,0)
+			      + t4ddg_2(1,1,2,0)*t2s_3(1,1)
+			      + t4ddg_2(1,2,2,0)*t2s_3(1,2)
+			      + t4ddg_2(2,0,2,0)*t2s_3(2,0)
+			      + t4ddg_2(2,1,2,0)*t2s_3(2,1)
+			      + t4ddg_2(2,2,2,0)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(0,0,2,1)*t2s_3(0,0)
+			      + t4ddg_2(0,1,2,1)*t2s_3(0,1)
+			      + t4ddg_2(0,2,2,1)*t2s_3(0,2)
+			      + t4ddg_2(1,0,2,1)*t2s_3(1,0)
+			      + t4ddg_2(1,1,2,1)*t2s_3(1,1)
+			      + t4ddg_2(1,2,2,1)*t2s_3(1,2)
+			      + t4ddg_2(2,0,2,1)*t2s_3(2,0)
+			      + t4ddg_2(2,1,2,1)*t2s_3(2,1)
+			      + t4ddg_2(2,2,2,1)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(0,0,2,2)*t2s_3(0,0)
+			      + t4ddg_2(0,1,2,2)*t2s_3(0,1)
+			      + t4ddg_2(0,2,2,2)*t2s_3(0,2)
+			      + t4ddg_2(1,0,2,2)*t2s_3(1,0)
+			      + t4ddg_2(1,1,2,2)*t2s_3(1,1)
+			      + t4ddg_2(1,2,2,2)*t2s_3(1,2)
+			      + t4ddg_2(2,0,2,2)*t2s_3(2,0)
+			      + t4ddg_2(2,1,2,2)*t2s_3(2,1)
+			      + t4ddg_2(2,2,2,2)*t2s_3(2,2))
+		,"T2s(i,k)*T4ddg(i,j,k,l)(2,2)");
+
+  t4ddg_1(i,j,k,l)=(t4ddg_2(i,j,k,l)&t2s_3(i,j));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(i,j)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=(t2s_2(i,j)&t4ddg_2(i,j,k,l));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_2(0,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_2(0,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_2(0,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_2(1,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_2(1,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_2(1,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_2(2,0))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_2(2,1))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_2(2,2))
+		,"T2s(i,j)&T4ddg(i,j,k,l)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=(t4ddg_2(i,j,k,l)&t2s_3(k,l));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_3(0,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_3(0,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_3(0,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_3(1,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_3(1,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_3(1,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_3(2,0))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_3(2,1))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_3(2,2))
+		,"T4ddg(i,j,k,l)&T2s(k,l)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=(t2s_2(k,l)&t4ddg_2(i,j,k,l));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_2(0,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_2(0,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_2(0,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_2(1,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_2(1,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_2(1,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_2(2,0))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_2(2,1))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_2(2,2))
+		,"T2s(k,l)&T4ddg(i,j,k,l)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=(t4ddg_2(i,j,k,l)%t2s_3(i,j));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(i,j)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=(t2s_2(i,j)%t4ddg_2(i,j,k,l));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)/t2s_2(0,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)/t2s_2(0,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)/t2s_2(0,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)/t2s_2(1,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)/t2s_2(1,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)/t2s_2(1,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)/t2s_2(2,0))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)/t2s_2(2,1))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)/t2s_2(2,2))
+		,"T2s(i,j)%T4ddg(i,j,k,l)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=(t4ddg_2(i,j,k,l)%t2s_3(k,l));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)/t2s_3(0,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)/t2s_3(0,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)/t2s_3(0,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)/t2s_3(1,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)/t2s_3(1,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)/t2s_3(1,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)/t2s_3(2,0))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)/t2s_3(2,1))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)/t2s_3(2,2))
+		,"T4ddg(i,j,k,l)%T2s(k,l)(2,2,2,2)");
+
+  t4ddg_1(i,j,k,l)=(t2s_2(k,l)%t4ddg_2(i,j,k,l));
+  test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(1,2,2,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)/t2s_2(0,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)/t2s_2(0,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)/t2s_2(0,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)/t2s_2(1,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)/t2s_2(1,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)/t2s_2(1,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)/t2s_2(2,0))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)/t2s_2(2,1))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)/t2s_2(2,2))
+		,"T2s(k,l)%T4ddg(i,j,k,l)(2,2,2,2)");
+
+  /* I originally put these declarations for unknown reasons, but they
+     won't work because the result is not a Tensor4_ddg.  The
+     multiplication messes up the symmetries. */
+
+
+//    t4ddg_1(i,j,k,l)=(t4ddg_2(i,j,k,l)&t2s_3(j,l));
+//    test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_3(2,2)));
+
+
+//    t4ddg_1(i,j,k,l)=(t2s_2(j,l)&t4ddg_2(i,j,k,l));
+//    test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_2(2,2)));
+//    cout << endl;
+
+
+//    t4ddg_1(i,j,k,l)=(t4ddg_2(i,j,k,l)&t2s_3(l,j));
+//    test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_3(0,0))
+//        test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_3(0,1))
+//        test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_3(0,2))
+//        test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_3(1,0))
+//        test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_3(1,1))
+//        test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_3(1,2))
+//        test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_3(2,2))
+//        test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_3(2,0))
+//        test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_3(2,1))
+//        test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_3(2,2)));
+//    cout << endl;
+
+
+//    t4ddg_1(i,j,k,l)=(t2s_2(l,j)&t4ddg_2(i,j,k,l));
+//    test_for_zero(t4ddg_1(0,0,0,0) - (t4ddg_2(0,0,0,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(0,0,0,1) - (t4ddg_2(0,0,0,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(0,0,0,2) - (t4ddg_2(0,0,0,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(0,0,1,0) - (t4ddg_2(0,0,1,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(0,0,1,1) - (t4ddg_2(0,0,1,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(0,0,1,2) - (t4ddg_2(0,0,1,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(0,0,2,0) - (t4ddg_2(0,0,2,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(0,0,2,1) - (t4ddg_2(0,0,2,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(0,0,2,2) - (t4ddg_2(0,0,2,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(0,1,0,0) - (t4ddg_2(0,1,0,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(0,1,0,1) - (t4ddg_2(0,1,0,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(0,1,0,2) - (t4ddg_2(0,1,0,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(0,1,1,0) - (t4ddg_2(0,1,1,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(0,1,1,1) - (t4ddg_2(0,1,1,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(0,1,1,2) - (t4ddg_2(0,1,1,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(0,1,2,0) - (t4ddg_2(0,1,2,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(0,1,2,1) - (t4ddg_2(0,1,2,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(0,1,2,2) - (t4ddg_2(0,1,2,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(0,2,0,0) - (t4ddg_2(0,2,0,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(0,2,0,1) - (t4ddg_2(0,2,0,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(0,2,0,2) - (t4ddg_2(0,2,0,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(0,2,1,0) - (t4ddg_2(0,2,1,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(0,2,1,1) - (t4ddg_2(0,2,1,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(0,2,1,2) - (t4ddg_2(0,2,1,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(0,2,2,0) - (t4ddg_2(0,2,2,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(0,2,2,1) - (t4ddg_2(0,2,2,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(0,2,2,2) - (t4ddg_2(0,2,2,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(1,0,0,0) - (t4ddg_2(1,0,0,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(1,0,0,1) - (t4ddg_2(1,0,0,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(1,0,0,2) - (t4ddg_2(1,0,0,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(1,0,1,0) - (t4ddg_2(1,0,1,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(1,0,1,1) - (t4ddg_2(1,0,1,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(1,0,1,2) - (t4ddg_2(1,0,1,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(1,0,2,0) - (t4ddg_2(1,0,2,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(1,0,2,1) - (t4ddg_2(1,0,2,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(1,0,2,2) - (t4ddg_2(1,0,2,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(1,1,0,0) - (t4ddg_2(1,1,0,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(1,1,0,1) - (t4ddg_2(1,1,0,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(1,1,0,2) - (t4ddg_2(1,1,0,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(1,1,1,0) - (t4ddg_2(1,1,1,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(1,1,1,1) - (t4ddg_2(1,1,1,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(1,1,1,2) - (t4ddg_2(1,1,1,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(1,1,2,0) - (t4ddg_2(1,1,2,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(1,1,2,1) - (t4ddg_2(1,1,2,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(1,1,2,2) - (t4ddg_2(1,1,2,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(1,2,0,0) - (t4ddg_2(1,2,0,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(1,2,0,1) - (t4ddg_2(1,2,0,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(1,2,0,2) - (t4ddg_2(1,2,0,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(1,2,1,0) - (t4ddg_2(1,2,1,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(1,2,1,1) - (t4ddg_2(1,2,1,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(1,2,1,2) - (t4ddg_2(1,2,1,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(1,2,2,0) - (t4ddg_2(1,2,2,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(1,2,2,1) - (t4ddg_2(1,2,2,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(1,2,2,2) - (t4ddg_2(1,2,2,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(2,0,0,0) - (t4ddg_2(2,0,0,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(2,0,0,1) - (t4ddg_2(2,0,0,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(2,0,0,2) - (t4ddg_2(2,0,0,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(2,0,1,0) - (t4ddg_2(2,0,1,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(2,0,1,1) - (t4ddg_2(2,0,1,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(2,0,1,2) - (t4ddg_2(2,0,1,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(2,0,2,0) - (t4ddg_2(2,0,2,0)*t2s_2(0,0))
+//        test_for_zero(t4ddg_1(2,0,2,1) - (t4ddg_2(2,0,2,1)*t2s_2(0,1))
+//        test_for_zero(t4ddg_1(2,0,2,2) - (t4ddg_2(2,0,2,2)*t2s_2(0,2))
+//        test_for_zero(t4ddg_1(2,1,0,0) - (t4ddg_2(2,1,0,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(2,1,0,1) - (t4ddg_2(2,1,0,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(2,1,0,2) - (t4ddg_2(2,1,0,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(2,1,1,0) - (t4ddg_2(2,1,1,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(2,1,1,1) - (t4ddg_2(2,1,1,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(2,1,1,2) - (t4ddg_2(2,1,1,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(2,1,2,0) - (t4ddg_2(2,1,2,0)*t2s_2(1,0))
+//        test_for_zero(t4ddg_1(2,1,2,1) - (t4ddg_2(2,1,2,1)*t2s_2(1,1))
+//        test_for_zero(t4ddg_1(2,1,2,2) - (t4ddg_2(2,1,2,2)*t2s_2(1,2))
+//        test_for_zero(t4ddg_1(2,2,0,0) - (t4ddg_2(2,2,0,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(2,2,0,1) - (t4ddg_2(2,2,0,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(2,2,0,2) - (t4ddg_2(2,2,0,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(2,2,1,0) - (t4ddg_2(2,2,1,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(2,2,1,1) - (t4ddg_2(2,2,1,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(2,2,1,2) - (t4ddg_2(2,2,1,2)*t2s_2(2,2))
+//        test_for_zero(t4ddg_1(2,2,2,0) - (t4ddg_2(2,2,2,0)*t2s_2(2,0))
+//        test_for_zero(t4ddg_1(2,2,2,1) - (t4ddg_2(2,2,2,1)*t2s_2(2,1))
+//        test_for_zero(t4ddg_1(2,2,2,2) - (t4ddg_2(2,2,2,2)*t2s_2(2,2)));
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T4ddg/test_T4ddgIV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T4ddg/test_T4ddgIV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,698 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T4ddgIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  Tensor4_ddg<double,3,3> t4ddg_1, t4ddg_2, t4ddg_3;
+
+  t4ddg_2(i,j,l,m)=t2s_2(i,j)*t2s_2(l,m);
+  t2s_1(i,k)=(t4ddg_2(i,j,k,l) ^ t2s_2(j,l));
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2s_2(0,0)
+			      + t4ddg_2(0,0,0,1)*t2s_2(0,1)
+			      + t4ddg_2(0,0,0,2)*t2s_2(0,2)
+			      + t4ddg_2(0,1,0,0)*t2s_2(1,0)
+			      + t4ddg_2(0,1,0,1)*t2s_2(1,1)
+			      + t4ddg_2(0,1,0,2)*t2s_2(1,2)
+			      + t4ddg_2(0,2,0,0)*t2s_2(2,0)
+			      + t4ddg_2(0,2,0,1)*t2s_2(2,1)
+			      + t4ddg_2(0,2,0,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,0,1,0)*t2s_2(0,0)
+			      + t4ddg_2(0,0,1,1)*t2s_2(0,1)
+			      + t4ddg_2(0,0,1,2)*t2s_2(0,2)
+			      + t4ddg_2(0,1,1,0)*t2s_2(1,0)
+			      + t4ddg_2(0,1,1,1)*t2s_2(1,1)
+			      + t4ddg_2(0,1,1,2)*t2s_2(1,2)
+			      + t4ddg_2(0,2,1,0)*t2s_2(2,0)
+			      + t4ddg_2(0,2,1,1)*t2s_2(2,1)
+			      + t4ddg_2(0,2,1,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,0,2,0)*t2s_2(0,0)
+			      + t4ddg_2(0,0,2,1)*t2s_2(0,1)
+			      + t4ddg_2(0,0,2,2)*t2s_2(0,2)
+			      + t4ddg_2(0,1,2,0)*t2s_2(1,0)
+			      + t4ddg_2(0,1,2,1)*t2s_2(1,1)
+			      + t4ddg_2(0,1,2,2)*t2s_2(1,2)
+			      + t4ddg_2(0,2,2,0)*t2s_2(2,0)
+			      + t4ddg_2(0,2,2,1)*t2s_2(2,1)
+			      + t4ddg_2(0,2,2,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(1,0,0,0)*t2s_2(0,0)
+			      + t4ddg_2(1,0,0,1)*t2s_2(0,1)
+			      + t4ddg_2(1,0,0,2)*t2s_2(0,2)
+			      + t4ddg_2(1,1,0,0)*t2s_2(1,0)
+			      + t4ddg_2(1,1,0,1)*t2s_2(1,1)
+			      + t4ddg_2(1,1,0,2)*t2s_2(1,2)
+			      + t4ddg_2(1,2,0,0)*t2s_2(2,0)
+			      + t4ddg_2(1,2,0,1)*t2s_2(2,1)
+			      + t4ddg_2(1,2,0,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(1,0,1,0)*t2s_2(0,0)
+			      + t4ddg_2(1,0,1,1)*t2s_2(0,1)
+			      + t4ddg_2(1,0,1,2)*t2s_2(0,2)
+			      + t4ddg_2(1,1,1,0)*t2s_2(1,0)
+			      + t4ddg_2(1,1,1,1)*t2s_2(1,1)
+			      + t4ddg_2(1,1,1,2)*t2s_2(1,2)
+			      + t4ddg_2(1,2,1,0)*t2s_2(2,0)
+			      + t4ddg_2(1,2,1,1)*t2s_2(2,1)
+			      + t4ddg_2(1,2,1,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(1,0,2,0)*t2s_2(0,0)
+			      + t4ddg_2(1,0,2,1)*t2s_2(0,1)
+			      + t4ddg_2(1,0,2,2)*t2s_2(0,2)
+			      + t4ddg_2(1,1,2,0)*t2s_2(1,0)
+			      + t4ddg_2(1,1,2,1)*t2s_2(1,1)
+			      + t4ddg_2(1,1,2,2)*t2s_2(1,2)
+			      + t4ddg_2(1,2,2,0)*t2s_2(2,0)
+			      + t4ddg_2(1,2,2,1)*t2s_2(2,1)
+			      + t4ddg_2(1,2,2,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(2,0,0,0)*t2s_2(0,0)
+			      + t4ddg_2(2,0,0,1)*t2s_2(0,1)
+			      + t4ddg_2(2,0,0,2)*t2s_2(0,2)
+			      + t4ddg_2(2,1,0,0)*t2s_2(1,0)
+			      + t4ddg_2(2,1,0,1)*t2s_2(1,1)
+			      + t4ddg_2(2,1,0,2)*t2s_2(1,2)
+			      + t4ddg_2(2,2,0,0)*t2s_2(2,0)
+			      + t4ddg_2(2,2,0,1)*t2s_2(2,1)
+			      + t4ddg_2(2,2,0,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(2,0,1,0)*t2s_2(0,0)
+			      + t4ddg_2(2,0,1,1)*t2s_2(0,1)
+			      + t4ddg_2(2,0,1,2)*t2s_2(0,2)
+			      + t4ddg_2(2,1,1,0)*t2s_2(1,0)
+			      + t4ddg_2(2,1,1,1)*t2s_2(1,1)
+			      + t4ddg_2(2,1,1,2)*t2s_2(1,2)
+			      + t4ddg_2(2,2,1,0)*t2s_2(2,0)
+			      + t4ddg_2(2,2,1,1)*t2s_2(2,1)
+			      + t4ddg_2(2,2,1,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(2,0,2,0)*t2s_2(0,0)
+			      + t4ddg_2(2,0,2,1)*t2s_2(0,1)
+			      + t4ddg_2(2,0,2,2)*t2s_2(0,2)
+			      + t4ddg_2(2,1,2,0)*t2s_2(1,0)
+			      + t4ddg_2(2,1,2,1)*t2s_2(1,1)
+			      + t4ddg_2(2,1,2,2)*t2s_2(1,2)
+			      + t4ddg_2(2,2,2,0)*t2s_2(2,0)
+			      + t4ddg_2(2,2,2,1)*t2s_2(2,1)
+			      + t4ddg_2(2,2,2,2)*t2s_2(2,2))
+		,"T4ddg(i,j,k,l)^T2s(j,l)(2,2)");
+
+  t2s_1(i,k)=(t2s_3(j,l) ^ t4ddg_2(i,j,k,l));
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2s_3(0,0)
+			      + t4ddg_2(0,0,0,1)*t2s_3(0,1)
+			      + t4ddg_2(0,0,0,2)*t2s_3(0,2)
+			      + t4ddg_2(0,1,0,0)*t2s_3(1,0)
+			      + t4ddg_2(0,1,0,1)*t2s_3(1,1)
+			      + t4ddg_2(0,1,0,2)*t2s_3(1,2)
+			      + t4ddg_2(0,2,0,0)*t2s_3(2,0)
+			      + t4ddg_2(0,2,0,1)*t2s_3(2,1)
+			      + t4ddg_2(0,2,0,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,0,1,0)*t2s_3(0,0)
+			      + t4ddg_2(0,0,1,1)*t2s_3(0,1)
+			      + t4ddg_2(0,0,1,2)*t2s_3(0,2)
+			      + t4ddg_2(0,1,1,0)*t2s_3(1,0)
+			      + t4ddg_2(0,1,1,1)*t2s_3(1,1)
+			      + t4ddg_2(0,1,1,2)*t2s_3(1,2)
+			      + t4ddg_2(0,2,1,0)*t2s_3(2,0)
+			      + t4ddg_2(0,2,1,1)*t2s_3(2,1)
+			      + t4ddg_2(0,2,1,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,0,2,0)*t2s_3(0,0)
+			      + t4ddg_2(0,0,2,1)*t2s_3(0,1)
+			      + t4ddg_2(0,0,2,2)*t2s_3(0,2)
+			      + t4ddg_2(0,1,2,0)*t2s_3(1,0)
+			      + t4ddg_2(0,1,2,1)*t2s_3(1,1)
+			      + t4ddg_2(0,1,2,2)*t2s_3(1,2)
+			      + t4ddg_2(0,2,2,0)*t2s_3(2,0)
+			      + t4ddg_2(0,2,2,1)*t2s_3(2,1)
+			      + t4ddg_2(0,2,2,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(1,0,0,0)*t2s_3(0,0)
+			      + t4ddg_2(1,0,0,1)*t2s_3(0,1)
+			      + t4ddg_2(1,0,0,2)*t2s_3(0,2)
+			      + t4ddg_2(1,1,0,0)*t2s_3(1,0)
+			      + t4ddg_2(1,1,0,1)*t2s_3(1,1)
+			      + t4ddg_2(1,1,0,2)*t2s_3(1,2)
+			      + t4ddg_2(1,2,0,0)*t2s_3(2,0)
+			      + t4ddg_2(1,2,0,1)*t2s_3(2,1)
+			      + t4ddg_2(1,2,0,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(1,0,1,0)*t2s_3(0,0)
+			      + t4ddg_2(1,0,1,1)*t2s_3(0,1)
+			      + t4ddg_2(1,0,1,2)*t2s_3(0,2)
+			      + t4ddg_2(1,1,1,0)*t2s_3(1,0)
+			      + t4ddg_2(1,1,1,1)*t2s_3(1,1)
+			      + t4ddg_2(1,1,1,2)*t2s_3(1,2)
+			      + t4ddg_2(1,2,1,0)*t2s_3(2,0)
+			      + t4ddg_2(1,2,1,1)*t2s_3(2,1)
+			      + t4ddg_2(1,2,1,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(1,0,2,0)*t2s_3(0,0)
+			      + t4ddg_2(1,0,2,1)*t2s_3(0,1)
+			      + t4ddg_2(1,0,2,2)*t2s_3(0,2)
+			      + t4ddg_2(1,1,2,0)*t2s_3(1,0)
+			      + t4ddg_2(1,1,2,1)*t2s_3(1,1)
+			      + t4ddg_2(1,1,2,2)*t2s_3(1,2)
+			      + t4ddg_2(1,2,2,0)*t2s_3(2,0)
+			      + t4ddg_2(1,2,2,1)*t2s_3(2,1)
+			      + t4ddg_2(1,2,2,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(2,0,0,0)*t2s_3(0,0)
+			      + t4ddg_2(2,0,0,1)*t2s_3(0,1)
+			      + t4ddg_2(2,0,0,2)*t2s_3(0,2)
+			      + t4ddg_2(2,1,0,0)*t2s_3(1,0)
+			      + t4ddg_2(2,1,0,1)*t2s_3(1,1)
+			      + t4ddg_2(2,1,0,2)*t2s_3(1,2)
+			      + t4ddg_2(2,2,0,0)*t2s_3(2,0)
+			      + t4ddg_2(2,2,0,1)*t2s_3(2,1)
+			      + t4ddg_2(2,2,0,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(2,0,1,0)*t2s_3(0,0)
+			      + t4ddg_2(2,0,1,1)*t2s_3(0,1)
+			      + t4ddg_2(2,0,1,2)*t2s_3(0,2)
+			      + t4ddg_2(2,1,1,0)*t2s_3(1,0)
+			      + t4ddg_2(2,1,1,1)*t2s_3(1,1)
+			      + t4ddg_2(2,1,1,2)*t2s_3(1,2)
+			      + t4ddg_2(2,2,1,0)*t2s_3(2,0)
+			      + t4ddg_2(2,2,1,1)*t2s_3(2,1)
+			      + t4ddg_2(2,2,1,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(2,0,2,0)*t2s_3(0,0)
+			      + t4ddg_2(2,0,2,1)*t2s_3(0,1)
+			      + t4ddg_2(2,0,2,2)*t2s_3(0,2)
+			      + t4ddg_2(2,1,2,0)*t2s_3(1,0)
+			      + t4ddg_2(2,1,2,1)*t2s_3(1,1)
+			      + t4ddg_2(2,1,2,2)*t2s_3(1,2)
+			      + t4ddg_2(2,2,2,0)*t2s_3(2,0)
+			      + t4ddg_2(2,2,2,1)*t2s_3(2,1)
+			      + t4ddg_2(2,2,2,2)*t2s_3(2,2))
+		,"T2s(j,l)^T4ddg(i,j,k,l)(2,2)");
+
+  t2s_1(i,k)=t4ddg_2(i,k,j,l)*t2_2(j,l);
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2_2(0,0)
+			      + t4ddg_2(0,0,0,1)*t2_2(0,1)
+			      + t4ddg_2(0,0,0,2)*t2_2(0,2)
+			      + t4ddg_2(0,0,1,0)*t2_2(1,0)
+			      + t4ddg_2(0,0,1,1)*t2_2(1,1)
+			      + t4ddg_2(0,0,1,2)*t2_2(1,2)
+			      + t4ddg_2(0,0,2,0)*t2_2(2,0)
+			      + t4ddg_2(0,0,2,1)*t2_2(2,1)
+			      + t4ddg_2(0,0,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,1,0,0)*t2_2(0,0)
+			      + t4ddg_2(0,1,0,1)*t2_2(0,1)
+			      + t4ddg_2(0,1,0,2)*t2_2(0,2)
+			      + t4ddg_2(0,1,1,0)*t2_2(1,0)
+			      + t4ddg_2(0,1,1,1)*t2_2(1,1)
+			      + t4ddg_2(0,1,1,2)*t2_2(1,2)
+			      + t4ddg_2(0,1,2,0)*t2_2(2,0)
+			      + t4ddg_2(0,1,2,1)*t2_2(2,1)
+			      + t4ddg_2(0,1,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,2,0,0)*t2_2(0,0)
+			      + t4ddg_2(0,2,0,1)*t2_2(0,1)
+			      + t4ddg_2(0,2,0,2)*t2_2(0,2)
+			      + t4ddg_2(0,2,1,0)*t2_2(1,0)
+			      + t4ddg_2(0,2,1,1)*t2_2(1,1)
+			      + t4ddg_2(0,2,1,2)*t2_2(1,2)
+			      + t4ddg_2(0,2,2,0)*t2_2(2,0)
+			      + t4ddg_2(0,2,2,1)*t2_2(2,1)
+			      + t4ddg_2(0,2,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(1,0,0,0)*t2_2(0,0)
+			      + t4ddg_2(1,0,0,1)*t2_2(0,1)
+			      + t4ddg_2(1,0,0,2)*t2_2(0,2)
+			      + t4ddg_2(1,0,1,0)*t2_2(1,0)
+			      + t4ddg_2(1,0,1,1)*t2_2(1,1)
+			      + t4ddg_2(1,0,1,2)*t2_2(1,2)
+			      + t4ddg_2(1,0,2,0)*t2_2(2,0)
+			      + t4ddg_2(1,0,2,1)*t2_2(2,1)
+			      + t4ddg_2(1,0,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(1,1,0,0)*t2_2(0,0)
+			      + t4ddg_2(1,1,0,1)*t2_2(0,1)
+			      + t4ddg_2(1,1,0,2)*t2_2(0,2)
+			      + t4ddg_2(1,1,1,0)*t2_2(1,0)
+			      + t4ddg_2(1,1,1,1)*t2_2(1,1)
+			      + t4ddg_2(1,1,1,2)*t2_2(1,2)
+			      + t4ddg_2(1,1,2,0)*t2_2(2,0)
+			      + t4ddg_2(1,1,2,1)*t2_2(2,1)
+			      + t4ddg_2(1,1,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(1,2,0,0)*t2_2(0,0)
+			      + t4ddg_2(1,2,0,1)*t2_2(0,1)
+			      + t4ddg_2(1,2,0,2)*t2_2(0,2)
+			      + t4ddg_2(1,2,1,0)*t2_2(1,0)
+			      + t4ddg_2(1,2,1,1)*t2_2(1,1)
+			      + t4ddg_2(1,2,1,2)*t2_2(1,2)
+			      + t4ddg_2(1,2,2,0)*t2_2(2,0)
+			      + t4ddg_2(1,2,2,1)*t2_2(2,1)
+			      + t4ddg_2(1,2,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(2,0,0,0)*t2_2(0,0)
+			      + t4ddg_2(2,0,0,1)*t2_2(0,1)
+			      + t4ddg_2(2,0,0,2)*t2_2(0,2)
+			      + t4ddg_2(2,0,1,0)*t2_2(1,0)
+			      + t4ddg_2(2,0,1,1)*t2_2(1,1)
+			      + t4ddg_2(2,0,1,2)*t2_2(1,2)
+			      + t4ddg_2(2,0,2,0)*t2_2(2,0)
+			      + t4ddg_2(2,0,2,1)*t2_2(2,1)
+			      + t4ddg_2(2,0,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(2,1,0,0)*t2_2(0,0)
+			      + t4ddg_2(2,1,0,1)*t2_2(0,1)
+			      + t4ddg_2(2,1,0,2)*t2_2(0,2)
+			      + t4ddg_2(2,1,1,0)*t2_2(1,0)
+			      + t4ddg_2(2,1,1,1)*t2_2(1,1)
+			      + t4ddg_2(2,1,1,2)*t2_2(1,2)
+			      + t4ddg_2(2,1,2,0)*t2_2(2,0)
+			      + t4ddg_2(2,1,2,1)*t2_2(2,1)
+			      + t4ddg_2(2,1,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(2,2,0,0)*t2_2(0,0)
+			      + t4ddg_2(2,2,0,1)*t2_2(0,1)
+			      + t4ddg_2(2,2,0,2)*t2_2(0,2)
+			      + t4ddg_2(2,2,1,0)*t2_2(1,0)
+			      + t4ddg_2(2,2,1,1)*t2_2(1,1)
+			      + t4ddg_2(2,2,1,2)*t2_2(1,2)
+			      + t4ddg_2(2,2,2,0)*t2_2(2,0)
+			      + t4ddg_2(2,2,2,1)*t2_2(2,1)
+			      + t4ddg_2(2,2,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(j,l)(2,2)");
+
+  t2s_1(i,k)=t2_3(j,l)*t4ddg_2(i,k,j,l);
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2_3(0,0)
+			      + t4ddg_2(0,0,0,1)*t2_3(0,1)
+			      + t4ddg_2(0,0,0,2)*t2_3(0,2)
+			      + t4ddg_2(0,0,1,0)*t2_3(1,0)
+			      + t4ddg_2(0,0,1,1)*t2_3(1,1)
+			      + t4ddg_2(0,0,1,2)*t2_3(1,2)
+			      + t4ddg_2(0,0,2,0)*t2_3(2,0)
+			      + t4ddg_2(0,0,2,1)*t2_3(2,1)
+			      + t4ddg_2(0,0,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,1,0,0)*t2_3(0,0)
+			      + t4ddg_2(0,1,0,1)*t2_3(0,1)
+			      + t4ddg_2(0,1,0,2)*t2_3(0,2)
+			      + t4ddg_2(0,1,1,0)*t2_3(1,0)
+			      + t4ddg_2(0,1,1,1)*t2_3(1,1)
+			      + t4ddg_2(0,1,1,2)*t2_3(1,2)
+			      + t4ddg_2(0,1,2,0)*t2_3(2,0)
+			      + t4ddg_2(0,1,2,1)*t2_3(2,1)
+			      + t4ddg_2(0,1,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,2,0,0)*t2_3(0,0)
+			      + t4ddg_2(0,2,0,1)*t2_3(0,1)
+			      + t4ddg_2(0,2,0,2)*t2_3(0,2)
+			      + t4ddg_2(0,2,1,0)*t2_3(1,0)
+			      + t4ddg_2(0,2,1,1)*t2_3(1,1)
+			      + t4ddg_2(0,2,1,2)*t2_3(1,2)
+			      + t4ddg_2(0,2,2,0)*t2_3(2,0)
+			      + t4ddg_2(0,2,2,1)*t2_3(2,1)
+			      + t4ddg_2(0,2,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(1,0,0,0)*t2_3(0,0)
+			      + t4ddg_2(1,0,0,1)*t2_3(0,1)
+			      + t4ddg_2(1,0,0,2)*t2_3(0,2)
+			      + t4ddg_2(1,0,1,0)*t2_3(1,0)
+			      + t4ddg_2(1,0,1,1)*t2_3(1,1)
+			      + t4ddg_2(1,0,1,2)*t2_3(1,2)
+			      + t4ddg_2(1,0,2,0)*t2_3(2,0)
+			      + t4ddg_2(1,0,2,1)*t2_3(2,1)
+			      + t4ddg_2(1,0,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(1,1,0,0)*t2_3(0,0)
+			      + t4ddg_2(1,1,0,1)*t2_3(0,1)
+			      + t4ddg_2(1,1,0,2)*t2_3(0,2)
+			      + t4ddg_2(1,1,1,0)*t2_3(1,0)
+			      + t4ddg_2(1,1,1,1)*t2_3(1,1)
+			      + t4ddg_2(1,1,1,2)*t2_3(1,2)
+			      + t4ddg_2(1,1,2,0)*t2_3(2,0)
+			      + t4ddg_2(1,1,2,1)*t2_3(2,1)
+			      + t4ddg_2(1,1,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(1,2,0,0)*t2_3(0,0)
+			      + t4ddg_2(1,2,0,1)*t2_3(0,1)
+			      + t4ddg_2(1,2,0,2)*t2_3(0,2)
+			      + t4ddg_2(1,2,1,0)*t2_3(1,0)
+			      + t4ddg_2(1,2,1,1)*t2_3(1,1)
+			      + t4ddg_2(1,2,1,2)*t2_3(1,2)
+			      + t4ddg_2(1,2,2,0)*t2_3(2,0)
+			      + t4ddg_2(1,2,2,1)*t2_3(2,1)
+			      + t4ddg_2(1,2,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(2,0,0,0)*t2_3(0,0)
+			      + t4ddg_2(2,0,0,1)*t2_3(0,1)
+			      + t4ddg_2(2,0,0,2)*t2_3(0,2)
+			      + t4ddg_2(2,0,1,0)*t2_3(1,0)
+			      + t4ddg_2(2,0,1,1)*t2_3(1,1)
+			      + t4ddg_2(2,0,1,2)*t2_3(1,2)
+			      + t4ddg_2(2,0,2,0)*t2_3(2,0)
+			      + t4ddg_2(2,0,2,1)*t2_3(2,1)
+			      + t4ddg_2(2,0,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(2,1,0,0)*t2_3(0,0)
+			      + t4ddg_2(2,1,0,1)*t2_3(0,1)
+			      + t4ddg_2(2,1,0,2)*t2_3(0,2)
+			      + t4ddg_2(2,1,1,0)*t2_3(1,0)
+			      + t4ddg_2(2,1,1,1)*t2_3(1,1)
+			      + t4ddg_2(2,1,1,2)*t2_3(1,2)
+			      + t4ddg_2(2,1,2,0)*t2_3(2,0)
+			      + t4ddg_2(2,1,2,1)*t2_3(2,1)
+			      + t4ddg_2(2,1,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(2,2,0,0)*t2_3(0,0)
+			      + t4ddg_2(2,2,0,1)*t2_3(0,1)
+			      + t4ddg_2(2,2,0,2)*t2_3(0,2)
+			      + t4ddg_2(2,2,1,0)*t2_3(1,0)
+			      + t4ddg_2(2,2,1,1)*t2_3(1,1)
+			      + t4ddg_2(2,2,1,2)*t2_3(1,2)
+			      + t4ddg_2(2,2,2,0)*t2_3(2,0)
+			      + t4ddg_2(2,2,2,1)*t2_3(2,1)
+			      + t4ddg_2(2,2,2,2)*t2_3(2,2))
+		,"T2(j,l)*T4ddg(i,j,k,l)(2,2)");
+
+
+  t2s_1(i,k)=t4ddg_2(i,k,j,l)*t2_2(l,j);
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2_2(0,0)
+			      + t4ddg_2(0,0,0,1)*t2_2(0,1)
+			      + t4ddg_2(0,0,0,2)*t2_2(0,2)
+			      + t4ddg_2(0,0,1,0)*t2_2(1,0)
+			      + t4ddg_2(0,0,1,1)*t2_2(1,1)
+			      + t4ddg_2(0,0,1,2)*t2_2(1,2)
+			      + t4ddg_2(0,0,2,0)*t2_2(2,0)
+			      + t4ddg_2(0,0,2,1)*t2_2(2,1)
+			      + t4ddg_2(0,0,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,1,0,0)*t2_2(0,0)
+			      + t4ddg_2(0,1,0,1)*t2_2(0,1)
+			      + t4ddg_2(0,1,0,2)*t2_2(0,2)
+			      + t4ddg_2(0,1,1,0)*t2_2(1,0)
+			      + t4ddg_2(0,1,1,1)*t2_2(1,1)
+			      + t4ddg_2(0,1,1,2)*t2_2(1,2)
+			      + t4ddg_2(0,1,2,0)*t2_2(2,0)
+			      + t4ddg_2(0,1,2,1)*t2_2(2,1)
+			      + t4ddg_2(0,1,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,2,0,0)*t2_2(0,0)
+			      + t4ddg_2(0,2,0,1)*t2_2(0,1)
+			      + t4ddg_2(0,2,0,2)*t2_2(0,2)
+			      + t4ddg_2(0,2,1,0)*t2_2(1,0)
+			      + t4ddg_2(0,2,1,1)*t2_2(1,1)
+			      + t4ddg_2(0,2,1,2)*t2_2(1,2)
+			      + t4ddg_2(0,2,2,0)*t2_2(2,0)
+			      + t4ddg_2(0,2,2,1)*t2_2(2,1)
+			      + t4ddg_2(0,2,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(1,0,0,0)*t2_2(0,0)
+			      + t4ddg_2(1,0,0,1)*t2_2(0,1)
+			      + t4ddg_2(1,0,0,2)*t2_2(0,2)
+			      + t4ddg_2(1,0,1,0)*t2_2(1,0)
+			      + t4ddg_2(1,0,1,1)*t2_2(1,1)
+			      + t4ddg_2(1,0,1,2)*t2_2(1,2)
+			      + t4ddg_2(1,0,2,0)*t2_2(2,0)
+			      + t4ddg_2(1,0,2,1)*t2_2(2,1)
+			      + t4ddg_2(1,0,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(1,1,0,0)*t2_2(0,0)
+			      + t4ddg_2(1,1,0,1)*t2_2(0,1)
+			      + t4ddg_2(1,1,0,2)*t2_2(0,2)
+			      + t4ddg_2(1,1,1,0)*t2_2(1,0)
+			      + t4ddg_2(1,1,1,1)*t2_2(1,1)
+			      + t4ddg_2(1,1,1,2)*t2_2(1,2)
+			      + t4ddg_2(1,1,2,0)*t2_2(2,0)
+			      + t4ddg_2(1,1,2,1)*t2_2(2,1)
+			      + t4ddg_2(1,1,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(1,2,0,0)*t2_2(0,0)
+			      + t4ddg_2(1,2,0,1)*t2_2(0,1)
+			      + t4ddg_2(1,2,0,2)*t2_2(0,2)
+			      + t4ddg_2(1,2,1,0)*t2_2(1,0)
+			      + t4ddg_2(1,2,1,1)*t2_2(1,1)
+			      + t4ddg_2(1,2,1,2)*t2_2(1,2)
+			      + t4ddg_2(1,2,2,0)*t2_2(2,0)
+			      + t4ddg_2(1,2,2,1)*t2_2(2,1)
+			      + t4ddg_2(1,2,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(2,0,0,0)*t2_2(0,0)
+			      + t4ddg_2(2,0,0,1)*t2_2(0,1)
+			      + t4ddg_2(2,0,0,2)*t2_2(0,2)
+			      + t4ddg_2(2,0,1,0)*t2_2(1,0)
+			      + t4ddg_2(2,0,1,1)*t2_2(1,1)
+			      + t4ddg_2(2,0,1,2)*t2_2(1,2)
+			      + t4ddg_2(2,0,2,0)*t2_2(2,0)
+			      + t4ddg_2(2,0,2,1)*t2_2(2,1)
+			      + t4ddg_2(2,0,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(2,1,0,0)*t2_2(0,0)
+			      + t4ddg_2(2,1,0,1)*t2_2(0,1)
+			      + t4ddg_2(2,1,0,2)*t2_2(0,2)
+			      + t4ddg_2(2,1,1,0)*t2_2(1,0)
+			      + t4ddg_2(2,1,1,1)*t2_2(1,1)
+			      + t4ddg_2(2,1,1,2)*t2_2(1,2)
+			      + t4ddg_2(2,1,2,0)*t2_2(2,0)
+			      + t4ddg_2(2,1,2,1)*t2_2(2,1)
+			      + t4ddg_2(2,1,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(2,2,0,0)*t2_2(0,0)
+			      + t4ddg_2(2,2,0,1)*t2_2(0,1)
+			      + t4ddg_2(2,2,0,2)*t2_2(0,2)
+			      + t4ddg_2(2,2,1,0)*t2_2(1,0)
+			      + t4ddg_2(2,2,1,1)*t2_2(1,1)
+			      + t4ddg_2(2,2,1,2)*t2_2(1,2)
+			      + t4ddg_2(2,2,2,0)*t2_2(2,0)
+			      + t4ddg_2(2,2,2,1)*t2_2(2,1)
+			      + t4ddg_2(2,2,2,2)*t2_2(2,2))
+		,"T4ddg(i,j,k,l)*T2(l,j)(2,2)");
+
+  t2s_1(i,k)=t2_3(l,j)*t4ddg_2(i,k,j,l);
+  test_for_zero(t2s_1(0,0) - (t4ddg_2(0,0,0,0)*t2_3(0,0)
+			      + t4ddg_2(0,0,0,1)*t2_3(0,1)
+			      + t4ddg_2(0,0,0,2)*t2_3(0,2)
+			      + t4ddg_2(0,0,1,0)*t2_3(1,0)
+			      + t4ddg_2(0,0,1,1)*t2_3(1,1)
+			      + t4ddg_2(0,0,1,2)*t2_3(1,2)
+			      + t4ddg_2(0,0,2,0)*t2_3(2,0)
+			      + t4ddg_2(0,0,2,1)*t2_3(2,1)
+			      + t4ddg_2(0,0,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(0,0)");
+  test_for_zero(t2s_1(0,1) - (t4ddg_2(0,1,0,0)*t2_3(0,0)
+			      + t4ddg_2(0,1,0,1)*t2_3(0,1)
+			      + t4ddg_2(0,1,0,2)*t2_3(0,2)
+			      + t4ddg_2(0,1,1,0)*t2_3(1,0)
+			      + t4ddg_2(0,1,1,1)*t2_3(1,1)
+			      + t4ddg_2(0,1,1,2)*t2_3(1,2)
+			      + t4ddg_2(0,1,2,0)*t2_3(2,0)
+			      + t4ddg_2(0,1,2,1)*t2_3(2,1)
+			      + t4ddg_2(0,1,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(0,1)");
+  test_for_zero(t2s_1(0,2) - (t4ddg_2(0,2,0,0)*t2_3(0,0)
+			      + t4ddg_2(0,2,0,1)*t2_3(0,1)
+			      + t4ddg_2(0,2,0,2)*t2_3(0,2)
+			      + t4ddg_2(0,2,1,0)*t2_3(1,0)
+			      + t4ddg_2(0,2,1,1)*t2_3(1,1)
+			      + t4ddg_2(0,2,1,2)*t2_3(1,2)
+			      + t4ddg_2(0,2,2,0)*t2_3(2,0)
+			      + t4ddg_2(0,2,2,1)*t2_3(2,1)
+			      + t4ddg_2(0,2,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(0,2)");
+  test_for_zero(t2s_1(1,0) - (t4ddg_2(1,0,0,0)*t2_3(0,0)
+			      + t4ddg_2(1,0,0,1)*t2_3(0,1)
+			      + t4ddg_2(1,0,0,2)*t2_3(0,2)
+			      + t4ddg_2(1,0,1,0)*t2_3(1,0)
+			      + t4ddg_2(1,0,1,1)*t2_3(1,1)
+			      + t4ddg_2(1,0,1,2)*t2_3(1,2)
+			      + t4ddg_2(1,0,2,0)*t2_3(2,0)
+			      + t4ddg_2(1,0,2,1)*t2_3(2,1)
+			      + t4ddg_2(1,0,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(1,0)");
+  test_for_zero(t2s_1(1,1) - (t4ddg_2(1,1,0,0)*t2_3(0,0)
+			      + t4ddg_2(1,1,0,1)*t2_3(0,1)
+			      + t4ddg_2(1,1,0,2)*t2_3(0,2)
+			      + t4ddg_2(1,1,1,0)*t2_3(1,0)
+			      + t4ddg_2(1,1,1,1)*t2_3(1,1)
+			      + t4ddg_2(1,1,1,2)*t2_3(1,2)
+			      + t4ddg_2(1,1,2,0)*t2_3(2,0)
+			      + t4ddg_2(1,1,2,1)*t2_3(2,1)
+			      + t4ddg_2(1,1,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(1,1)");
+  test_for_zero(t2s_1(1,2) - (t4ddg_2(1,2,0,0)*t2_3(0,0)
+			      + t4ddg_2(1,2,0,1)*t2_3(0,1)
+			      + t4ddg_2(1,2,0,2)*t2_3(0,2)
+			      + t4ddg_2(1,2,1,0)*t2_3(1,0)
+			      + t4ddg_2(1,2,1,1)*t2_3(1,1)
+			      + t4ddg_2(1,2,1,2)*t2_3(1,2)
+			      + t4ddg_2(1,2,2,0)*t2_3(2,0)
+			      + t4ddg_2(1,2,2,1)*t2_3(2,1)
+			      + t4ddg_2(1,2,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(1,2)");
+  test_for_zero(t2s_1(2,0) - (t4ddg_2(2,0,0,0)*t2_3(0,0)
+			      + t4ddg_2(2,0,0,1)*t2_3(0,1)
+			      + t4ddg_2(2,0,0,2)*t2_3(0,2)
+			      + t4ddg_2(2,0,1,0)*t2_3(1,0)
+			      + t4ddg_2(2,0,1,1)*t2_3(1,1)
+			      + t4ddg_2(2,0,1,2)*t2_3(1,2)
+			      + t4ddg_2(2,0,2,0)*t2_3(2,0)
+			      + t4ddg_2(2,0,2,1)*t2_3(2,1)
+			      + t4ddg_2(2,0,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(2,0)");
+  test_for_zero(t2s_1(2,1) - (t4ddg_2(2,1,0,0)*t2_3(0,0)
+			      + t4ddg_2(2,1,0,1)*t2_3(0,1)
+			      + t4ddg_2(2,1,0,2)*t2_3(0,2)
+			      + t4ddg_2(2,1,1,0)*t2_3(1,0)
+			      + t4ddg_2(2,1,1,1)*t2_3(1,1)
+			      + t4ddg_2(2,1,1,2)*t2_3(1,2)
+			      + t4ddg_2(2,1,2,0)*t2_3(2,0)
+			      + t4ddg_2(2,1,2,1)*t2_3(2,1)
+			      + t4ddg_2(2,1,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(2,1)");
+  test_for_zero(t2s_1(2,2) - (t4ddg_2(2,2,0,0)*t2_3(0,0)
+			      + t4ddg_2(2,2,0,1)*t2_3(0,1)
+			      + t4ddg_2(2,2,0,2)*t2_3(0,2)
+			      + t4ddg_2(2,2,1,0)*t2_3(1,0)
+			      + t4ddg_2(2,2,1,1)*t2_3(1,1)
+			      + t4ddg_2(2,2,1,2)*t2_3(1,2)
+			      + t4ddg_2(2,2,2,0)*t2_3(2,0)
+			      + t4ddg_2(2,2,2,1)*t2_3(2,1)
+			      + t4ddg_2(2,2,2,2)*t2_3(2,2))
+		,"T2(l,j)*T4ddg(i,j,k,l)(2,2)");
+
+  t3dg_1(i,j,k)=t4ddg_2(i,j,l,k)*t1_2(l);
+  test_for_zero(t3dg_1(0,0,0) - (t4ddg_2(0,0,0,0)*t1_2(0)
+				 + t4ddg_2(0,0,1,0)*t1_2(1)
+				 + t4ddg_2(0,0,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,0,0)");
+  test_for_zero(t3dg_1(0,0,1) - (t4ddg_2(0,0,0,1)*t1_2(0)
+				 + t4ddg_2(0,0,1,1)*t1_2(1)
+				 + t4ddg_2(0,0,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,0,1)");
+  test_for_zero(t3dg_1(0,0,2) - (t4ddg_2(0,0,0,2)*t1_2(0)
+				 + t4ddg_2(0,0,1,2)*t1_2(1)
+				 + t4ddg_2(0,0,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,0,2)");
+  test_for_zero(t3dg_1(0,1,0) - (t4ddg_2(0,1,0,0)*t1_2(0)
+				 + t4ddg_2(0,1,1,0)*t1_2(1)
+				 + t4ddg_2(0,1,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,1,0)");
+  test_for_zero(t3dg_1(0,1,1) - (t4ddg_2(0,1,0,1)*t1_2(0)
+				 + t4ddg_2(0,1,1,1)*t1_2(1)
+				 + t4ddg_2(0,1,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,1,1)");
+  test_for_zero(t3dg_1(0,1,2) - (t4ddg_2(0,1,0,2)*t1_2(0)
+				 + t4ddg_2(0,1,1,2)*t1_2(1)
+				 + t4ddg_2(0,1,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,1,2)");
+  test_for_zero(t3dg_1(0,2,0) - (t4ddg_2(0,2,0,0)*t1_2(0)
+				 + t4ddg_2(0,2,1,0)*t1_2(1)
+				 + t4ddg_2(0,2,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,2,0)");
+  test_for_zero(t3dg_1(0,2,1) - (t4ddg_2(0,2,0,1)*t1_2(0)
+				 + t4ddg_2(0,2,1,1)*t1_2(1)
+				 + t4ddg_2(0,2,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,2,1)");
+  test_for_zero(t3dg_1(0,2,2) - (t4ddg_2(0,2,0,2)*t1_2(0)
+				 + t4ddg_2(0,2,1,2)*t1_2(1)
+				 + t4ddg_2(0,2,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(0,2,2)");
+  test_for_zero(t3dg_1(1,0,0) - (t4ddg_2(1,0,0,0)*t1_2(0)
+				 + t4ddg_2(1,0,1,0)*t1_2(1)
+				 + t4ddg_2(1,0,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,0,0)");
+  test_for_zero(t3dg_1(1,0,1) - (t4ddg_2(1,0,0,1)*t1_2(0)
+				 + t4ddg_2(1,0,1,1)*t1_2(1)
+				 + t4ddg_2(1,0,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,0,1)");
+  test_for_zero(t3dg_1(1,0,2) - (t4ddg_2(1,0,0,2)*t1_2(0)
+				 + t4ddg_2(1,0,1,2)*t1_2(1)
+				 + t4ddg_2(1,0,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,0,2)");
+  test_for_zero(t3dg_1(1,1,0) - (t4ddg_2(1,1,0,0)*t1_2(0)
+				 + t4ddg_2(1,1,1,0)*t1_2(1)
+				 + t4ddg_2(1,1,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - (t4ddg_2(1,1,0,1)*t1_2(0)
+				 + t4ddg_2(1,1,1,1)*t1_2(1)
+				 + t4ddg_2(1,1,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,1,1)");
+  test_for_zero(t3dg_1(1,1,2) - (t4ddg_2(1,1,0,2)*t1_2(0)
+				 + t4ddg_2(1,1,1,2)*t1_2(1)
+				 + t4ddg_2(1,1,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,1,2)");
+  test_for_zero(t3dg_1(1,2,0) - (t4ddg_2(1,2,0,0)*t1_2(0)
+				 + t4ddg_2(1,2,1,0)*t1_2(1)
+				 + t4ddg_2(1,2,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,2,0)");
+  test_for_zero(t3dg_1(1,2,1) - (t4ddg_2(1,2,0,1)*t1_2(0)
+				 + t4ddg_2(1,2,1,1)*t1_2(1)
+				 + t4ddg_2(1,2,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,2,1)");
+  test_for_zero(t3dg_1(1,2,2) - (t4ddg_2(1,2,0,2)*t1_2(0)
+				 + t4ddg_2(1,2,1,2)*t1_2(1)
+				 + t4ddg_2(1,2,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(1,2,2)");
+  test_for_zero(t3dg_1(2,0,0) - (t4ddg_2(2,0,0,0)*t1_2(0)
+				 + t4ddg_2(2,0,1,0)*t1_2(1)
+				 + t4ddg_2(2,0,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,0,0)");
+  test_for_zero(t3dg_1(2,0,1) - (t4ddg_2(2,0,0,1)*t1_2(0)
+				 + t4ddg_2(2,0,1,1)*t1_2(1)
+				 + t4ddg_2(2,0,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,0,1)");
+  test_for_zero(t3dg_1(2,0,2) - (t4ddg_2(2,0,0,2)*t1_2(0)
+				 + t4ddg_2(2,0,1,2)*t1_2(1)
+				 + t4ddg_2(2,0,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,0,2)");
+  test_for_zero(t3dg_1(2,1,0) - (t4ddg_2(2,1,0,0)*t1_2(0)
+				 + t4ddg_2(2,1,1,0)*t1_2(1)
+				 + t4ddg_2(2,1,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,1,0)");
+  test_for_zero(t3dg_1(2,1,1) - (t4ddg_2(2,1,0,1)*t1_2(0)
+				 + t4ddg_2(2,1,1,1)*t1_2(1)
+				 + t4ddg_2(2,1,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,1,1)");
+  test_for_zero(t3dg_1(2,1,2) - (t4ddg_2(2,1,0,2)*t1_2(0)
+				 + t4ddg_2(2,1,1,2)*t1_2(1)
+				 + t4ddg_2(2,1,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,1,2)");
+  test_for_zero(t3dg_1(2,2,0) - (t4ddg_2(2,2,0,0)*t1_2(0)
+				 + t4ddg_2(2,2,1,0)*t1_2(1)
+				 + t4ddg_2(2,2,2,0)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,2,0)");
+  test_for_zero(t3dg_1(2,2,1) - (t4ddg_2(2,2,0,1)*t1_2(0)
+				 + t4ddg_2(2,2,1,1)*t1_2(1)
+				 + t4ddg_2(2,2,2,1)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - (t4ddg_2(2,2,0,2)*t1_2(0)
+				 + t4ddg_2(2,2,1,2)*t1_2(1)
+				 + t4ddg_2(2,2,2,2)*t1_2(2))
+		,"T4ddg(i,j,l,k)*T1(l)(2,2,2)");
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/T4ddg/test_T4ddgV.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/T4ddg/test_T4ddgV.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,1808 @@
+#include <iostream>
+#include "../../../FTensor.h"
+#include "../test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T4ddgV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  Tensor4_ddg<double,3,3> t4ddg_1, t4ddg_2, t4ddg_3;
+
+  /* T4_ddg(1,1,i,j)=T2s(i,j) */
+
+  Tensor1<double,3> t1_3;
+  t1_3(i)=t1_1(j)*t2_1(i,j);
+
+  t4ddg_1(N0,N0,i,j)=(t1_1(i)^t1_1(j));
+  t4ddg_1(N0,N1,i,j)=t2s_1(i,j);
+  t4ddg_1(N0,N2,i,j)=(t1_3(i)^t1_3(j));
+  t4ddg_1(N1,N1,i,j)=t2s_2(i,j);
+  t4ddg_1(N1,N2,i,j)=(t1_2(i)^t1_2(j));
+  t4ddg_1(N2,N2,i,j)=t2s_3(i,j);
+
+  test_for_zero(t4ddg_1(0,0,0,0) - (t1_1(0)*t1_1(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t1_1(0)*t1_1(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t1_1(0)*t1_1(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t1_1(1)*t1_1(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t1_1(1)*t1_1(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t1_1(1)*t1_1(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t1_1(2)*t1_1(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t1_1(2)*t1_1(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t1_1(2)*t1_1(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t2s_1(0,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t2s_1(0,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t2s_1(0,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t2s_1(1,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t2s_1(1,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t2s_1(1,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t2s_1(2,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t2s_1(2,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t2s_1(2,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,1,2,2)");
+  test_for_zero((t4ddg_1(0,2,0,0) - (t1_3(0)*t1_3(0)))/t4ddg_1(0,2,0,0)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,0,0)");
+  test_for_zero((t4ddg_1(0,2,0,1) - (t1_3(0)*t1_3(1)))/t4ddg_1(0,2,0,1)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,0,1)");
+  test_for_zero((t4ddg_1(0,2,0,2) - (t1_3(0)*t1_3(2)))/t4ddg_1(0,2,0,2)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,0,2)");
+  test_for_zero((t4ddg_1(0,2,1,0) - (t1_3(1)*t1_3(0)))/t4ddg_1(0,2,1,0)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,1,0)");
+  test_for_zero((t4ddg_1(0,2,1,1) - (t1_3(1)*t1_3(1)))/t4ddg_1(0,2,1,1)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,1,1)");
+  test_for_zero((t4ddg_1(0,2,1,2) - (t1_3(1)*t1_3(2)))/t4ddg_1(0,2,1,2)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,1,2)");
+  test_for_zero((t4ddg_1(0,2,2,0) - (t1_3(2)*t1_3(0)))/t4ddg_1(0,2,2,0)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,2,0)");
+  test_for_zero((t4ddg_1(0,2,2,1) - (t1_3(2)*t1_3(1)))/t4ddg_1(0,2,2,1)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,2,1)");
+  test_for_zero((t4ddg_1(0,2,2,2) - (t1_3(2)*t1_3(2)))/t4ddg_1(0,2,2,2)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(0,2,2,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t2s_1(0,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t2s_1(0,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t2s_1(0,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t2s_1(1,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t2s_1(1,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t2s_1(1,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t2s_1(2,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t2s_1(2,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t2s_1(2,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t2s_2(0,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t2s_2(0,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t2s_2(0,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t2s_2(1,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t2s_2(1,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t2s_2(1,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t2s_2(2,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t2s_2(2,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t2s_2(2,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t1_2(0)*t1_2(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t1_2(0)*t1_2(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t1_2(0)*t1_2(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t1_2(1)*t1_2(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t1_2(1)*t1_2(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t1_2(1)*t1_2(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t1_2(2)*t1_2(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t1_2(2)*t1_2(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t1_2(2)*t1_2(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(1,2,2,2)");
+  test_for_zero((t4ddg_1(2,0,0,0) - (t1_3(0)*t1_3(0)))/t4ddg_1(2,0,0,0)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,0,0)");
+  test_for_zero((t4ddg_1(2,0,0,1) - (t1_3(0)*t1_3(1)))/t4ddg_1(2,0,0,1)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,0,1)");
+  test_for_zero((t4ddg_1(2,0,0,2) - (t1_3(0)*t1_3(2)))/t4ddg_1(2,0,0,2)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,0,2)");
+  test_for_zero((t4ddg_1(2,0,1,0) - (t1_3(1)*t1_3(0)))/t4ddg_1(2,0,1,0)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,1,0)");
+  test_for_zero((t4ddg_1(2,0,1,1) - (t1_3(1)*t1_3(1)))/t4ddg_1(2,0,1,1)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,1,1)");
+  test_for_zero((t4ddg_1(2,0,1,2) - (t1_3(1)*t1_3(2)))/t4ddg_1(2,0,1,2)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,1,2)");
+  test_for_zero((t4ddg_1(2,0,2,0) - (t1_3(2)*t1_3(0)))/t4ddg_1(2,0,2,0)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,2,0)");
+  test_for_zero((t4ddg_1(2,0,2,1) - (t1_3(2)*t1_3(1)))/t4ddg_1(2,0,2,1)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,2,1)");
+  test_for_zero((t4ddg_1(2,0,2,2) - (t1_3(2)*t1_3(2)))/t4ddg_1(2,0,2,2)
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t1_2(0)*t1_2(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t1_2(0)*t1_2(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t1_2(0)*t1_2(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t1_2(1)*t1_2(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t1_2(1)*t1_2(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t1_2(1)*t1_2(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t1_2(2)*t1_2(0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t1_2(2)*t1_2(1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t1_2(2)*t1_2(2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t2s_3(0,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t2s_3(0,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t2s_3(0,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t2s_3(1,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t2s_3(1,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t2s_3(1,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t2s_3(2,0))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t2s_3(2,1))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t2s_3(2,2))
+		,"T4ddg(N,N,i,j)=T2s(i,j)(2,2,2,2)");
+
+  t4ddg_2(i,j,k,l)=13*t4ddg_1(i,j,k,l);
+  test_for_zero(t4ddg_2(0,0,0,0) - 13*(t1_1(0)*t1_1(0))
+		,"T*T4ddg(0,0,0,0)");
+  test_for_zero(t4ddg_2(0,0,0,1) - 13*(t1_1(0)*t1_1(1))
+		,"T*T4ddg(0,0,0,1)");
+  test_for_zero(t4ddg_2(0,0,0,2) - 13*(t1_1(0)*t1_1(2))
+		,"T*T4ddg(0,0,0,2)");
+  test_for_zero(t4ddg_2(0,0,1,0) - 13*(t1_1(1)*t1_1(0))
+		,"T*T4ddg(0,0,1,0)");
+  test_for_zero(t4ddg_2(0,0,1,1) - 13*(t1_1(1)*t1_1(1))
+		,"T*T4ddg(0,0,1,1)");
+  test_for_zero(t4ddg_2(0,0,1,2) - 13*(t1_1(1)*t1_1(2))
+		,"T*T4ddg(0,0,1,2)");
+  test_for_zero(t4ddg_2(0,0,2,0) - 13*(t1_1(2)*t1_1(0))
+		,"T*T4ddg(0,0,2,0)");
+  test_for_zero(t4ddg_2(0,0,2,1) - 13*(t1_1(2)*t1_1(1))
+		,"T*T4ddg(0,0,2,1)");
+  test_for_zero(t4ddg_2(0,0,2,2) - 13*(t1_1(2)*t1_1(2))
+		,"T*T4ddg(0,0,2,2)");
+  test_for_zero(t4ddg_2(0,1,0,0) - 13*(t2s_1(0,0))
+		,"T*T4ddg(0,1,0,0)");
+  test_for_zero(t4ddg_2(0,1,0,1) - 13*(t2s_1(0,1))
+		,"T*T4ddg(0,1,0,1)");
+  test_for_zero(t4ddg_2(0,1,0,2) - 13*(t2s_1(0,2))
+		,"T*T4ddg(0,1,0,2)");
+  test_for_zero(t4ddg_2(0,1,1,0) - 13*(t2s_1(1,0))
+		,"T*T4ddg(0,1,1,0)");
+  test_for_zero(t4ddg_2(0,1,1,1) - 13*(t2s_1(1,1))
+		,"T*T4ddg(0,1,1,1)");
+  test_for_zero(t4ddg_2(0,1,1,2) - 13*(t2s_1(1,2))
+		,"T*T4ddg(0,1,1,2)");
+  test_for_zero(t4ddg_2(0,1,2,0) - 13*(t2s_1(2,0))
+		,"T*T4ddg(0,1,2,0)");
+  test_for_zero(t4ddg_2(0,1,2,1) - 13*(t2s_1(2,1))
+		,"T*T4ddg(0,1,2,1)");
+  test_for_zero(t4ddg_2(0,1,2,2) - 13*(t2s_1(2,2))
+		,"T*T4ddg(0,1,2,2)");
+  test_for_zero((t4ddg_2(0,2,0,0) - 13*(t1_3(0)*t1_3(0)))/t4ddg_2(0,2,0,0)
+		,"T*T4ddg(0,2,0,0)");
+  test_for_zero((t4ddg_2(0,2,0,1) - 13*(t1_3(0)*t1_3(1)))/t4ddg_2(0,2,0,1)
+		,"T*T4ddg(0,2,0,1)");
+  test_for_zero((t4ddg_2(0,2,0,2) - 13*(t1_3(0)*t1_3(2)))/t4ddg_2(0,2,0,2)
+		,"T*T4ddg(0,2,0,2)");
+  test_for_zero((t4ddg_2(0,2,1,0) - 13*(t1_3(1)*t1_3(0)))/t4ddg_2(0,2,1,0)
+		,"T*T4ddg(0,2,1,0)");
+  test_for_zero((t4ddg_2(0,2,1,1) - 13*(t1_3(1)*t1_3(1)))/t4ddg_2(0,2,1,1)
+		,"T*T4ddg(0,2,1,1)");
+  test_for_zero((t4ddg_2(0,2,1,2) - 13*(t1_3(1)*t1_3(2)))/t4ddg_2(0,2,1,2)
+		,"T*T4ddg(0,2,1,2)");
+  test_for_zero((t4ddg_2(0,2,2,0) - 13*(t1_3(2)*t1_3(0)))/t4ddg_2(0,2,2,0)
+		,"T*T4ddg(0,2,2,0)");
+  test_for_zero((t4ddg_2(0,2,2,1) - 13*(t1_3(2)*t1_3(1)))/t4ddg_2(0,2,2,1)
+		,"T*T4ddg(0,2,2,1)");
+  test_for_zero((t4ddg_2(0,2,2,2) - 13*(t1_3(2)*t1_3(2)))/t4ddg_2(0,2,2,2)
+		,"T*T4ddg(0,2,2,2)");
+  test_for_zero(t4ddg_2(1,0,0,0) - 13*(t2s_1(0,0))
+		,"T*T4ddg(1,0,0,0)");
+  test_for_zero(t4ddg_2(1,0,0,1) - 13*(t2s_1(0,1))
+		,"T*T4ddg(1,0,0,1)");
+  test_for_zero(t4ddg_2(1,0,0,2) - 13*(t2s_1(0,2))
+		,"T*T4ddg(1,0,0,2)");
+  test_for_zero(t4ddg_2(1,0,1,0) - 13*(t2s_1(1,0))
+		,"T*T4ddg(1,0,1,0)");
+  test_for_zero(t4ddg_2(1,0,1,1) - 13*(t2s_1(1,1))
+		,"T*T4ddg(1,0,1,1)");
+  test_for_zero(t4ddg_2(1,0,1,2) - 13*(t2s_1(1,2))
+		,"T*T4ddg(1,0,1,2)");
+  test_for_zero(t4ddg_2(1,0,2,0) - 13*(t2s_1(2,0))
+		,"T*T4ddg(1,0,2,0)");
+  test_for_zero(t4ddg_2(1,0,2,1) - 13*(t2s_1(2,1))
+		,"T*T4ddg(1,0,2,1)");
+  test_for_zero(t4ddg_2(1,0,2,2) - 13*(t2s_1(2,2))
+		,"T*T4ddg(1,0,2,2)");
+  test_for_zero(t4ddg_2(1,1,0,0) - 13*(t2s_2(0,0))
+		,"T*T4ddg(1,1,0,0)");
+  test_for_zero(t4ddg_2(1,1,0,1) - 13*(t2s_2(0,1))
+		,"T*T4ddg(1,1,0,1)");
+  test_for_zero(t4ddg_2(1,1,0,2) - 13*(t2s_2(0,2))
+		,"T*T4ddg(1,1,0,2)");
+  test_for_zero(t4ddg_2(1,1,1,0) - 13*(t2s_2(1,0))
+		,"T*T4ddg(1,1,1,0)");
+  test_for_zero(t4ddg_2(1,1,1,1) - 13*(t2s_2(1,1))
+		,"T*T4ddg(1,1,1,1)");
+  test_for_zero(t4ddg_2(1,1,1,2) - 13*(t2s_2(1,2))
+		,"T*T4ddg(1,1,1,2)");
+  test_for_zero(t4ddg_2(1,1,2,0) - 13*(t2s_2(2,0))
+		,"T*T4ddg(1,1,2,0)");
+  test_for_zero(t4ddg_2(1,1,2,1) - 13*(t2s_2(2,1))
+		,"T*T4ddg(1,1,2,1)");
+  test_for_zero(t4ddg_2(1,1,2,2) - 13*(t2s_2(2,2))
+		,"T*T4ddg(1,1,2,2)");
+  test_for_zero(t4ddg_2(1,2,0,0) - 13*(t1_2(0)*t1_2(0))
+		,"T*T4ddg(1,2,0,0)");
+  test_for_zero(t4ddg_2(1,2,0,1) - 13*(t1_2(0)*t1_2(1))
+		,"T*T4ddg(1,2,0,1)");
+  test_for_zero(t4ddg_2(1,2,0,2) - 13*(t1_2(0)*t1_2(2))
+		,"T*T4ddg(1,2,0,2)");
+  test_for_zero(t4ddg_2(1,2,1,0) - 13*(t1_2(1)*t1_2(0))
+		,"T*T4ddg(1,2,1,0)");
+  test_for_zero(t4ddg_2(1,2,1,1) - 13*(t1_2(1)*t1_2(1))
+		,"T*T4ddg(1,2,1,1)");
+  test_for_zero(t4ddg_2(1,2,1,2) - 13*(t1_2(1)*t1_2(2))
+		,"T*T4ddg(1,2,1,2)");
+  test_for_zero(t4ddg_2(1,2,2,0) - 13*(t1_2(2)*t1_2(0))
+		,"T*T4ddg(1,2,2,0)");
+  test_for_zero(t4ddg_2(1,2,2,1) - 13*(t1_2(2)*t1_2(1))
+		,"T*T4ddg(1,2,2,1)");
+  test_for_zero(t4ddg_2(1,2,2,2) - 13*(t1_2(2)*t1_2(2))
+		,"T*T4ddg(1,2,2,2)");
+  test_for_zero((t4ddg_2(2,0,0,0) - 13*(t1_3(0)*t1_3(0)))/t4ddg_2(2,0,0,0)
+		,"T*T4ddg(2,0,0,0)");
+  test_for_zero((t4ddg_2(2,0,0,1) - 13*(t1_3(0)*t1_3(1)))/t4ddg_2(2,0,0,1)
+		,"T*T4ddg(2,0,0,1)");
+  test_for_zero((t4ddg_2(2,0,0,2) - 13*(t1_3(0)*t1_3(2)))/t4ddg_2(2,0,0,2)
+		,"T*T4ddg(2,0,0,2)");
+  test_for_zero((t4ddg_2(2,0,1,0) - 13*(t1_3(1)*t1_3(0)))/t4ddg_2(2,0,1,0)
+		,"T*T4ddg(2,0,1,0)");
+  test_for_zero((t4ddg_2(2,0,1,1) - 13*(t1_3(1)*t1_3(1)))/t4ddg_2(2,0,1,1)
+		,"T*T4ddg(2,0,1,1)");
+  test_for_zero((t4ddg_2(2,0,1,2) - 13*(t1_3(1)*t1_3(2)))/t4ddg_2(2,0,1,2)
+		,"T*T4ddg(2,0,1,2)");
+  test_for_zero((t4ddg_2(2,0,2,0) - 13*(t1_3(2)*t1_3(0)))/t4ddg_2(2,0,2,0)
+		,"T*T4ddg(2,0,2,0)");
+  test_for_zero((t4ddg_2(2,0,2,1) - 13*(t1_3(2)*t1_3(1)))/t4ddg_2(2,0,2,1)
+		,"T*T4ddg(2,0,2,1)");
+  test_for_zero((t4ddg_2(2,0,2,2) - 13*(t1_3(2)*t1_3(2)))/t4ddg_2(2,0,2,2)
+		,"T*T4ddg(2,0,2,2)");
+  test_for_zero(t4ddg_2(2,1,0,0) - 13*(t1_2(0)*t1_2(0))
+		,"T*T4ddg(2,1,0,0)");
+  test_for_zero(t4ddg_2(2,1,0,1) - 13*(t1_2(0)*t1_2(1))
+		,"T*T4ddg(2,1,0,1)");
+  test_for_zero(t4ddg_2(2,1,0,2) - 13*(t1_2(0)*t1_2(2))
+		,"T*T4ddg(2,1,0,2)");
+  test_for_zero(t4ddg_2(2,1,1,0) - 13*(t1_2(1)*t1_2(0))
+		,"T*T4ddg(2,1,1,0)");
+  test_for_zero(t4ddg_2(2,1,1,1) - 13*(t1_2(1)*t1_2(1))
+		,"T*T4ddg(2,1,1,1)");
+  test_for_zero(t4ddg_2(2,1,1,2) - 13*(t1_2(1)*t1_2(2))
+		,"T*T4ddg(2,1,1,2)");
+  test_for_zero(t4ddg_2(2,1,2,0) - 13*(t1_2(2)*t1_2(0))
+		,"T*T4ddg(2,1,2,0)");
+  test_for_zero(t4ddg_2(2,1,2,1) - 13*(t1_2(2)*t1_2(1))
+		,"T*T4ddg(2,1,2,1)");
+  test_for_zero(t4ddg_2(2,1,2,2) - 13*(t1_2(2)*t1_2(2))
+		,"T*T4ddg(2,1,2,2)");
+  test_for_zero(t4ddg_2(2,2,0,0) - 13*(t2s_3(0,0))
+		,"T*T4ddg(2,2,0,0)");
+  test_for_zero(t4ddg_2(2,2,0,1) - 13*(t2s_3(0,1))
+		,"T*T4ddg(2,2,0,1)");
+  test_for_zero(t4ddg_2(2,2,0,2) - 13*(t2s_3(0,2))
+		,"T*T4ddg(2,2,0,2)");
+  test_for_zero(t4ddg_2(2,2,1,0) - 13*(t2s_3(1,0))
+		,"T*T4ddg(2,2,1,0)");
+  test_for_zero(t4ddg_2(2,2,1,1) - 13*(t2s_3(1,1))
+		,"T*T4ddg(2,2,1,1)");
+  test_for_zero(t4ddg_2(2,2,1,2) - 13*(t2s_3(1,2))
+		,"T*T4ddg(2,2,1,2)");
+  test_for_zero(t4ddg_2(2,2,2,0) - 13*(t2s_3(2,0))
+		,"T*T4ddg(2,2,2,0)");
+  test_for_zero(t4ddg_2(2,2,2,1) - 13*(t2s_3(2,1))
+		,"T*T4ddg(2,2,2,1)");
+  test_for_zero(t4ddg_2(2,2,2,2) - 13*(t2s_3(2,2))
+		,"T*T4ddg(2,2,2,2)");
+
+
+  t4ddg_2(i,j,k,l)=t4ddg_1(i,j,k,l)*7;
+  test_for_zero(t4ddg_2(0,0,0,0) - 7*(t1_1(0)*t1_1(0))
+		,"T4ddg*T(0,0,0,0)");
+  test_for_zero(t4ddg_2(0,0,0,1) - 7*(t1_1(0)*t1_1(1))
+		,"T4ddg*T(0,0,0,1)");
+  test_for_zero(t4ddg_2(0,0,0,2) - 7*(t1_1(0)*t1_1(2))
+		,"T4ddg*T(0,0,0,2)");
+  test_for_zero(t4ddg_2(0,0,1,0) - 7*(t1_1(1)*t1_1(0))
+		,"T4ddg*T(0,0,1,0)");
+  test_for_zero(t4ddg_2(0,0,1,1) - 7*(t1_1(1)*t1_1(1))
+		,"T4ddg*T(0,0,1,1)");
+  test_for_zero(t4ddg_2(0,0,1,2) - 7*(t1_1(1)*t1_1(2))
+		,"T4ddg*T(0,0,1,2)");
+  test_for_zero(t4ddg_2(0,0,2,0) - 7*(t1_1(2)*t1_1(0))
+		,"T4ddg*T(0,0,2,0)");
+  test_for_zero(t4ddg_2(0,0,2,1) - 7*(t1_1(2)*t1_1(1))
+		,"T4ddg*T(0,0,2,1)");
+  test_for_zero(t4ddg_2(0,0,2,2) - 7*(t1_1(2)*t1_1(2))
+		,"T4ddg*T(0,0,2,2)");
+  test_for_zero(t4ddg_2(0,1,0,0) - 7*(t2s_1(0,0))
+		,"T4ddg*T(0,1,0,0)");
+  test_for_zero(t4ddg_2(0,1,0,1) - 7*(t2s_1(0,1))
+		,"T4ddg*T(0,1,0,1)");
+  test_for_zero(t4ddg_2(0,1,0,2) - 7*(t2s_1(0,2))
+		,"T4ddg*T(0,1,0,2)");
+  test_for_zero(t4ddg_2(0,1,1,0) - 7*(t2s_1(1,0))
+		,"T4ddg*T(0,1,1,0)");
+  test_for_zero(t4ddg_2(0,1,1,1) - 7*(t2s_1(1,1))
+		,"T4ddg*T(0,1,1,1)");
+  test_for_zero(t4ddg_2(0,1,1,2) - 7*(t2s_1(1,2))
+		,"T4ddg*T(0,1,1,2)");
+  test_for_zero(t4ddg_2(0,1,2,0) - 7*(t2s_1(2,0))
+		,"T4ddg*T(0,1,2,0)");
+  test_for_zero(t4ddg_2(0,1,2,1) - 7*(t2s_1(2,1))
+		,"T4ddg*T(0,1,2,1)");
+  test_for_zero(t4ddg_2(0,1,2,2) - 7*(t2s_1(2,2))
+		,"T4ddg*T(0,1,2,2)");
+  test_for_zero((t4ddg_2(0,2,0,0) - 7*(t1_3(0)*t1_3(0)))/t4ddg_2(0,2,0,0)
+		,"T4ddg*T(0,2,0,0)");
+  test_for_zero((t4ddg_2(0,2,0,1) - 7*(t1_3(0)*t1_3(1)))/t4ddg_2(0,2,0,1)
+		,"T4ddg*T(0,2,0,1)");
+  test_for_zero((t4ddg_2(0,2,0,2) - 7*(t1_3(0)*t1_3(2)))/t4ddg_2(0,2,0,2)
+		,"T4ddg*T(0,2,0,2)");
+  test_for_zero((t4ddg_2(0,2,1,0) - 7*(t1_3(1)*t1_3(0)))/t4ddg_2(0,2,1,0)
+		,"T4ddg*T(0,2,1,0)");
+  test_for_zero((t4ddg_2(0,2,1,1) - 7*(t1_3(1)*t1_3(1)))/t4ddg_2(0,2,1,1)
+		,"T4ddg*T(0,2,1,1)");
+  test_for_zero((t4ddg_2(0,2,1,2) - 7*(t1_3(1)*t1_3(2)))/t4ddg_2(0,2,1,2)
+		,"T4ddg*T(0,2,1,2)");
+  test_for_zero((t4ddg_2(0,2,2,0) - 7*(t1_3(2)*t1_3(0)))/t4ddg_2(0,2,2,0)
+		,"T4ddg*T(0,2,2,0)");
+  test_for_zero((t4ddg_2(0,2,2,1) - 7*(t1_3(2)*t1_3(1)))/t4ddg_2(0,2,2,1)
+		,"T4ddg*T(0,2,2,1)");
+  test_for_zero((t4ddg_2(0,2,2,2) - 7*(t1_3(2)*t1_3(2)))/t4ddg_2(0,2,2,2)
+		,"T4ddg*T(0,2,2,2)");
+  test_for_zero(t4ddg_2(1,0,0,0) - 7*(t2s_1(0,0))
+		,"T4ddg*T(1,0,0,0)");
+  test_for_zero(t4ddg_2(1,0,0,1) - 7*(t2s_1(0,1))
+		,"T4ddg*T(1,0,0,1)");
+  test_for_zero(t4ddg_2(1,0,0,2) - 7*(t2s_1(0,2))
+		,"T4ddg*T(1,0,0,2)");
+  test_for_zero(t4ddg_2(1,0,1,0) - 7*(t2s_1(1,0))
+		,"T4ddg*T(1,0,1,0)");
+  test_for_zero(t4ddg_2(1,0,1,1) - 7*(t2s_1(1,1))
+		,"T4ddg*T(1,0,1,1)");
+  test_for_zero(t4ddg_2(1,0,1,2) - 7*(t2s_1(1,2))
+		,"T4ddg*T(1,0,1,2)");
+  test_for_zero(t4ddg_2(1,0,2,0) - 7*(t2s_1(2,0))
+		,"T4ddg*T(1,0,2,0)");
+  test_for_zero(t4ddg_2(1,0,2,1) - 7*(t2s_1(2,1))
+		,"T4ddg*T(1,0,2,1)");
+  test_for_zero(t4ddg_2(1,0,2,2) - 7*(t2s_1(2,2))
+		,"T4ddg*T(1,0,2,2)");
+  test_for_zero(t4ddg_2(1,1,0,0) - 7*(t2s_2(0,0))
+		,"T4ddg*T(1,1,0,0)");
+  test_for_zero(t4ddg_2(1,1,0,1) - 7*(t2s_2(0,1))
+		,"T4ddg*T(1,1,0,1)");
+  test_for_zero(t4ddg_2(1,1,0,2) - 7*(t2s_2(0,2))
+		,"T4ddg*T(1,1,0,2)");
+  test_for_zero(t4ddg_2(1,1,1,0) - 7*(t2s_2(1,0))
+		,"T4ddg*T(1,1,1,0)");
+  test_for_zero(t4ddg_2(1,1,1,1) - 7*(t2s_2(1,1))
+		,"T4ddg*T(1,1,1,1)");
+  test_for_zero(t4ddg_2(1,1,1,2) - 7*(t2s_2(1,2))
+		,"T4ddg*T(1,1,1,2)");
+  test_for_zero(t4ddg_2(1,1,2,0) - 7*(t2s_2(2,0))
+		,"T4ddg*T(1,1,2,0)");
+  test_for_zero(t4ddg_2(1,1,2,1) - 7*(t2s_2(2,1))
+		,"T4ddg*T(1,1,2,1)");
+  test_for_zero(t4ddg_2(1,1,2,2) - 7*(t2s_2(2,2))
+		,"T4ddg*T(1,1,2,2)");
+  test_for_zero(t4ddg_2(1,2,0,0) - 7*(t1_2(0)*t1_2(0))
+		,"T4ddg*T(1,2,0,0)");
+  test_for_zero(t4ddg_2(1,2,0,1) - 7*(t1_2(0)*t1_2(1))
+		,"T4ddg*T(1,2,0,1)");
+  test_for_zero(t4ddg_2(1,2,0,2) - 7*(t1_2(0)*t1_2(2))
+		,"T4ddg*T(1,2,0,2)");
+  test_for_zero(t4ddg_2(1,2,1,0) - 7*(t1_2(1)*t1_2(0))
+		,"T4ddg*T(1,2,1,0)");
+  test_for_zero(t4ddg_2(1,2,1,1) - 7*(t1_2(1)*t1_2(1))
+		,"T4ddg*T(1,2,1,1)");
+  test_for_zero(t4ddg_2(1,2,1,2) - 7*(t1_2(1)*t1_2(2))
+		,"T4ddg*T(1,2,1,2)");
+  test_for_zero(t4ddg_2(1,2,2,0) - 7*(t1_2(2)*t1_2(0))
+		,"T4ddg*T(1,2,2,0)");
+  test_for_zero(t4ddg_2(1,2,2,1) - 7*(t1_2(2)*t1_2(1))
+		,"T4ddg*T(1,2,2,1)");
+  test_for_zero(t4ddg_2(1,2,2,2) - 7*(t1_2(2)*t1_2(2))
+		,"T4ddg*T(1,2,2,2)");
+  test_for_zero((t4ddg_2(2,0,0,0) - 7*(t1_3(0)*t1_3(0)))/t4ddg_2(2,0,0,0)
+		,"T4ddg*T(2,0,0,0)");
+  test_for_zero((t4ddg_2(2,0,0,1) - 7*(t1_3(0)*t1_3(1)))/t4ddg_2(2,0,0,1)
+		,"T4ddg*T(2,0,0,1)");
+  test_for_zero((t4ddg_2(2,0,0,2) - 7*(t1_3(0)*t1_3(2)))/t4ddg_2(2,0,0,2)
+		,"T4ddg*T(2,0,0,2)");
+  test_for_zero((t4ddg_2(2,0,1,0) - 7*(t1_3(1)*t1_3(0)))/t4ddg_2(2,0,1,0)
+		,"T4ddg*T(2,0,1,0)");
+  test_for_zero((t4ddg_2(2,0,1,1) - 7*(t1_3(1)*t1_3(1)))/t4ddg_2(2,0,1,1)
+		,"T4ddg*T(2,0,1,1)");
+  test_for_zero((t4ddg_2(2,0,1,2) - 7*(t1_3(1)*t1_3(2)))/t4ddg_2(2,0,1,2)
+		,"T4ddg*T(2,0,1,2)");
+  test_for_zero((t4ddg_2(2,0,2,0) - 7*(t1_3(2)*t1_3(0)))/t4ddg_2(2,0,2,0)
+		,"T4ddg*T(2,0,2,0)");
+  test_for_zero((t4ddg_2(2,0,2,1) - 7*(t1_3(2)*t1_3(1)))/t4ddg_2(2,0,2,1)
+		,"T4ddg*T(2,0,2,1)");
+  test_for_zero((t4ddg_2(2,0,2,2) - 7*(t1_3(2)*t1_3(2)))/t4ddg_2(2,0,2,2)
+		,"T4ddg*T(2,0,2,2)");
+  test_for_zero(t4ddg_2(2,1,0,0) - 7*(t1_2(0)*t1_2(0))
+		,"T4ddg*T(2,1,0,0)");
+  test_for_zero(t4ddg_2(2,1,0,1) - 7*(t1_2(0)*t1_2(1))
+		,"T4ddg*T(2,1,0,1)");
+  test_for_zero(t4ddg_2(2,1,0,2) - 7*(t1_2(0)*t1_2(2))
+		,"T4ddg*T(2,1,0,2)");
+  test_for_zero(t4ddg_2(2,1,1,0) - 7*(t1_2(1)*t1_2(0))
+		,"T4ddg*T(2,1,1,0)");
+  test_for_zero(t4ddg_2(2,1,1,1) - 7*(t1_2(1)*t1_2(1))
+		,"T4ddg*T(2,1,1,1)");
+  test_for_zero(t4ddg_2(2,1,1,2) - 7*(t1_2(1)*t1_2(2))
+		,"T4ddg*T(2,1,1,2)");
+  test_for_zero(t4ddg_2(2,1,2,0) - 7*(t1_2(2)*t1_2(0))
+		,"T4ddg*T(2,1,2,0)");
+  test_for_zero(t4ddg_2(2,1,2,1) - 7*(t1_2(2)*t1_2(1))
+		,"T4ddg*T(2,1,2,1)");
+  test_for_zero(t4ddg_2(2,1,2,2) - 7*(t1_2(2)*t1_2(2))
+		,"T4ddg*T(2,1,2,2)");
+  test_for_zero(t4ddg_2(2,2,0,0) - 7*(t2s_3(0,0))
+		,"T4ddg*T(2,2,0,0)");
+  test_for_zero(t4ddg_2(2,2,0,1) - 7*(t2s_3(0,1))
+		,"T4ddg*T(2,2,0,1)");
+  test_for_zero(t4ddg_2(2,2,0,2) - 7*(t2s_3(0,2))
+		,"T4ddg*T(2,2,0,2)");
+  test_for_zero(t4ddg_2(2,2,1,0) - 7*(t2s_3(1,0))
+		,"T4ddg*T(2,2,1,0)");
+  test_for_zero(t4ddg_2(2,2,1,1) - 7*(t2s_3(1,1))
+		,"T4ddg*T(2,2,1,1)");
+  test_for_zero(t4ddg_2(2,2,1,2) - 7*(t2s_3(1,2))
+		,"T4ddg*T(2,2,1,2)");
+  test_for_zero(t4ddg_2(2,2,2,0) - 7*(t2s_3(2,0))
+		,"T4ddg*T(2,2,2,0)");
+  test_for_zero(t4ddg_2(2,2,2,1) - 7*(t2s_3(2,1))
+		,"T4ddg*T(2,2,2,1)");
+  test_for_zero(t4ddg_2(2,2,2,2) - 7*(t2s_3(2,2))
+		,"T4ddg*T(2,2,2,2)");
+
+  t4ddg_1(N0,i,j,k)=t3dg_1(j,k,i);
+
+  test_for_zero(t4ddg_1(0,0,0,0) - (t3dg_1(0,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t3dg_1(0,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t3dg_1(0,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t3dg_1(1,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t3dg_1(1,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t3dg_1(1,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t3dg_1(2,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t3dg_1(2,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t3dg_1(2,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,0,2,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t3dg_1(0,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t3dg_1(0,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t3dg_1(0,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t3dg_1(1,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t3dg_1(1,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t3dg_1(1,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t3dg_1(2,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t3dg_1(2,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t3dg_1(2,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,1,2,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t3dg_1(0,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t3dg_1(0,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t3dg_1(0,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t3dg_1(1,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t3dg_1(1,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t3dg_1(1,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t3dg_1(2,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t3dg_1(2,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t3dg_1(2,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(0,2,2,2)");
+
+  t4ddg_1(N1,i,j,k)=t3dg_2(j,k,i);
+
+  test_for_zero(t4ddg_1(1,0,0,0) - (t3dg_2(0,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t3dg_2(0,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t3dg_2(0,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t3dg_2(1,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t3dg_2(1,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t3dg_2(1,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t3dg_2(2,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t3dg_2(2,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t3dg_2(2,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,0,2,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t3dg_2(0,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t3dg_2(0,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t3dg_2(0,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t3dg_2(1,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t3dg_2(1,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t3dg_2(1,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t3dg_2(2,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t3dg_2(2,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t3dg_2(2,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,1,2,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t3dg_2(0,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t3dg_2(0,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t3dg_2(0,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t3dg_2(1,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t3dg_2(1,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t3dg_2(1,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t3dg_2(2,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t3dg_2(2,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t3dg_2(2,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(1,2,2,2)");
+
+  t4ddg_1(N2,i,j,k)=t3dg_3(j,k,i);
+
+  test_for_zero(t4ddg_1(2,0,0,0) - (t3dg_3(0,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t3dg_3(0,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t3dg_3(0,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t3dg_3(1,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t3dg_3(1,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t3dg_3(1,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t3dg_3(2,0,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t3dg_3(2,1,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t3dg_3(2,2,0))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,0,2,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t3dg_3(0,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t3dg_3(0,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t3dg_3(0,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t3dg_3(1,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t3dg_3(1,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t3dg_3(1,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t3dg_3(2,0,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t3dg_3(2,1,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t3dg_3(2,2,1))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,1,2,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t3dg_3(0,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t3dg_3(0,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t3dg_3(0,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t3dg_3(1,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t3dg_3(1,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t3dg_3(1,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t3dg_3(2,0,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t3dg_3(2,1,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t3dg_3(2,2,2))
+		,"T4ddg(N,i,j,k)=T3dg(j,k,i)(2,2,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(0,0,i,j);
+  test_for_zero(t4ddg_1(0,0,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,0,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,0,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(0,0,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(0,1,i,j);
+  test_for_zero(t4ddg_1(0,1,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(0,1,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(0,2,i,j);
+  test_for_zero(t4ddg_1(0,2,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(0,2,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(1,0,i,j);
+  test_for_zero(t4ddg_1(1,0,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(1,0,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(1,1,i,j);
+  test_for_zero(t4ddg_1(1,1,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(1,1,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(1,2,i,j);
+  test_for_zero(t4ddg_1(1,2,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(1,2,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(2,0,i,j);
+  test_for_zero(t4ddg_1(2,0,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(2,0,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(2,1,i,j);
+  test_for_zero(t4ddg_1(2,1,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(2,1,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(2,2,i,j);
+  test_for_zero(t4ddg_1(2,2,0,0) - (t2s_1(0,0))
+		,"T4ddg(Num,Num,i,j)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t2s_1(0,1))
+		,"T4ddg(Num,Num,i,j)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t2s_1(0,2))
+		,"T4ddg(Num,Num,i,j)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t2s_1(1,0))
+		,"T4ddg(Num,Num,i,j)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t2s_1(1,1))
+		,"T4ddg(Num,Num,i,j)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t2s_1(1,2))
+		,"T4ddg(Num,Num,i,j)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t2s_1(2,0))
+		,"T4ddg(Num,Num,i,j)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t2s_1(2,1))
+		,"T4ddg(Num,Num,i,j)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t2s_1(2,2))
+		,"T4ddg(Num,Num,i,j)(2,2,2,2)");
+
+
+
+
+
+  t2s_1(i,j)=t4ddg_1(i,j,0,0);
+  test_for_zero(t4ddg_1(0,0,0,0) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(0,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,0,0) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(0,0,1,0)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(0,0,1,1)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(0,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,0,0) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(0,0,2,0)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(0,0,2,1)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(0,0,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,0,1);
+  test_for_zero(t4ddg_1(0,0,0,1) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(0,1,0,2)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(0,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(0,1,1,1)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(0,1,1,2)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(0,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(0,1,2,1)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(0,1,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,0,2);
+  test_for_zero(t4ddg_1(0,0,0,2) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(0,2,0,2)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(0,2,1,0)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(0,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(0,2,1,2)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(0,2,2,0)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(0,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(0,2,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,1,0);
+  test_for_zero(t4ddg_1(0,0,1,0) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(1,0,0,0)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(1,0,0,1)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,0) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(1,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,1,0) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(1,0,2,0)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(1,0,2,1)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(1,0,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,1,1);
+  test_for_zero(t4ddg_1(0,0,1,1) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(1,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(1,1,0,1)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(1,1,1,2)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(1,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(1,1,2,1)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(1,1,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,1,2);
+  test_for_zero(t4ddg_1(0,0,1,2) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(1,2,0,0)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(1,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(1,2,1,2)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(1,2,2,0)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(1,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(1,2,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,2,0);
+  test_for_zero(t4ddg_1(0,0,2,0) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(2,0,0,0)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(2,0,0,1)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(2,0,0,2)");
+  test_for_zero(t4ddg_1(1,0,2,0) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(2,0,1,0)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(2,0,1,1)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,0) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(2,0,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,2,1);
+  test_for_zero(t4ddg_1(0,0,2,1) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(2,1,0,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(2,1,0,1)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(2,1,0,2)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(2,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(2,1,1,1)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(2,1,2,2)");
+
+  t2s_1(i,j)=t4ddg_1(i,j,2,2);
+  test_for_zero(t4ddg_1(0,0,2,2) - (t2s_1(0,0))
+		,"T4ddg(i,j,Num,Num)(2,2,0,0)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t2s_1(0,1))
+		,"T4ddg(i,j,Num,Num)(2,2,0,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t2s_1(0,2))
+		,"T4ddg(i,j,Num,Num)(2,2,0,2)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t2s_1(1,0))
+		,"T4ddg(i,j,Num,Num)(2,2,1,0)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t2s_1(1,1))
+		,"T4ddg(i,j,Num,Num)(2,2,1,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t2s_1(1,2))
+		,"T4ddg(i,j,Num,Num)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t2s_1(2,0))
+		,"T4ddg(i,j,Num,Num)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t2s_1(2,1))
+		,"T4ddg(i,j,Num,Num)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t2s_1(2,2))
+		,"T4ddg(i,j,Num,Num)(2,2,2,2)");
+
+
+
+  t2_1(i,j)=t4ddg_1(0,i,0,j);
+  test_for_zero(t4ddg_1(0,0,0,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(0,0,0,0)");
+  test_for_zero(t4ddg_1(0,0,0,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(0,0,0,1)");
+  test_for_zero(t4ddg_1(0,0,0,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(0,0,0,2)");
+  test_for_zero(t4ddg_1(0,1,0,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(0,0,1,0)");
+  test_for_zero(t4ddg_1(0,1,0,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(0,0,1,1)");
+  test_for_zero(t4ddg_1(0,1,0,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(0,0,1,2)");
+  test_for_zero(t4ddg_1(0,2,0,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(0,0,2,0)");
+  test_for_zero(t4ddg_1(0,2,0,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(0,0,2,1)");
+  test_for_zero(t4ddg_1(0,2,0,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(0,0,2,2)");
+
+  t2_1(i,j)=t4ddg_1(0,i,1,j);
+  test_for_zero(t4ddg_1(0,0,1,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(0,1,0,0)");
+  test_for_zero(t4ddg_1(0,0,1,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(0,1,0,1)");
+  test_for_zero(t4ddg_1(0,0,1,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(0,1,0,2)");
+  test_for_zero(t4ddg_1(0,1,1,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(0,1,1,0)");
+  test_for_zero(t4ddg_1(0,1,1,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(0,1,1,1)");
+  test_for_zero(t4ddg_1(0,1,1,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(0,1,1,2)");
+  test_for_zero(t4ddg_1(0,2,1,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(0,1,2,0)");
+  test_for_zero(t4ddg_1(0,2,1,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(0,1,2,1)");
+  test_for_zero(t4ddg_1(0,2,1,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(0,1,2,2)");
+
+  t2_1(i,j)=t4ddg_1(0,i,2,j);
+  test_for_zero(t4ddg_1(0,0,2,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(0,2,0,0)");
+  test_for_zero(t4ddg_1(0,0,2,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(0,2,0,1)");
+  test_for_zero(t4ddg_1(0,0,2,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(0,2,0,2)");
+  test_for_zero(t4ddg_1(0,1,2,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(0,2,1,0)");
+  test_for_zero(t4ddg_1(0,1,2,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(0,2,1,1)");
+  test_for_zero(t4ddg_1(0,1,2,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(0,2,1,2)");
+  test_for_zero(t4ddg_1(0,2,2,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(0,2,2,0)");
+  test_for_zero(t4ddg_1(0,2,2,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(0,2,2,1)");
+  test_for_zero(t4ddg_1(0,2,2,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(0,2,2,2)");
+
+  t2_1(i,j)=t4ddg_1(1,i,0,j);
+  test_for_zero(t4ddg_1(1,0,0,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(1,0,0,0)");
+  test_for_zero(t4ddg_1(1,0,0,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(1,0,0,1)");
+  test_for_zero(t4ddg_1(1,0,0,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(1,0,0,2)");
+  test_for_zero(t4ddg_1(1,1,0,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(1,0,1,0)");
+  test_for_zero(t4ddg_1(1,1,0,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(1,0,1,1)");
+  test_for_zero(t4ddg_1(1,1,0,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(1,0,1,2)");
+  test_for_zero(t4ddg_1(1,2,0,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(1,0,2,0)");
+  test_for_zero(t4ddg_1(1,2,0,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(1,0,2,1)");
+  test_for_zero(t4ddg_1(1,2,0,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(1,0,2,2)");
+
+  t2_1(i,j)=t4ddg_1(1,i,1,j);
+  test_for_zero(t4ddg_1(1,0,1,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(1,1,0,0)");
+  test_for_zero(t4ddg_1(1,0,1,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(1,1,0,1)");
+  test_for_zero(t4ddg_1(1,0,1,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(1,1,0,2)");
+  test_for_zero(t4ddg_1(1,1,1,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(1,1,1,0)");
+  test_for_zero(t4ddg_1(1,1,1,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(1,1,1,1)");
+  test_for_zero(t4ddg_1(1,1,1,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(1,1,1,2)");
+  test_for_zero(t4ddg_1(1,2,1,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(1,1,2,0)");
+  test_for_zero(t4ddg_1(1,2,1,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(1,1,2,1)");
+  test_for_zero(t4ddg_1(1,2,1,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(1,1,2,2)");
+
+  t2_1(i,j)=t4ddg_1(1,i,2,j);
+  test_for_zero(t4ddg_1(1,0,2,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(1,2,0,0)");
+  test_for_zero(t4ddg_1(1,0,2,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(1,2,0,1)");
+  test_for_zero(t4ddg_1(1,0,2,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(1,2,0,2)");
+  test_for_zero(t4ddg_1(1,1,2,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(1,2,1,0)");
+  test_for_zero(t4ddg_1(1,1,2,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(1,2,1,1)");
+  test_for_zero(t4ddg_1(1,1,2,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(1,2,1,2)");
+  test_for_zero(t4ddg_1(1,2,2,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(1,2,2,0)");
+  test_for_zero(t4ddg_1(1,2,2,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(1,2,2,1)");
+  test_for_zero(t4ddg_1(1,2,2,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(1,2,2,2)");
+
+  t2_1(i,j)=t4ddg_1(2,i,0,j);
+  test_for_zero(t4ddg_1(2,0,0,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(2,0,0,0)");
+  test_for_zero(t4ddg_1(2,0,0,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(2,0,0,1)");
+  test_for_zero(t4ddg_1(2,0,0,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(2,0,0,2)");
+  test_for_zero(t4ddg_1(2,1,0,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(2,0,1,0)");
+  test_for_zero(t4ddg_1(2,1,0,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(2,0,1,1)");
+  test_for_zero(t4ddg_1(2,1,0,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(2,0,1,2)");
+  test_for_zero(t4ddg_1(2,2,0,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(2,0,2,0)");
+  test_for_zero(t4ddg_1(2,2,0,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(2,0,2,1)");
+  test_for_zero(t4ddg_1(2,2,0,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(2,0,2,2)");
+
+  t2_1(i,j)=t4ddg_1(2,i,1,j);
+  test_for_zero(t4ddg_1(2,0,1,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(2,1,0,0)");
+  test_for_zero(t4ddg_1(2,0,1,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(2,1,0,1)");
+  test_for_zero(t4ddg_1(2,0,1,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(2,1,0,2)");
+  test_for_zero(t4ddg_1(2,1,1,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(2,1,1,0)");
+  test_for_zero(t4ddg_1(2,1,1,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(2,1,1,1)");
+  test_for_zero(t4ddg_1(2,1,1,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(2,1,1,2)");
+  test_for_zero(t4ddg_1(2,2,1,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(2,1,2,0)");
+  test_for_zero(t4ddg_1(2,2,1,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(2,1,2,1)");
+  test_for_zero(t4ddg_1(2,2,1,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(2,1,2,2)");
+
+  t2_1(i,j)=t4ddg_1(2,i,2,j);
+  test_for_zero(t4ddg_1(2,0,2,0) - (t2_1(0,0))
+		,"T4ddg(Num,i,Num,j)(2,2,0,0)");
+  test_for_zero(t4ddg_1(2,0,2,1) - (t2_1(0,1))
+		,"T4ddg(Num,i,Num,j)(2,2,0,1)");
+  test_for_zero(t4ddg_1(2,0,2,2) - (t2_1(0,2))
+		,"T4ddg(Num,i,Num,j)(2,2,0,2)");
+  test_for_zero(t4ddg_1(2,1,2,0) - (t2_1(1,0))
+		,"T4ddg(Num,i,Num,j)(2,2,1,0)");
+  test_for_zero(t4ddg_1(2,1,2,1) - (t2_1(1,1))
+		,"T4ddg(Num,i,Num,j)(2,2,1,1)");
+  test_for_zero(t4ddg_1(2,1,2,2) - (t2_1(1,2))
+		,"T4ddg(Num,i,Num,j)(2,2,1,2)");
+  test_for_zero(t4ddg_1(2,2,2,0) - (t2_1(2,0))
+		,"T4ddg(Num,i,Num,j)(2,2,2,0)");
+  test_for_zero(t4ddg_1(2,2,2,1) - (t2_1(2,1))
+		,"T4ddg(Num,i,Num,j)(2,2,2,1)");
+  test_for_zero(t4ddg_1(2,2,2,2) - (t2_1(2,2))
+		,"T4ddg(Num,i,Num,j)(2,2,2,2)");
+
+  t3dg_1(j,k,i)=t4ddg_1(0,i,j,k);
+  test_for_zero(t3dg_1(0,0,0) - t4ddg_1(0,0,0,0)
+		,"T4ddg(Num,i,j,k)(0,0,0,0)");
+  test_for_zero(t3dg_1(0,1,0) - t4ddg_1(0,0,0,1)
+		,"T4ddg(Num,i,j,k)(0,0,0,1)");
+  test_for_zero(t3dg_1(0,2,0) - t4ddg_1(0,0,0,2)
+		,"T4ddg(Num,i,j,k)(0,0,0,2)");
+  test_for_zero(t3dg_1(1,0,0) - t4ddg_1(0,0,1,0)
+		,"T4ddg(Num,i,j,k)(0,0,1,0)");
+  test_for_zero(t3dg_1(1,1,0) - t4ddg_1(0,0,1,1)
+		,"T4ddg(Num,i,j,k)(0,0,1,1)");
+  test_for_zero(t3dg_1(1,2,0) - t4ddg_1(0,0,1,2)
+		,"T4ddg(Num,i,j,k)(0,0,1,2)");
+  test_for_zero(t3dg_1(2,0,0) - t4ddg_1(0,0,2,0)
+		,"T4ddg(Num,i,j,k)(0,0,2,0)");
+  test_for_zero(t3dg_1(2,1,0) - t4ddg_1(0,0,2,1)
+		,"T4ddg(Num,i,j,k)(0,0,2,1)");
+  test_for_zero(t3dg_1(2,2,0) - t4ddg_1(0,0,2,2)
+		,"T4ddg(Num,i,j,k)(0,0,2,2)");
+  test_for_zero(t3dg_1(0,0,1) - t4ddg_1(0,1,0,0)
+		,"T4ddg(Num,i,j,k)(0,1,0,0)");
+  test_for_zero(t3dg_1(0,1,1) - t4ddg_1(0,1,0,1)
+		,"T4ddg(Num,i,j,k)(0,1,0,1)");
+  test_for_zero(t3dg_1(0,2,1) - t4ddg_1(0,1,0,2)
+		,"T4ddg(Num,i,j,k)(0,1,0,2)");
+  test_for_zero(t3dg_1(1,0,1) - t4ddg_1(0,1,1,0)
+		,"T4ddg(Num,i,j,k)(0,1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - t4ddg_1(0,1,1,1)
+		,"T4ddg(Num,i,j,k)(0,1,1,1)");
+  test_for_zero(t3dg_1(1,2,1) - t4ddg_1(0,1,1,2)
+		,"T4ddg(Num,i,j,k)(0,1,1,2)");
+  test_for_zero(t3dg_1(2,0,1) - t4ddg_1(0,1,2,0)
+		,"T4ddg(Num,i,j,k)(0,1,2,0)");
+  test_for_zero(t3dg_1(2,1,1) - t4ddg_1(0,1,2,1)
+		,"T4ddg(Num,i,j,k)(0,1,2,1)");
+  test_for_zero(t3dg_1(2,2,1) - t4ddg_1(0,1,2,2)
+		,"T4ddg(Num,i,j,k)(0,1,2,2)");
+  test_for_zero(t3dg_1(0,0,2) - t4ddg_1(0,2,0,0)
+		,"T4ddg(Num,i,j,k)(0,2,0,0)");
+  test_for_zero(t3dg_1(0,1,2) - t4ddg_1(0,2,0,1)
+		,"T4ddg(Num,i,j,k)(0,2,0,1)");
+  test_for_zero(t3dg_1(0,2,2) - t4ddg_1(0,2,0,2)
+		,"T4ddg(Num,i,j,k)(0,2,0,2)");
+  test_for_zero(t3dg_1(1,0,2) - t4ddg_1(0,2,1,0)
+		,"T4ddg(Num,i,j,k)(0,2,1,0)");
+  test_for_zero(t3dg_1(1,1,2) - t4ddg_1(0,2,1,1)
+		,"T4ddg(Num,i,j,k)(0,2,1,1)");
+  test_for_zero(t3dg_1(1,2,2) - t4ddg_1(0,2,1,2)
+		,"T4ddg(Num,i,j,k)(0,2,1,2)");
+  test_for_zero(t3dg_1(2,0,2) - t4ddg_1(0,2,2,0)
+		,"T4ddg(Num,i,j,k)(0,2,2,0)");
+  test_for_zero(t3dg_1(2,1,2) - t4ddg_1(0,2,2,1)
+		,"T4ddg(Num,i,j,k)(0,2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - t4ddg_1(0,2,2,2)
+		,"T4ddg(Num,i,j,k)(0,2,2,2)");
+
+  t3dg_1(j,k,i)=t4ddg_1(1,i,j,k);
+  test_for_zero(t3dg_1(0,0,0) - t4ddg_1(1,0,0,0)
+		,"T4ddg(Num,i,j,k)(1,0,0,0)");
+  test_for_zero(t3dg_1(0,1,0) - t4ddg_1(1,0,0,1)
+		,"T4ddg(Num,i,j,k)(1,0,0,1)");
+  test_for_zero(t3dg_1(0,2,0) - t4ddg_1(1,0,0,2)
+		,"T4ddg(Num,i,j,k)(1,0,0,2)");
+  test_for_zero(t3dg_1(1,0,0) - t4ddg_1(1,0,1,0)
+		,"T4ddg(Num,i,j,k)(1,0,1,0)");
+  test_for_zero(t3dg_1(1,1,0) - t4ddg_1(1,0,1,1)
+		,"T4ddg(Num,i,j,k)(1,0,1,1)");
+  test_for_zero(t3dg_1(1,2,0) - t4ddg_1(1,0,1,2)
+		,"T4ddg(Num,i,j,k)(1,0,1,2)");
+  test_for_zero(t3dg_1(2,0,0) - t4ddg_1(1,0,2,0)
+		,"T4ddg(Num,i,j,k)(1,0,2,0)");
+  test_for_zero(t3dg_1(2,1,0) - t4ddg_1(1,0,2,1)
+		,"T4ddg(Num,i,j,k)(1,0,2,1)");
+  test_for_zero(t3dg_1(2,2,0) - t4ddg_1(1,0,2,2)
+		,"T4ddg(Num,i,j,k)(1,0,2,2)");
+  test_for_zero(t3dg_1(0,0,1) - t4ddg_1(1,1,0,0)
+		,"T4ddg(Num,i,j,k)(1,1,0,0)");
+  test_for_zero(t3dg_1(0,1,1) - t4ddg_1(1,1,0,1)
+		,"T4ddg(Num,i,j,k)(1,1,0,1)");
+  test_for_zero(t3dg_1(0,2,1) - t4ddg_1(1,1,0,2)
+		,"T4ddg(Num,i,j,k)(1,1,0,2)");
+  test_for_zero(t3dg_1(1,0,1) - t4ddg_1(1,1,1,0)
+		,"T4ddg(Num,i,j,k)(1,1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - t4ddg_1(1,1,1,1)
+		,"T4ddg(Num,i,j,k)(1,1,1,1)");
+  test_for_zero(t3dg_1(1,2,1) - t4ddg_1(1,1,1,2)
+		,"T4ddg(Num,i,j,k)(1,1,1,2)");
+  test_for_zero(t3dg_1(2,0,1) - t4ddg_1(1,1,2,0)
+		,"T4ddg(Num,i,j,k)(1,1,2,0)");
+  test_for_zero(t3dg_1(2,1,1) - t4ddg_1(1,1,2,1)
+		,"T4ddg(Num,i,j,k)(1,1,2,1)");
+  test_for_zero(t3dg_1(2,2,1) - t4ddg_1(1,1,2,2)
+		,"T4ddg(Num,i,j,k)(1,1,2,2)");
+  test_for_zero(t3dg_1(0,0,2) - t4ddg_1(1,2,0,0)
+		,"T4ddg(Num,i,j,k)(1,2,0,0)");
+  test_for_zero(t3dg_1(0,1,2) - t4ddg_1(1,2,0,1)
+		,"T4ddg(Num,i,j,k)(1,2,0,1)");
+  test_for_zero(t3dg_1(0,2,2) - t4ddg_1(1,2,0,2)
+		,"T4ddg(Num,i,j,k)(1,2,0,2)");
+  test_for_zero(t3dg_1(1,0,2) - t4ddg_1(1,2,1,0)
+		,"T4ddg(Num,i,j,k)(1,2,1,0)");
+  test_for_zero(t3dg_1(1,1,2) - t4ddg_1(1,2,1,1)
+		,"T4ddg(Num,i,j,k)(1,2,1,1)");
+  test_for_zero(t3dg_1(1,2,2) - t4ddg_1(1,2,1,2)
+		,"T4ddg(Num,i,j,k)(1,2,1,2)");
+  test_for_zero(t3dg_1(2,0,2) - t4ddg_1(1,2,2,0)
+		,"T4ddg(Num,i,j,k)(1,2,2,0)");
+  test_for_zero(t3dg_1(2,1,2) - t4ddg_1(1,2,2,1)
+		,"T4ddg(Num,i,j,k)(1,2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - t4ddg_1(1,2,2,2)
+		,"T4ddg(Num,i,j,k)(1,2,2,2)");
+
+  t3dg_1(j,k,i)=t4ddg_1(2,i,j,k);
+  test_for_zero(t3dg_1(0,0,0) - t4ddg_1(2,0,0,0)
+		,"T4ddg(Num,i,j,k)(2,0,0,0)");
+  test_for_zero(t3dg_1(0,1,0) - t4ddg_1(2,0,0,1)
+		,"T4ddg(Num,i,j,k)(2,0,0,1)");
+  test_for_zero(t3dg_1(0,2,0) - t4ddg_1(2,0,0,2)
+		,"T4ddg(Num,i,j,k)(2,0,0,2)");
+  test_for_zero(t3dg_1(1,0,0) - t4ddg_1(2,0,1,0)
+		,"T4ddg(Num,i,j,k)(2,0,1,0)");
+  test_for_zero(t3dg_1(1,1,0) - t4ddg_1(2,0,1,1)
+		,"T4ddg(Num,i,j,k)(2,0,1,1)");
+  test_for_zero(t3dg_1(1,2,0) - t4ddg_1(2,0,1,2)
+		,"T4ddg(Num,i,j,k)(2,0,1,2)");
+  test_for_zero(t3dg_1(2,0,0) - t4ddg_1(2,0,2,0)
+		,"T4ddg(Num,i,j,k)(2,0,2,0)");
+  test_for_zero(t3dg_1(2,1,0) - t4ddg_1(2,0,2,1)
+		,"T4ddg(Num,i,j,k)(2,0,2,1)");
+  test_for_zero(t3dg_1(2,2,0) - t4ddg_1(2,0,2,2)
+		,"T4ddg(Num,i,j,k)(2,0,2,2)");
+  test_for_zero(t3dg_1(0,0,1) - t4ddg_1(2,1,0,0)
+		,"T4ddg(Num,i,j,k)(2,1,0,0)");
+  test_for_zero(t3dg_1(0,1,1) - t4ddg_1(2,1,0,1)
+		,"T4ddg(Num,i,j,k)(2,1,0,1)");
+  test_for_zero(t3dg_1(0,2,1) - t4ddg_1(2,1,0,2)
+		,"T4ddg(Num,i,j,k)(2,1,0,2)");
+  test_for_zero(t3dg_1(1,0,1) - t4ddg_1(2,1,1,0)
+		,"T4ddg(Num,i,j,k)(2,1,1,0)");
+  test_for_zero(t3dg_1(1,1,1) - t4ddg_1(2,1,1,1)
+		,"T4ddg(Num,i,j,k)(2,1,1,1)");
+  test_for_zero(t3dg_1(1,2,1) - t4ddg_1(2,1,1,2)
+		,"T4ddg(Num,i,j,k)(2,1,1,2)");
+  test_for_zero(t3dg_1(2,0,1) - t4ddg_1(2,1,2,0)
+		,"T4ddg(Num,i,j,k)(2,1,2,0)");
+  test_for_zero(t3dg_1(2,1,1) - t4ddg_1(2,1,2,1)
+		,"T4ddg(Num,i,j,k)(2,1,2,1)");
+  test_for_zero(t3dg_1(2,2,1) - t4ddg_1(2,1,2,2)
+		,"T4ddg(Num,i,j,k)(2,1,2,2)");
+  test_for_zero(t3dg_1(0,0,2) - t4ddg_1(2,2,0,0)
+		,"T4ddg(Num,i,j,k)(2,2,0,0)");
+  test_for_zero(t3dg_1(0,1,2) - t4ddg_1(2,2,0,1)
+		,"T4ddg(Num,i,j,k)(2,2,0,1)");
+  test_for_zero(t3dg_1(0,2,2) - t4ddg_1(2,2,0,2)
+		,"T4ddg(Num,i,j,k)(2,2,0,2)");
+  test_for_zero(t3dg_1(1,0,2) - t4ddg_1(2,2,1,0)
+		,"T4ddg(Num,i,j,k)(2,2,1,0)");
+  test_for_zero(t3dg_1(1,1,2) - t4ddg_1(2,2,1,1)
+		,"T4ddg(Num,i,j,k)(2,2,1,1)");
+  test_for_zero(t3dg_1(1,2,2) - t4ddg_1(2,2,1,2)
+		,"T4ddg(Num,i,j,k)(2,2,1,2)");
+  test_for_zero(t3dg_1(2,0,2) - t4ddg_1(2,2,2,0)
+		,"T4ddg(Num,i,j,k)(2,2,2,0)");
+  test_for_zero(t3dg_1(2,1,2) - t4ddg_1(2,2,2,1)
+		,"T4ddg(Num,i,j,k)(2,2,2,1)");
+  test_for_zero(t3dg_1(2,2,2) - t4ddg_1(2,2,2,2)
+		,"T4ddg(Num,i,j,k)(2,2,2,2)");
+
+  /* Only one index int the first slot*/
+
+  t1_1(i)=t4ddg_1(i,0,0,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,0)
+		,"T4ddg(i,Num,Num,Num)(0,0,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,0)
+		,"T4ddg(i,Num,Num,Num)(0,0,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,0)
+		,"T4ddg(i,Num,Num,Num)(0,0,0,2)");
+  t1_1(i)=t4ddg_1(i,0,0,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,1)
+		,"T4ddg(i,Num,Num,Num)(0,0,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,1)
+		,"T4ddg(i,Num,Num,Num)(0,0,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,1)
+		,"T4ddg(i,Num,Num,Num)(0,0,1,2)");
+  t1_1(i)=t4ddg_1(i,0,0,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,2)
+		,"T4ddg(i,Num,Num,Num)(0,0,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,2)
+		,"T4ddg(i,Num,Num,Num)(0,0,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,2)
+		,"T4ddg(i,Num,Num,Num)(0,0,2,2)");
+  t1_1(i)=t4ddg_1(i,0,1,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,0)
+		,"T4ddg(i,Num,Num,Num)(0,1,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,0)
+		,"T4ddg(i,Num,Num,Num)(0,1,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,0)
+		,"T4ddg(i,Num,Num,Num)(0,1,0,2)");
+  t1_1(i)=t4ddg_1(i,0,1,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,1)
+		,"T4ddg(i,Num,Num,Num)(0,1,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,1)
+		,"T4ddg(i,Num,Num,Num)(0,1,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,1)
+		,"T4ddg(i,Num,Num,Num)(0,1,1,2)");
+  t1_1(i)=t4ddg_1(i,0,1,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,2)
+		,"T4ddg(i,Num,Num,Num)(0,1,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,2)
+		,"T4ddg(i,Num,Num,Num)(0,1,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,2)
+		,"T4ddg(i,Num,Num,Num)(0,1,2,2)");
+  t1_1(i)=t4ddg_1(i,0,2,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,0)
+		,"T4ddg(i,Num,Num,Num)(0,2,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,0)
+		,"T4ddg(i,Num,Num,Num)(0,2,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,0)
+		,"T4ddg(i,Num,Num,Num)(0,2,0,2)");
+  t1_1(i)=t4ddg_1(i,0,2,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,1)
+		,"T4ddg(i,Num,Num,Num)(0,2,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,1)
+		,"T4ddg(i,Num,Num,Num)(0,2,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,1)
+		,"T4ddg(i,Num,Num,Num)(0,2,1,2)");
+  t1_1(i)=t4ddg_1(i,0,2,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,2)
+		,"T4ddg(i,Num,Num,Num)(0,2,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,2)
+		,"T4ddg(i,Num,Num,Num)(0,2,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,2)
+		,"T4ddg(i,Num,Num,Num)(0,2,2,2)");
+  t1_1(i)=t4ddg_1(i,1,0,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,0)
+		,"T4ddg(i,Num,Num,Num)(1,0,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,0)
+		,"T4ddg(i,Num,Num,Num)(1,0,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,0)
+		,"T4ddg(i,Num,Num,Num)(1,0,0,2)");
+  t1_1(i)=t4ddg_1(i,1,0,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,1)
+		,"T4ddg(i,Num,Num,Num)(1,0,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,1)
+		,"T4ddg(i,Num,Num,Num)(1,0,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,1)
+		,"T4ddg(i,Num,Num,Num)(1,0,1,2)");
+  t1_1(i)=t4ddg_1(i,1,0,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,2)
+		,"T4ddg(i,Num,Num,Num)(1,0,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,2)
+		,"T4ddg(i,Num,Num,Num)(1,0,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,0,2)
+		,"T4ddg(i,Num,Num,Num)(1,0,2,2)");
+  t1_1(i)=t4ddg_1(i,1,1,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,0)
+		,"T4ddg(i,Num,Num,Num)(1,1,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,0)
+		,"T4ddg(i,Num,Num,Num)(1,1,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,0)
+		,"T4ddg(i,Num,Num,Num)(1,1,0,2)");
+  t1_1(i)=t4ddg_1(i,1,1,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,1)
+		,"T4ddg(i,Num,Num,Num)(1,1,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,1)
+		,"T4ddg(i,Num,Num,Num)(1,1,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,1)
+		,"T4ddg(i,Num,Num,Num)(1,1,1,2)");
+  t1_1(i)=t4ddg_1(i,1,1,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,2)
+		,"T4ddg(i,Num,Num,Num)(1,1,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,2)
+		,"T4ddg(i,Num,Num,Num)(1,1,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,1,2)
+		,"T4ddg(i,Num,Num,Num)(1,1,2,2)");
+  t1_1(i)=t4ddg_1(i,1,2,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,0)
+		,"T4ddg(i,Num,Num,Num)(1,2,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,0)
+		,"T4ddg(i,Num,Num,Num)(1,2,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,0)
+		,"T4ddg(i,Num,Num,Num)(1,2,0,2)");
+  t1_1(i)=t4ddg_1(i,1,2,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,1)
+		,"T4ddg(i,Num,Num,Num)(1,2,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,1)
+		,"T4ddg(i,Num,Num,Num)(1,2,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,1)
+		,"T4ddg(i,Num,Num,Num)(1,2,1,2)");
+  t1_1(i)=t4ddg_1(i,1,2,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,2)
+		,"T4ddg(i,Num,Num,Num)(1,2,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,2)
+		,"T4ddg(i,Num,Num,Num)(1,2,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,1,2,2)
+		,"T4ddg(i,Num,Num,Num)(1,2,2,2)");
+  t1_1(i)=t4ddg_1(i,2,0,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,0)
+		,"T4ddg(i,Num,Num,Num)(2,0,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,0)
+		,"T4ddg(i,Num,Num,Num)(2,0,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,0)
+		,"T4ddg(i,Num,Num,Num)(2,0,0,2)");
+  t1_1(i)=t4ddg_1(i,2,0,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,1)
+		,"T4ddg(i,Num,Num,Num)(2,0,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,1)
+		,"T4ddg(i,Num,Num,Num)(2,0,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,1)
+		,"T4ddg(i,Num,Num,Num)(2,0,1,2)");
+  t1_1(i)=t4ddg_1(i,2,0,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,2)
+		,"T4ddg(i,Num,Num,Num)(2,0,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,2)
+		,"T4ddg(i,Num,Num,Num)(2,0,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,0,2)
+		,"T4ddg(i,Num,Num,Num)(2,0,2,2)");
+  t1_1(i)=t4ddg_1(i,2,1,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,0)
+		,"T4ddg(i,Num,Num,Num)(2,1,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,0)
+		,"T4ddg(i,Num,Num,Num)(2,1,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,0)
+		,"T4ddg(i,Num,Num,Num)(2,1,0,2)");
+  t1_1(i)=t4ddg_1(i,2,1,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,1)
+		,"T4ddg(i,Num,Num,Num)(2,1,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,1)
+		,"T4ddg(i,Num,Num,Num)(2,1,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,1)
+		,"T4ddg(i,Num,Num,Num)(2,1,1,2)");
+  t1_1(i)=t4ddg_1(i,2,1,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,2)
+		,"T4ddg(i,Num,Num,Num)(2,1,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,2)
+		,"T4ddg(i,Num,Num,Num)(2,1,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,1,2)
+		,"T4ddg(i,Num,Num,Num)(2,1,2,2)");
+  t1_1(i)=t4ddg_1(i,2,2,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,0)
+		,"T4ddg(i,Num,Num,Num)(2,2,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,0)
+		,"T4ddg(i,Num,Num,Num)(2,2,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,0)
+		,"T4ddg(i,Num,Num,Num)(2,2,0,2)");
+  t1_1(i)=t4ddg_1(i,2,2,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,1)
+		,"T4ddg(i,Num,Num,Num)(2,2,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,1)
+		,"T4ddg(i,Num,Num,Num)(2,2,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,1)
+		,"T4ddg(i,Num,Num,Num)(2,2,1,2)");
+  t1_1(i)=t4ddg_1(i,2,2,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,2)
+		,"T4ddg(i,Num,Num,Num)(2,2,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,2)
+		,"T4ddg(i,Num,Num,Num)(2,2,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,2,2,2)
+		,"T4ddg(i,Num,Num,Num)(2,2,2,2)");
+
+  /* Only one index in the second slot */
+
+  t1_1(i)=t4ddg_1(0,i,0,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(0,0,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(0,0,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(0,0,0,2)");
+  t1_1(i)=t4ddg_1(0,i,0,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(0,0,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(0,0,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(0,0,1,2)");
+  t1_1(i)=t4ddg_1(0,i,0,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(0,0,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(0,0,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(0,0,2,2)");
+  t1_1(i)=t4ddg_1(0,i,1,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(0,1,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(0,1,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(0,1,0,2)");
+  t1_1(i)=t4ddg_1(0,i,1,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(0,1,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(0,1,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(0,1,1,2)");
+  t1_1(i)=t4ddg_1(0,i,1,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(0,1,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(0,1,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(0,1,2,2)");
+  t1_1(i)=t4ddg_1(0,i,2,0);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(0,2,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(0,2,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(0,2,0,2)");
+  t1_1(i)=t4ddg_1(0,i,2,1);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(0,2,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(0,2,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(0,2,1,2)");
+  t1_1(i)=t4ddg_1(0,i,2,2);
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(0,2,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(0,2,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(0,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(0,2,2,2)");
+  t1_1(i)=t4ddg_1(1,i,0,0);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(1,0,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(1,0,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(1,0,0,2)");
+  t1_1(i)=t4ddg_1(1,i,0,1);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(1,0,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(1,0,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(1,0,1,2)");
+  t1_1(i)=t4ddg_1(1,i,0,2);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(1,0,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(1,0,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(1,0,2,2)");
+  t1_1(i)=t4ddg_1(1,i,1,0);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(1,1,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(1,1,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(1,1,0,2)");
+  t1_1(i)=t4ddg_1(1,i,1,1);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(1,1,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(1,1,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(1,1,1,2)");
+  t1_1(i)=t4ddg_1(1,i,1,2);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(1,1,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(1,1,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(1,1,2,2)");
+  t1_1(i)=t4ddg_1(1,i,2,0);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(1,2,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(1,2,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(1,2,0,2)");
+  t1_1(i)=t4ddg_1(1,i,2,1);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(1,2,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(1,2,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(1,2,1,2)");
+  t1_1(i)=t4ddg_1(1,i,2,2);
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(1,2,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(1,2,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(1,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(1,2,2,2)");
+  t1_1(i)=t4ddg_1(2,i,0,0);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(2,0,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(2,0,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,0)
+		,"T4ddg(Num,i,Num,Num)(2,0,0,2)");
+  t1_1(i)=t4ddg_1(2,i,0,1);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(2,0,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(2,0,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,1)
+		,"T4ddg(Num,i,Num,Num)(2,0,1,2)");
+  t1_1(i)=t4ddg_1(2,i,0,2);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(2,0,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(2,0,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,0,2)
+		,"T4ddg(Num,i,Num,Num)(2,0,2,2)");
+  t1_1(i)=t4ddg_1(2,i,1,0);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(2,1,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(2,1,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,0)
+		,"T4ddg(Num,i,Num,Num)(2,1,0,2)");
+  t1_1(i)=t4ddg_1(2,i,1,1);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(2,1,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(2,1,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,1)
+		,"T4ddg(Num,i,Num,Num)(2,1,1,2)");
+  t1_1(i)=t4ddg_1(2,i,1,2);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(2,1,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(2,1,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,1,2)
+		,"T4ddg(Num,i,Num,Num)(2,1,2,2)");
+  t1_1(i)=t4ddg_1(2,i,2,0);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(2,2,0,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(2,2,0,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,0)
+		,"T4ddg(Num,i,Num,Num)(2,2,0,2)");
+  t1_1(i)=t4ddg_1(2,i,2,1);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(2,2,1,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(2,2,1,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,1)
+		,"T4ddg(Num,i,Num,Num)(2,2,1,2)");
+  t1_1(i)=t4ddg_1(2,i,2,2);
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(2,2,2,0)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(2,2,2,1)");
+  test_for_zero(t1_1(0) - t4ddg_1(2,0,2,2)
+		,"T4ddg(Num,i,Num,Num)(2,2,2,2)");
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T0.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T0.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "../../FTensor.h"
+#include "test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T0(const int &T, Tensor0<double*> &t0_1,
+	     const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor0 test cases. */
+
+  t0_1=T+t0_2;
+  test_for_zero(t0_1-T-t0_2,"T+T0");
+  t0_1+=10+t0_2;
+  test_for_zero(t0_1-(10+T+2*t0_2),"T0+=T");
+  t0_1-=5+3*t0_2;
+  test_for_zero(t0_1-(5+T-t0_2),"T0-=T");
+  t0_1*=2+t0_2;
+  test_for_zero(t0_1-(5+T-t0_2)*(2+t0_2),"T0*=T");
+  t0_1/=7.0+t0_2;
+  test_for_zero(t0_1-(5+T-t0_2)*(2+t0_2)/(7.0+t0_2),"T0/=T");
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T0.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T0.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,8 @@
+extern void test_T0(const int &T, Tensor0<double*> &t0_1,
+		    const Tensor0<double*> &t0_2,
+		    Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		    Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		    const Tensor2<double,3,3> &t2_3,
+		    Tensor2_symmetric<double,3> &t2s_1,
+		    const Tensor2_symmetric<double,3> &t2s_2,
+		    const Tensor2_symmetric<double,3> &t2s_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T1.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T1.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,93 @@
+#include <iostream>
+#include "../../FTensor.h"
+#include "test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T1(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor1 test cases. */
+
+  t1_1(i)=2*t1_2(i);
+  test_for_zero(t1_1(0)-2*t1_2(0),"T*T1(0)");
+  test_for_zero(t1_1(1)-2*t1_2(1),"T*T1(1)");
+  test_for_zero(t1_1(2)-2*t1_2(2),"T*T1(2)");
+  t1_1(i)+=3*t1_2(i);
+  test_for_zero(t1_1(0)-5*t1_2(0),"T1+=T1(0)");
+  test_for_zero(t1_1(1)-5*t1_2(1),"T1+=T1(1)");
+  test_for_zero(t1_1(2)-5*t1_2(2),"T1+=T1(2)");
+  t1_1(i)-=t1_2(i)/2;
+  test_for_zero(t1_1(0)-4.5*t1_2(0),"T1-=T1(0)");
+  test_for_zero(t1_1(1)-4.5*t1_2(1),"T1-=T1(1)");
+  test_for_zero(t1_1(2)-4.5*t1_2(2),"T1-=T1(2)");
+  t1_1(i)*=3;
+  test_for_zero(t1_1(0)-13.5*t1_2(0),"T1(0)*=T");
+  test_for_zero(t1_1(1)-13.5*t1_2(1),"T1(1)*=T");
+  test_for_zero(t1_1(2)-13.5*t1_2(2),"T1(2)*=T");
+  t1_1(i)/=4.5;
+  test_for_zero(t1_1(0)-3*t1_2(0),"T1(0)/=T");
+  test_for_zero(t1_1(1)-3*t1_2(1),"T1(1)/=T");
+  test_for_zero(t1_1(2)-3*t1_2(2),"T1(2)/=T");
+  t1_1(i)+=10;
+  test_for_zero(t1_1(0)-3*t1_2(0)-10,"T1(0)+=T");
+  test_for_zero(t1_1(1)-3*t1_2(1)-10,"T1(1)+=T");
+  test_for_zero(t1_1(2)-3*t1_2(2)-10,"T1(2)+=T");
+  t1_1(i)-=7;
+  test_for_zero(t1_1(0)-3*t1_2(0)-3,"T1(0)-=T");
+  test_for_zero(t1_1(1)-3*t1_2(1)-3,"T1(1)-=T");
+  test_for_zero(t1_1(2)-3*t1_2(2)-3,"T1(2)-=T");
+  t1_1(i)=t1_2(i)+t1_1(i);
+  test_for_zero(t1_1(0)-4*t1_2(0)-3,"T1+T1(0)");
+  test_for_zero(t1_1(1)-4*t1_2(1)-3,"T1+T1(1)");
+  test_for_zero(t1_1(2)-4*t1_2(2)-3,"T1+T1(2)");
+  t1_1(i)=-t1_2(i)-t1_1(i);
+  test_for_zero(t1_1(0)+5*t1_2(0)+3,"-T1-T1(0)");
+  test_for_zero(t1_1(1)+5*t1_2(1)+3,"-T1-T1(1)");
+  test_for_zero(t1_1(2)+5*t1_2(2)+3,"-T1-T1(2)");
+  t1_1(i)=t1_2(i)+10;
+  test_for_zero(t1_1(0)-t1_2(0)-10,"T1(0)+T");
+  test_for_zero(t1_1(1)-t1_2(1)-10,"T1(1)+T");
+  test_for_zero(t1_1(2)-t1_2(2)-10,"T1(2)+T");
+  t1_1(i)=t1_2(i)-10;
+  test_for_zero(t1_1(0)-t1_2(0)+10,"T1(0)-T");
+  test_for_zero(t1_1(1)-t1_2(1)+10,"T1(1)-T");
+  test_for_zero(t1_1(2)-t1_2(2)+10,"T1(2)-T");
+  test_for_zero(t1_1(i)*t1_2(i)-(t1_2(0)*(t1_2(0)-10) + t1_2(1)*(t1_2(1)-10)
+				 + t1_2(2)*(t1_2(2)-10)),"T1(i)*T1(i)");
+  t1_1(i)=10-t1_2(i);
+  test_for_zero(t1_1(0)+t1_2(0)-10,"T-T1(0)");
+  test_for_zero(t1_1(1)+t1_2(1)-10,"T-T1(1)");
+  test_for_zero(t1_1(2)+t1_2(2)-10,"T-T1(2)");
+  t1_1(i)=t1_2(i);
+  test_for_zero(t1_1(0)-t1_2(0),"T1=T1(0)");
+  test_for_zero(t1_1(1)-t1_2(1),"T1=T1(1)");
+  test_for_zero(t1_1(2)-t1_2(2),"T1=T1(2)");
+  t1_1(i)=10;
+  test_for_zero(t1_1(0)-10,"T1(0)=T");
+  test_for_zero(t1_1(1)-10,"T1(1)=T");
+  test_for_zero(t1_1(2)-10,"T1(2)=T");
+  
+  t1_1(i)=(t1_1(i)&t1_2(i));
+  test_for_zero(t1_1(0)-10*t1_2(0),"T1&T1(0)");
+  test_for_zero(t1_1(1)-10*t1_2(1),"T1&T1(1)");
+  test_for_zero(t1_1(2)-10*t1_2(2),"T1&T1(2)");
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T1.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T1.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,7 @@
+extern void test_T1(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T2.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T2.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,7 @@
+extern void test_T2(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	     Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	     Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	     const Tensor2<double,3,3> &t2_3,
+	     Tensor2_symmetric<double,3> &t2s_1,
+	     const Tensor2_symmetric<double,3> &t2s_2,
+	     const Tensor2_symmetric<double,3> &t2s_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T2s.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T2s.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,7 @@
+extern void test_T2s(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T3.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T3.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+extern void test_T3(const int &T, Tensor0<double*> &t0_1,
+		    const Tensor0<double*> &t0_2,
+		    Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		    Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		    const Tensor2<double,3,3> &t2_3,
+		    Tensor2_symmetric<double,3> &t2s_1,
+		    const Tensor2_symmetric<double,3> &t2s_2,
+		    const Tensor2_symmetric<double,3> &t2s_3,
+		    Tensor3_dg<double,3,3> &t3dg_1,
+		    const Tensor3_dg<double,3,3> &t3dg_2,
+		    const Tensor3_dg<double,3,3> &t3dg_3,
+		    Tensor3_christof<double,3,3> &t3ch_1,
+		    const Tensor3_christof<double,3,3> &t3ch_2,
+		    const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T3II.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T3II.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,13 @@
+extern void test_T3II(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+		      const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T3as.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T3as.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+extern 
+void test_T3as(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_antisymmetric<double,3,3> &t3as_1,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	       const Tensor3_antisymmetric<double,3,3> &t3as_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T3ch.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T3ch.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,448 @@
+#include <iostream>
+#include "../../FTensor.h"
+#include "test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T3ch(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  /* Tensor3_ch tests */
+
+  t2s_1(i,j)=t3ch_1(N0,i,j);
+  test_for_zero(t3ch_1(0,0,0)-t2s_1(0,0)
+		,"T3ch(N,i,j)(0,0,0)");
+  test_for_zero(t3ch_1(0,0,1)-t2s_1(0,1)
+		,"T3ch(N,i,j)(0,0,1)");
+  test_for_zero(t3ch_1(0,0,2)-t2s_1(0,2)
+		,"T3ch(N,i,j)(0,0,2)");
+  test_for_zero(t3ch_1(0,1,1)-t2s_1(1,1)
+		,"T3ch(N,i,j)(0,1,1)");
+  test_for_zero(t3ch_1(0,1,2)-t2s_1(1,2)
+		,"T3ch(N,i,j)(0,1,2)");
+  test_for_zero(t3ch_1(0,2,2)-t2s_1(2,2)
+		,"T3ch(N,i,j)(0,2,2)");
+  t2s_1(i,j)=t3ch_1(N1,i,j);
+  test_for_zero(t3ch_1(1,0,0)-t2s_1(0,0)
+		,"T3ch(N,i,j)(1,0,0)");
+  test_for_zero(t3ch_1(1,0,1)-t2s_1(0,1)
+		,"T3ch(N,i,j)(1,0,1)");
+  test_for_zero(t3ch_1(1,0,2)-t2s_1(0,2)
+		,"T3ch(N,i,j)(1,0,2)");
+  test_for_zero(t3ch_1(1,1,1)-t2s_1(1,1)
+		,"T3ch(N,i,j)(1,1,1)");
+  test_for_zero(t3ch_1(1,1,2)-t2s_1(1,2)
+		,"T3ch(N,i,j)(1,1,2)");
+  test_for_zero(t3ch_1(1,2,2)-t2s_1(2,2)
+		,"T3ch(N,i,j)(1,2,2)");
+  t2s_1(i,j)=t3ch_1(N2,i,j);
+  test_for_zero(t3ch_1(2,0,0)-t2s_1(0,0)
+		,"T3ch(N,i,j)(2,0,0)");
+  test_for_zero(t3ch_1(2,0,1)-t2s_1(0,1)
+		,"T3ch(N,i,j)(2,0,1)");
+  test_for_zero(t3ch_1(2,0,2)-t2s_1(0,2)
+		,"T3ch(N,i,j)(2,0,2)");
+  test_for_zero(t3ch_1(2,1,1)-t2s_1(1,1)
+		,"T3ch(N,i,j)(2,1,1)");
+  test_for_zero(t3ch_1(2,1,2)-t2s_1(1,2)
+		,"T3ch(N,i,j)(2,1,2)");
+  test_for_zero(t3ch_1(2,2,2)-t2s_1(2,2)
+		,"T3ch(N,i,j)(2,2,2)");
+
+  /* Now, test with actual numbers. */
+
+  t2s_1(i,j)=t3ch_2(0,i,j);
+  test_for_zero(t3ch_2(0,0,0)-t2s_1(0,0)
+		,"T3ch(Num,i,j)(0,0,0)");
+  test_for_zero(t3ch_2(0,0,1)-t2s_1(0,1)
+		,"T3ch(Num,i,j)(0,0,1)");
+  test_for_zero(t3ch_2(0,0,2)-t2s_1(0,2)
+		,"T3ch(Num,i,j)(0,0,2)");
+  test_for_zero(t3ch_2(0,1,0)-t2s_1(1,0)
+		,"T3ch(Num,i,j)(0,1,0)");
+  test_for_zero(t3ch_2(0,1,1)-t2s_1(1,1)
+		,"T3ch(Num,i,j)(0,1,1)");
+  test_for_zero(t3ch_2(0,1,2)-t2s_1(1,2)
+		,"T3ch(Num,i,j)(0,1,2)");
+  test_for_zero(t3ch_2(0,2,0)-t2s_1(2,0)
+		,"T3ch(Num,i,j)(0,2,0)");
+  test_for_zero(t3ch_2(0,2,1)-t2s_1(2,1)
+		,"T3ch(Num,i,j)(0,2,1)");
+  test_for_zero(t3ch_2(0,2,2)-t2s_1(2,2)
+		,"T3ch(Num,i,j)(0,2,2)");
+
+  t2s_1(i,j)=t3ch_2(1,i,j);
+  test_for_zero(t3ch_2(1,0,0)-t2s_1(0,0)
+		,"T3ch(Num,i,j)(1,0,0)");
+  test_for_zero(t3ch_2(1,0,1)-t2s_1(0,1)
+		,"T3ch(Num,i,j)(1,0,1)");
+  test_for_zero(t3ch_2(1,0,2)-t2s_1(0,2)
+		,"T3ch(Num,i,j)(1,0,2)");
+  test_for_zero(t3ch_2(1,1,0)-t2s_1(1,0)
+		,"T3ch(Num,i,j)(1,1,0)");
+  test_for_zero(t3ch_2(1,1,1)-t2s_1(1,1)
+		,"T3ch(Num,i,j)(1,1,1)");
+  test_for_zero(t3ch_2(1,1,2)-t2s_1(1,2)
+		,"T3ch(Num,i,j)(1,1,2)");
+  test_for_zero(t3ch_2(1,2,0)-t2s_1(2,0)
+		,"T3ch(Num,i,j)(1,2,0)");
+  test_for_zero(t3ch_2(1,2,1)-t2s_1(2,1)
+		,"T3ch(Num,i,j)(1,2,1)");
+  test_for_zero(t3ch_2(1,2,2)-t2s_1(2,2)
+		,"T3ch(Num,i,j)(1,2,2)");
+
+  t2s_1(i,j)=t3ch_2(2,i,j);
+  test_for_zero(t3ch_2(2,0,0)-t2s_1(0,0)
+		,"T3ch(Num,i,j)(2,0,0)");
+  test_for_zero(t3ch_2(2,0,1)-t2s_1(0,1)
+		,"T3ch(Num,i,j)(2,0,1)");
+  test_for_zero(t3ch_2(2,0,2)-t2s_1(0,2)
+		,"T3ch(Num,i,j)(2,0,2)");
+  test_for_zero(t3ch_2(2,1,0)-t2s_1(1,0)
+		,"T3ch(Num,i,j)(2,1,0)");
+  test_for_zero(t3ch_2(2,1,1)-t2s_1(1,1)
+		,"T3ch(Num,i,j)(2,1,1)");
+  test_for_zero(t3ch_2(2,1,2)-t2s_1(1,2)
+		,"T3ch(Num,i,j)(2,1,2)");
+  test_for_zero(t3ch_2(2,2,0)-t2s_1(2,0)
+		,"T3ch(Num,i,j)(2,2,0)");
+  test_for_zero(t3ch_2(2,2,1)-t2s_1(2,1)
+		,"T3ch(Num,i,j)(2,2,1)");
+  test_for_zero(t3ch_2(2,2,2)-t2s_1(2,2)
+		,"T3ch(Num,i,j)(2,2,2)");
+
+  t2_1(i,j)=t3ch_2(j,0,i);
+  test_for_zero(t3ch_2(0,0,0)-t2_1(0,0)
+		,"T3ch(j,Num,i)(0,0,0)");
+  test_for_zero(t3ch_2(1,0,0)-t2_1(0,1)
+		,"T3ch(j,Num,i)(0,0,1)");
+  test_for_zero(t3ch_2(2,0,0)-t2_1(0,2)
+		,"T3ch(j,Num,i)(0,0,2)");
+  test_for_zero(t3ch_2(0,0,1)-t2_1(1,0)
+		,"T3ch(j,Num,i)(0,1,0)");
+  test_for_zero(t3ch_2(1,0,1)-t2_1(1,1)
+		,"T3ch(j,Num,i)(0,1,1)");
+  test_for_zero(t3ch_2(2,0,1)-t2_1(1,2)
+		,"T3ch(j,Num,i)(0,1,2)");
+  test_for_zero(t3ch_2(0,0,2)-t2_1(2,0)
+		,"T3ch(j,Num,i)(0,2,0)");
+  test_for_zero(t3ch_2(1,0,2)-t2_1(2,1)
+		,"T3ch(j,Num,i)(0,2,1)");
+  test_for_zero(t3ch_2(2,0,2)-t2_1(2,2)
+		,"T3ch(j,Num,i)(0,2,2)");
+
+  t2_1(i,j)=t3ch_2(j,1,i);
+  test_for_zero(t3ch_2(0,1,0)-t2_1(0,0)
+		,"T3ch(j,Num,i)(1,0,0)");
+  test_for_zero(t3ch_2(1,1,0)-t2_1(0,1)
+		,"T3ch(j,Num,i)(1,0,1)");
+  test_for_zero(t3ch_2(2,1,0)-t2_1(0,2)
+		,"T3ch(j,Num,i)(1,0,2)");
+  test_for_zero(t3ch_2(0,1,1)-t2_1(1,0)
+		,"T3ch(j,Num,i)(1,1,0)");
+  test_for_zero(t3ch_2(1,1,1)-t2_1(1,1)
+		,"T3ch(j,Num,i)(1,1,1)");
+  test_for_zero(t3ch_2(2,1,1)-t2_1(1,2)
+		,"T3ch(j,Num,i)(1,1,2)");
+  test_for_zero(t3ch_2(0,1,2)-t2_1(2,0)
+		,"T3ch(j,Num,i)(1,2,0)");
+  test_for_zero(t3ch_2(1,1,2)-t2_1(2,1)
+		,"T3ch(j,Num,i)(1,2,1)");
+  test_for_zero(t3ch_2(2,1,2)-t2_1(2,2)
+		,"T3ch(j,Num,i)(1,2,2)");
+
+  t2_1(i,j)=t3ch_2(j,2,i);
+  test_for_zero(t3ch_2(0,2,0)-t2_1(0,0)
+		,"T3ch(j,Num,i)(2,0,0)");
+  test_for_zero(t3ch_2(1,2,0)-t2_1(0,1)
+		,"T3ch(j,Num,i)(2,0,1)");
+  test_for_zero(t3ch_2(2,2,0)-t2_1(0,2)
+		,"T3ch(j,Num,i)(2,0,2)");
+  test_for_zero(t3ch_2(0,2,1)-t2_1(1,0)
+		,"T3ch(j,Num,i)(2,1,0)");
+  test_for_zero(t3ch_2(1,2,1)-t2_1(1,1)
+		,"T3ch(j,Num,i)(2,1,1)");
+  test_for_zero(t3ch_2(2,2,1)-t2_1(1,2)
+		,"T3ch(j,Num,i)(2,1,2)");
+  test_for_zero(t3ch_2(0,2,2)-t2_1(2,0)
+		,"T3ch(j,Num,i)(2,2,0)");
+  test_for_zero(t3ch_2(1,2,2)-t2_1(2,1)
+		,"T3ch(j,Num,i)(2,2,1)");
+  test_for_zero(t3ch_2(2,2,2)-t2_1(2,2)
+		,"T3ch(j,Num,i)(2,2,2)");
+
+  t2_1(i,j)=t3ch_2(j,i,0);
+  test_for_zero(t3ch_2(0,0,0)-t2_1(0,0)
+		,"T3ch(j,i,Num)(0,0,0)");
+  test_for_zero(t3ch_2(1,0,0)-t2_1(0,1)
+		,"T3ch(j,i,Num)(0,0,1)");
+  test_for_zero(t3ch_2(2,0,0)-t2_1(0,2)
+		,"T3ch(j,i,Num)(0,0,2)");
+  test_for_zero(t3ch_2(0,1,0)-t2_1(1,0)
+		,"T3ch(j,i,Num)(0,1,0)");
+  test_for_zero(t3ch_2(1,1,0)-t2_1(1,1)
+		,"T3ch(j,i,Num)(0,1,1)");
+  test_for_zero(t3ch_2(2,1,0)-t2_1(1,2)
+		,"T3ch(j,i,Num)(0,1,2)");
+  test_for_zero(t3ch_2(0,2,0)-t2_1(2,0)
+		,"T3ch(j,i,Num)(0,2,0)");
+  test_for_zero(t3ch_2(1,2,0)-t2_1(2,1)
+		,"T3ch(j,i,Num)(0,2,1)");
+  test_for_zero(t3ch_2(2,2,0)-t2_1(2,2)
+		,"T3ch(j,i,Num)(0,2,2)");
+
+  t2_1(i,j)=t3ch_2(j,i,1);
+  test_for_zero(t3ch_2(0,0,1)-t2_1(0,0)
+		,"T3ch(j,i,Num)(1,0,0)");
+  test_for_zero(t3ch_2(1,0,1)-t2_1(0,1)
+		,"T3ch(j,i,Num)(1,0,1)");
+  test_for_zero(t3ch_2(2,0,1)-t2_1(0,2)
+		,"T3ch(j,i,Num)(1,0,2)");
+  test_for_zero(t3ch_2(0,1,1)-t2_1(1,0)
+		,"T3ch(j,i,Num)(1,1,0)");
+  test_for_zero(t3ch_2(1,1,1)-t2_1(1,1)
+		,"T3ch(j,i,Num)(1,1,1)");
+  test_for_zero(t3ch_2(2,1,1)-t2_1(1,2)
+		,"T3ch(j,i,Num)(1,1,2)");
+  test_for_zero(t3ch_2(0,2,1)-t2_1(2,0)
+		,"T3ch(j,i,Num)(1,2,0)");
+  test_for_zero(t3ch_2(1,2,1)-t2_1(2,1)
+		,"T3ch(j,i,Num)(1,2,1)");
+  test_for_zero(t3ch_2(2,2,1)-t2_1(2,2)
+		,"T3ch(j,i,Num)(1,2,2)");
+
+  t2_1(i,j)=t3ch_2(j,i,2);
+  test_for_zero(t3ch_2(0,0,2)-t2_1(0,0)
+		,"T3ch(j,i,Num)(2,0,0)");
+  test_for_zero(t3ch_2(1,0,2)-t2_1(0,1)
+		,"T3ch(j,i,Num)(2,0,1)");
+  test_for_zero(t3ch_2(2,0,2)-t2_1(0,2)
+		,"T3ch(j,i,Num)(2,0,2)");
+  test_for_zero(t3ch_2(0,1,2)-t2_1(1,0)
+		,"T3ch(j,i,Num)(2,1,0)");
+  test_for_zero(t3ch_2(1,1,2)-t2_1(1,1)
+		,"T3ch(j,i,Num)(2,1,1)");
+  test_for_zero(t3ch_2(2,1,2)-t2_1(1,2)
+		,"T3ch(j,i,Num)(2,1,2)");
+  test_for_zero(t3ch_2(0,2,2)-t2_1(2,0)
+		,"T3ch(j,i,Num)(2,2,0)");
+  test_for_zero(t3ch_2(1,2,2)-t2_1(2,1)
+		,"T3ch(j,i,Num)(2,2,1)");
+  test_for_zero(t3ch_2(2,2,2)-t2_1(2,2)
+		,"T3ch(j,i,Num)(2,2,2)");
+
+  /* Assignment to double */
+
+  t3ch_1(i,j,k)=10;
+  test_for_zero(t3ch_1(0,0,0) - 10
+		,"T3ch=T(0,0,0)");
+  test_for_zero(t3ch_1(0,0,1) - 10
+		,"T3ch=T(0,0,1)");
+  test_for_zero(t3ch_1(0,0,2) - 10
+		,"T3ch=T(0,0,2)");
+  test_for_zero(t3ch_1(0,1,0) - 10
+		,"T3ch=T(0,1,0)");
+  test_for_zero(t3ch_1(0,1,1) - 10
+		,"T3ch=T(0,1,1)");
+  test_for_zero(t3ch_1(0,1,2) - 10
+		,"T3ch=T(0,1,2)");
+  test_for_zero(t3ch_1(0,2,0) - 10
+		,"T3ch=T(0,2,0)");
+  test_for_zero(t3ch_1(0,2,1) - 10
+		,"T3ch=T(0,2,1)");
+  test_for_zero(t3ch_1(0,2,2) - 10
+		,"T3ch=T(0,2,2)");
+  test_for_zero(t3ch_1(1,0,0) - 10
+		,"T3ch=T(1,0,0)");
+  test_for_zero(t3ch_1(1,0,1) - 10
+		,"T3ch=T(1,0,1)");
+  test_for_zero(t3ch_1(1,0,2) - 10
+		,"T3ch=T(1,0,2)");
+  test_for_zero(t3ch_1(1,1,0) - 10
+		,"T3ch=T(1,1,0)");
+  test_for_zero(t3ch_1(1,1,1) - 10
+		,"T3ch=T(1,1,1)");
+  test_for_zero(t3ch_1(1,1,2) - 10
+		,"T3ch=T(1,1,2)");
+  test_for_zero(t3ch_1(1,2,0) - 10
+		,"T3ch=T(1,2,0)");
+  test_for_zero(t3ch_1(1,2,1) - 10
+		,"T3ch=T(1,2,1)");
+  test_for_zero(t3ch_1(1,2,2) - 10
+		,"T3ch=T(1,2,2)");
+  test_for_zero(t3ch_1(2,0,0) - 10
+		,"T3ch=T(2,0,0)");
+  test_for_zero(t3ch_1(2,0,1) - 10
+		,"T3ch=T(2,0,1)");
+  test_for_zero(t3ch_1(2,0,2) - 10
+		,"T3ch=T(2,0,2)");
+  test_for_zero(t3ch_1(2,1,0) - 10
+		,"T3ch=T(2,1,0)");
+  test_for_zero(t3ch_1(2,1,1) - 10
+		,"T3ch=T(2,1,1)");
+  test_for_zero(t3ch_1(2,1,2) - 10
+		,"T3ch=T(2,1,2)");
+  test_for_zero(t3ch_1(2,2,0) - 10
+		,"T3ch=T(2,2,0)");
+  test_for_zero(t3ch_1(2,2,1) - 10
+		,"T3ch=T(2,2,1)");
+  test_for_zero(t3ch_1(2,2,2) - 10
+		,"T3ch=T(2,2,2)");
+
+  t3ch_1(i,j,k)=t3dg_2(j,k,i);
+  test_for_zero(t3ch_1(0,0,0) - t3dg_2(0,0,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,0,0)");
+  test_for_zero(t3ch_1(0,0,1) - t3dg_2(0,1,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,0,1)");
+  test_for_zero(t3ch_1(0,0,2) - t3dg_2(0,2,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,0,2)");
+  test_for_zero(t3ch_1(0,1,0) - t3dg_2(1,0,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,1,0)");
+  test_for_zero(t3ch_1(0,1,1) - t3dg_2(1,1,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,1,1)");
+  test_for_zero(t3ch_1(0,1,2) - t3dg_2(1,2,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,1,2)");
+  test_for_zero(t3ch_1(0,2,0) - t3dg_2(2,0,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,2,0)");
+  test_for_zero(t3ch_1(0,2,1) - t3dg_2(2,1,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,2,1)");
+  test_for_zero(t3ch_1(0,2,2) - t3dg_2(2,2,0)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(0,2,2)");
+  test_for_zero(t3ch_1(1,0,0) - t3dg_2(0,0,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,0,0)");
+  test_for_zero(t3ch_1(1,0,1) - t3dg_2(0,1,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,0,1)");
+  test_for_zero(t3ch_1(1,0,2) - t3dg_2(0,2,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,0,2)");
+  test_for_zero(t3ch_1(1,1,0) - t3dg_2(1,0,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,1,0)");
+  test_for_zero(t3ch_1(1,1,1) - t3dg_2(1,1,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,1,1)");
+  test_for_zero(t3ch_1(1,1,2) - t3dg_2(1,2,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,1,2)");
+  test_for_zero(t3ch_1(1,2,0) - t3dg_2(2,0,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,2,0)");
+  test_for_zero(t3ch_1(1,2,1) - t3dg_2(2,1,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,2,1)");
+  test_for_zero(t3ch_1(1,2,2) - t3dg_2(2,2,1)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(1,2,2)");
+  test_for_zero(t3ch_1(2,0,0) - t3dg_2(0,0,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,0,0)");
+  test_for_zero(t3ch_1(2,0,1) - t3dg_2(0,1,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,0,1)");
+  test_for_zero(t3ch_1(2,0,2) - t3dg_2(0,2,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,0,2)");
+  test_for_zero(t3ch_1(2,1,0) - t3dg_2(1,0,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,1,0)");
+  test_for_zero(t3ch_1(2,1,1) - t3dg_2(1,1,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,1,1)");
+  test_for_zero(t3ch_1(2,1,2) - t3dg_2(1,2,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,1,2)");
+  test_for_zero(t3ch_1(2,2,0) - t3dg_2(2,0,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,2,0)");
+  test_for_zero(t3ch_1(2,2,1) - t3dg_2(2,1,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,2,1)");
+  test_for_zero(t3ch_1(2,2,2) - t3dg_2(2,2,2)
+		,"T3ch(i,j,k)=T3dg(j,k,i)(2,2,2)");
+
+  t3ch_1(i,j,k)=t3ch_2(i,j,k);
+  test_for_zero(t3ch_1(0,0,0) - t3ch_2(0,0,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,0,0)");
+  test_for_zero(t3ch_1(0,0,1) - t3ch_2(0,0,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,0,1)");
+  test_for_zero(t3ch_1(0,0,2) - t3ch_2(0,0,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,0,2)");
+  test_for_zero(t3ch_1(0,1,0) - t3ch_2(0,1,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,1,0)");
+  test_for_zero(t3ch_1(0,1,1) - t3ch_2(0,1,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,1,1)");
+  test_for_zero(t3ch_1(0,1,2) - t3ch_2(0,1,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,1,2)");
+  test_for_zero(t3ch_1(0,2,0) - t3ch_2(0,2,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,2,0)");
+  test_for_zero(t3ch_1(0,2,1) - t3ch_2(0,2,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,2,1)");
+  test_for_zero(t3ch_1(0,2,2) - t3ch_2(0,2,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(0,2,2)");
+  test_for_zero(t3ch_1(1,0,0) - t3ch_2(1,0,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,0,0)");
+  test_for_zero(t3ch_1(1,0,1) - t3ch_2(1,0,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,0,1)");
+  test_for_zero(t3ch_1(1,0,2) - t3ch_2(1,0,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,0,2)");
+  test_for_zero(t3ch_1(1,1,0) - t3ch_2(1,1,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,1,0)");
+  test_for_zero(t3ch_1(1,1,1) - t3ch_2(1,1,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,1,1)");
+  test_for_zero(t3ch_1(1,1,2) - t3ch_2(1,1,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,1,2)");
+  test_for_zero(t3ch_1(1,2,0) - t3ch_2(1,2,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,2,0)");
+  test_for_zero(t3ch_1(1,2,1) - t3ch_2(1,2,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,2,1)");
+  test_for_zero(t3ch_1(1,2,2) - t3ch_2(1,2,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(1,2,2)");
+  test_for_zero(t3ch_1(2,0,0) - t3ch_2(2,0,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,0,0)");
+  test_for_zero(t3ch_1(2,0,1) - t3ch_2(2,0,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,0,1)");
+  test_for_zero(t3ch_1(2,0,2) - t3ch_2(2,0,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,0,2)");
+  test_for_zero(t3ch_1(2,1,0) - t3ch_2(2,1,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,1,0)");
+  test_for_zero(t3ch_1(2,1,1) - t3ch_2(2,1,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,1,1)");
+  test_for_zero(t3ch_1(2,1,2) - t3ch_2(2,1,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,1,2)");
+  test_for_zero(t3ch_1(2,2,0) - t3ch_2(2,2,0)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,2,0)");
+  test_for_zero(t3ch_1(2,2,1) - t3ch_2(2,2,1)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,2,1)");
+  test_for_zero(t3ch_1(2,2,2) - t3ch_2(2,2,2)
+		,"T3ch(i,j,k)=T3ch(i,j,k)(2,2,2)");
+
+  t1_1(i)=t3ch_1(i,j,j);
+  test_for_zero(t1_1(0) - (t3ch_1(0,0,0) + t3ch_1(0,1,1) + t3ch_1(0,2,2))
+		,"t3ch(i,j,j)(0)");
+  test_for_zero(t1_1(1) - (t3ch_1(1,0,0) + t3ch_1(1,1,1) + t3ch_1(1,2,2))
+		,"t3ch(i,j,j)(1)");
+  test_for_zero(t1_1(2) - (t3ch_1(2,0,0) + t3ch_1(2,1,1) + t3ch_1(2,2,2))
+		,"t3ch(i,j,j)(2)");
+  t1_1(i)=t3ch_1(j,i,j);
+  test_for_zero(t1_1(0) - (t3ch_1(0,0,0) + t3ch_1(1,0,1) + t3ch_1(2,0,2))
+		,"t3ch(j,i,j)(0)");
+  test_for_zero(t1_1(1) - (t3ch_1(0,1,0) + t3ch_1(1,1,1) + t3ch_1(2,1,2))
+		,"t3ch(j,i,j)(1)");
+  test_for_zero(t1_1(2) - (t3ch_1(0,2,0) + t3ch_1(1,2,1) + t3ch_1(2,2,2))
+		,"t3ch(j,i,j)(2)");
+  t1_1(i)=t3ch_1(j,j,i);
+  test_for_zero(t1_1(0) - (t3ch_1(0,0,0) + t3ch_1(1,1,0) + t3ch_1(2,2,0))
+		,"t3ch(j,j,i)(0)");
+  test_for_zero(t1_1(1) - (t3ch_1(0,0,1) + t3ch_1(1,1,1) + t3ch_1(2,2,1))
+		,"t3ch(j,j,i)(1)");
+  test_for_zero(t1_1(2) - (t3ch_1(0,0,2) + t3ch_1(1,1,2) + t3ch_1(2,2,2))
+		,"t3ch(j,j,i)(2)");
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T3ch.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T3ch.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+extern
+void test_T3ch(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T3dg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T3dg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+extern
+void test_T3dg(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	       Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	       Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	       const Tensor2<double,3,3> &t2_3,
+	       Tensor2_symmetric<double,3> &t2s_1,
+	       const Tensor2_symmetric<double,3> &t2s_2,
+	       const Tensor2_symmetric<double,3> &t2s_3,
+	       Tensor3_dg<double,3,3> &t3dg_1,
+	       const Tensor3_dg<double,3,3> &t3dg_2,
+	       const Tensor3_dg<double,3,3> &t3dg_3,
+	       Tensor3_christof<double,3,3> &t3ch_1,
+	       const Tensor3_christof<double,3,3> &t3ch_2,
+	       const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T4R.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T4R.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,559 @@
+#include <iostream>
+#include "../../FTensor.h"
+#include "test_for_zero.h"
+using namespace FTensor;
+using namespace std;
+
+void test_T4R(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3,
+	      Tensor3_dg<double,3,3> &t3dg_1,
+	      const Tensor3_dg<double,3,3> &t3dg_2,
+	      const Tensor3_dg<double,3,3> &t3dg_3,
+	      Tensor3_antisymmetric<double,3,3> &t3as_1,
+	      const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	      const Tensor3_antisymmetric<double,3,3> &t3as_3)
+{
+  Index<'i',3> i;
+  Index<'j',3> j;
+  Index<'k',3> k;
+  Index<'l',3> l;
+  Index<'m',3> m;
+  Index<'n',3> n;
+
+  Number<0> N0;
+  Number<1> N1;
+  Number<2> N2;
+
+  Tensor4_Riemann<double,3> t4R_1, t4R_2, t4R_3;
+
+  cout << "T4_Riemann" << endl;
+
+  Tensor2_symmetric<double,3> delta_3(3,0,0,3,0,3), delta_5(5,0,0,5,0,5),
+    delta_2(2,0,0,2,0,2), delta_7(7,0,0,7,0,7);
+
+  t4R_1(i,j,k,l)=(delta_3(i,k)*delta_5(j,l) && delta_3(i,l)*delta_5(k,j));
+
+  test_for_zero(t4R_1(0,0,0,0) - (delta_3(0,0)*delta_5(0,0)-delta_3(0,0)*delta_5(0,0)),
+                "T4ddg && T4ddg (0,0,0,0)");
+  test_for_zero(t4R_1(0,0,0,1) - (delta_3(0,1)*delta_5(0,0)-delta_3(0,1)*delta_5(0,0)),
+                "T4ddg && T4ddg (0,0,0,1)");
+  test_for_zero(t4R_1(0,0,0,2) - (delta_3(0,2)*delta_5(0,0)-delta_3(0,2)*delta_5(0,0)),
+                "T4ddg && T4ddg (0,0,0,2)");
+  test_for_zero(t4R_1(0,0,1,0) - (delta_3(0,0)*delta_5(0,1)-delta_3(0,0)*delta_5(1,0)),
+                "T4ddg && T4ddg (0,0,1,0)");
+  test_for_zero(t4R_1(0,0,1,1) - (delta_3(0,1)*delta_5(0,1)-delta_3(0,1)*delta_5(1,0)),
+                "T4ddg && T4ddg (0,0,1,1)");
+  test_for_zero(t4R_1(0,0,1,2) - (delta_3(0,2)*delta_5(0,1)-delta_3(0,2)*delta_5(1,0)),
+                "T4ddg && T4ddg (0,0,1,2)");
+  test_for_zero(t4R_1(0,0,2,0) - (delta_3(0,0)*delta_5(0,2)-delta_3(0,0)*delta_5(2,0)),
+                "T4ddg && T4ddg (0,0,2,0)");
+  test_for_zero(t4R_1(0,0,2,1) - (delta_3(0,1)*delta_5(0,2)-delta_3(0,1)*delta_5(2,0)),
+                "T4ddg && T4ddg (0,0,2,1)");
+  test_for_zero(t4R_1(0,0,2,2) - (delta_3(0,2)*delta_5(0,2)-delta_3(0,2)*delta_5(2,0)),
+                "T4ddg && T4ddg (0,0,2,2)");
+  test_for_zero(t4R_1(0,1,0,0) - (delta_3(0,0)*delta_5(1,0)-delta_3(0,0)*delta_5(0,1)),
+                "T4ddg && T4ddg (0,1,0,0)");
+  test_for_zero(t4R_1(0,1,0,1) - (delta_3(0,0)*delta_5(1,1)-delta_3(0,1)*delta_5(0,1)),
+                "T4ddg && T4ddg (0,1,0,1)");
+  test_for_zero(t4R_1(0,1,0,2) - (delta_3(0,2)*delta_5(1,0)-delta_3(0,2)*delta_5(0,1)),
+                "T4ddg && T4ddg (0,1,0,2)");
+  test_for_zero(t4R_1(0,1,1,0) - (delta_3(0,0)*delta_5(1,1)-delta_3(0,0)*delta_5(1,1)),
+                "T4ddg && T4ddg (0,1,1,0)");
+  test_for_zero(t4R_1(0,1,1,1) - (delta_3(0,1)*delta_5(1,1)-delta_3(0,1)*delta_5(1,1)),
+                "T4ddg && T4ddg (0,1,1,1)");
+  test_for_zero(t4R_1(0,1,1,2) - (delta_3(0,2)*delta_5(1,1)-delta_3(0,2)*delta_5(1,1)),
+                "T4ddg && T4ddg (0,1,1,2)");
+  test_for_zero(t4R_1(0,1,2,0) - (delta_3(0,0)*delta_5(1,2)-delta_3(0,0)*delta_5(2,1)),
+                "T4ddg && T4ddg (0,1,2,0)");
+  test_for_zero(t4R_1(0,1,2,1) - (delta_3(0,1)*delta_5(1,2)-delta_3(0,1)*delta_5(2,1)),
+                "T4ddg && T4ddg (0,1,2,1)");
+  test_for_zero(t4R_1(0,1,2,2) - (delta_3(0,2)*delta_5(1,2)-delta_3(0,2)*delta_5(2,1)),
+                "T4ddg && T4ddg (0,1,2,2)");
+  test_for_zero(t4R_1(0,2,0,0) - (delta_3(0,0)*delta_5(2,0)-delta_3(0,0)*delta_5(0,2)),
+                "T4ddg && T4ddg (0,2,0,0)");
+  test_for_zero(t4R_1(0,2,0,1) - (delta_3(0,1)*delta_5(2,0)-delta_3(0,1)*delta_5(0,2)),
+                "T4ddg && T4ddg (0,2,0,1)");
+  test_for_zero(t4R_1(0,2,0,2) - (delta_3(0,0)*delta_5(2,2)-delta_3(0,2)*delta_5(0,2)),
+                "T4ddg && T4ddg (0,2,0,2)");
+  test_for_zero(t4R_1(0,2,1,0) - (delta_3(0,0)*delta_5(2,1)-delta_3(0,0)*delta_5(1,2)),
+                "T4ddg && T4ddg (0,2,1,0)");
+  test_for_zero(t4R_1(0,2,1,1) - (delta_3(0,1)*delta_5(2,1)-delta_3(0,1)*delta_5(1,2)),
+                "T4ddg && T4ddg (0,2,1,1)");
+  test_for_zero(t4R_1(0,2,1,2) - (delta_3(0,2)*delta_5(2,1)-delta_3(0,2)*delta_5(1,2)),
+                "T4ddg && T4ddg (0,2,1,2)");
+  test_for_zero(t4R_1(0,2,2,0) - (delta_3(0,0)*delta_5(2,2)-delta_3(0,0)*delta_5(2,2)),
+                "T4ddg && T4ddg (0,2,2,0)");
+  test_for_zero(t4R_1(0,2,2,1) - (delta_3(0,1)*delta_5(2,2)-delta_3(0,1)*delta_5(2,2)),
+                "T4ddg && T4ddg (0,2,2,1)");
+  test_for_zero(t4R_1(0,2,2,2) - (delta_3(0,2)*delta_5(2,2)-delta_3(0,2)*delta_5(2,2)),
+                "T4ddg && T4ddg (0,2,2,2)");
+  test_for_zero(t4R_1(1,0,0,0) - (delta_3(1,0)*delta_5(0,0)-delta_3(1,0)*delta_5(0,0)),
+                "T4ddg && T4ddg (1,0,0,0)");
+  test_for_zero(t4R_1(1,0,0,1) - (delta_3(1,1)*delta_5(0,0)-delta_3(1,1)*delta_5(0,0)),
+                "T4ddg && T4ddg (1,0,0,1)");
+  test_for_zero(t4R_1(1,0,0,2) - (delta_3(1,2)*delta_5(0,0)-delta_3(1,2)*delta_5(0,0)),
+                "T4ddg && T4ddg (1,0,0,2)");
+  test_for_zero(t4R_1(1,0,1,0) - (delta_3(1,0)*delta_5(0,1)-delta_3(1,0)*delta_5(1,0)),
+                "T4ddg && T4ddg (1,0,1,0)");
+  test_for_zero(t4R_1(1,0,1,1) - (delta_3(1,1)*delta_5(0,1)-delta_3(1,1)*delta_5(1,0)),
+                "T4ddg && T4ddg (1,0,1,1)");
+  test_for_zero(t4R_1(1,0,1,2) - (delta_3(1,2)*delta_5(0,1)-delta_3(1,2)*delta_5(1,0)),
+                "T4ddg && T4ddg (1,0,1,2)");
+  test_for_zero(t4R_1(1,0,2,0) - (delta_3(1,0)*delta_5(0,2)-delta_3(1,0)*delta_5(2,0)),
+                "T4ddg && T4ddg (1,0,2,0)");
+  test_for_zero(t4R_1(1,0,2,1) - (delta_3(1,1)*delta_5(0,2)-delta_3(1,1)*delta_5(2,0)),
+                "T4ddg && T4ddg (1,0,2,1)");
+  test_for_zero(t4R_1(1,0,2,2) - (delta_3(1,2)*delta_5(0,2)-delta_3(1,2)*delta_5(2,0)),
+                "T4ddg && T4ddg (1,0,2,2)");
+  test_for_zero(t4R_1(1,1,0,0) - (delta_3(1,0)*delta_5(1,0)-delta_3(1,0)*delta_5(0,1)),
+                "T4ddg && T4ddg (1,1,0,0)");
+  test_for_zero(t4R_1(1,1,0,1) - (delta_3(1,1)*delta_5(1,0)-delta_3(1,1)*delta_5(0,1)),
+                "T4ddg && T4ddg (1,1,0,1)");
+  test_for_zero(t4R_1(1,1,0,2) - (delta_3(1,2)*delta_5(1,0)-delta_3(1,2)*delta_5(0,1)),
+                "T4ddg && T4ddg (1,1,0,2)");
+  test_for_zero(t4R_1(1,1,1,0) - (delta_3(1,0)*delta_5(1,1)-delta_3(1,0)*delta_5(1,1)),
+                "T4ddg && T4ddg (1,1,1,0)");
+  test_for_zero(t4R_1(1,1,1,1) - (delta_3(1,1)*delta_5(1,1)-delta_3(1,1)*delta_5(1,1)),
+                "T4ddg && T4ddg (1,1,1,1)");
+  test_for_zero(t4R_1(1,1,1,2) - (delta_3(1,2)*delta_5(1,1)-delta_3(1,2)*delta_5(1,1)),
+                "T4ddg && T4ddg (1,1,1,2)");
+  test_for_zero(t4R_1(1,1,2,0) - (delta_3(1,0)*delta_5(1,2)-delta_3(1,0)*delta_5(2,1)),
+                "T4ddg && T4ddg (1,1,2,0)");
+  test_for_zero(t4R_1(1,1,2,1) - (delta_3(1,1)*delta_5(1,2)-delta_3(1,1)*delta_5(2,1)),
+                "T4ddg && T4ddg (1,1,2,1)");
+  test_for_zero(t4R_1(1,1,2,2) - (delta_3(1,2)*delta_5(1,2)-delta_3(1,2)*delta_5(2,1)),
+                "T4ddg && T4ddg (1,1,2,2)");
+  test_for_zero(t4R_1(1,2,0,0) - (delta_3(1,0)*delta_5(2,0)-delta_3(1,0)*delta_5(0,2)),
+                "T4ddg && T4ddg (1,2,0,0)");
+  test_for_zero(t4R_1(1,2,0,1) - (delta_3(1,1)*delta_5(2,0)-delta_3(1,1)*delta_5(0,2)),
+                "T4ddg && T4ddg (1,2,0,1)");
+  test_for_zero(t4R_1(1,2,0,2) - (delta_3(1,2)*delta_5(2,0)-delta_3(1,2)*delta_5(0,2)),
+                "T4ddg && T4ddg (1,2,0,2)");
+  test_for_zero(t4R_1(1,2,1,0) - (delta_3(1,0)*delta_5(2,1)-delta_3(1,0)*delta_5(1,2)),
+                "T4ddg && T4ddg (1,2,1,0)");
+  test_for_zero(t4R_1(1,2,1,1) - (delta_3(1,1)*delta_5(2,1)-delta_3(1,1)*delta_5(1,2)),
+                "T4ddg && T4ddg (1,2,1,1)");
+  test_for_zero(t4R_1(1,2,1,2) - (delta_3(1,1)*delta_5(2,2)-delta_3(1,2)*delta_5(1,2)),
+                "T4ddg && T4ddg (1,2,1,2)");
+  test_for_zero(t4R_1(1,2,2,0) - (delta_3(1,0)*delta_5(2,2)-delta_3(1,0)*delta_5(2,2)),
+                "T4ddg && T4ddg (1,2,2,0)");
+  test_for_zero(t4R_1(1,2,2,1) - (delta_3(1,1)*delta_5(2,2)-delta_3(1,1)*delta_5(2,2)),
+                "T4ddg && T4ddg (1,2,2,1)");
+  test_for_zero(t4R_1(1,2,2,2) - (delta_3(1,2)*delta_5(2,2)-delta_3(1,2)*delta_5(2,2)),
+                "T4ddg && T4ddg (1,2,2,2)");
+  test_for_zero(t4R_1(2,0,0,0) - (delta_3(2,0)*delta_5(0,0)-delta_3(2,0)*delta_5(0,0)),
+                "T4ddg && T4ddg (2,0,0,0)");
+  test_for_zero(t4R_1(2,0,0,1) - (delta_3(2,1)*delta_5(0,0)-delta_3(2,1)*delta_5(0,0)),
+                "T4ddg && T4ddg (2,0,0,1)");
+  test_for_zero(t4R_1(2,0,0,2) - (delta_3(2,2)*delta_5(0,0)-delta_3(2,2)*delta_5(0,0)),
+                "T4ddg && T4ddg (2,0,0,2)");
+  test_for_zero(t4R_1(2,0,1,0) - (delta_3(2,0)*delta_5(0,1)-delta_3(2,0)*delta_5(1,0)),
+                "T4ddg && T4ddg (2,0,1,0)");
+  test_for_zero(t4R_1(2,0,1,1) - (delta_3(2,1)*delta_5(0,1)-delta_3(2,1)*delta_5(1,0)),
+                "T4ddg && T4ddg (2,0,1,1)");
+  test_for_zero(t4R_1(2,0,1,2) - (delta_3(2,2)*delta_5(0,1)-delta_3(2,2)*delta_5(1,0)),
+                "T4ddg && T4ddg (2,0,1,2)");
+  test_for_zero(t4R_1(2,0,2,0) - (delta_3(2,0)*delta_5(0,2)-delta_3(2,0)*delta_5(2,0)),
+                "T4ddg && T4ddg (2,0,2,0)");
+  test_for_zero(t4R_1(2,0,2,1) - (delta_3(2,1)*delta_5(0,2)-delta_3(2,1)*delta_5(2,0)),
+                "T4ddg && T4ddg (2,0,2,1)");
+  test_for_zero(t4R_1(2,0,2,2) - (delta_3(2,2)*delta_5(0,2)-delta_3(2,2)*delta_5(2,0)),
+                "T4ddg && T4ddg (2,0,2,2)");
+  test_for_zero(t4R_1(2,1,0,0) - (delta_3(2,0)*delta_5(1,0)-delta_3(2,0)*delta_5(0,1)),
+                "T4ddg && T4ddg (2,1,0,0)");
+  test_for_zero(t4R_1(2,1,0,1) - (delta_3(2,1)*delta_5(1,0)-delta_3(2,1)*delta_5(0,1)),
+                "T4ddg && T4ddg (2,1,0,1)");
+  test_for_zero(t4R_1(2,1,0,2) - (delta_3(2,2)*delta_5(1,0)-delta_3(2,2)*delta_5(0,1)),
+                "T4ddg && T4ddg (2,1,0,2)");
+  test_for_zero(t4R_1(2,1,1,0) - (delta_3(2,0)*delta_5(1,1)-delta_3(2,0)*delta_5(1,1)),
+                "T4ddg && T4ddg (2,1,1,0)");
+  test_for_zero(t4R_1(2,1,1,1) - (delta_3(2,1)*delta_5(1,1)-delta_3(2,1)*delta_5(1,1)),
+                "T4ddg && T4ddg (2,1,1,1)");
+  test_for_zero(t4R_1(2,1,1,2) - (delta_3(2,2)*delta_5(1,1)-delta_3(2,2)*delta_5(1,1)),
+                "T4ddg && T4ddg (2,1,1,2)");
+  test_for_zero(t4R_1(2,1,2,0) - (delta_3(2,0)*delta_5(1,2)-delta_3(2,0)*delta_5(2,1)),
+                "T4ddg && T4ddg (2,1,2,0)");
+  test_for_zero(t4R_1(2,1,2,1) - (delta_3(2,1)*delta_5(1,2)-delta_3(2,1)*delta_5(2,1)),
+                "T4ddg && T4ddg (2,1,2,1)");
+  test_for_zero(t4R_1(2,1,2,2) - (delta_3(2,2)*delta_5(1,2)-delta_3(2,2)*delta_5(2,1)),
+                "T4ddg && T4ddg (2,1,2,2)");
+  test_for_zero(t4R_1(2,2,0,0) - (delta_3(2,0)*delta_5(2,0)-delta_3(2,0)*delta_5(0,2)),
+                "T4ddg && T4ddg (2,2,0,0)");
+  test_for_zero(t4R_1(2,2,0,1) - (delta_3(2,1)*delta_5(2,0)-delta_3(2,1)*delta_5(0,2)),
+                "T4ddg && T4ddg (2,2,0,1)");
+  test_for_zero(t4R_1(2,2,0,2) - (delta_3(2,2)*delta_5(2,0)-delta_3(2,2)*delta_5(0,2)),
+                "T4ddg && T4ddg (2,2,0,2)");
+  test_for_zero(t4R_1(2,2,1,0) - (delta_3(2,0)*delta_5(2,1)-delta_3(2,0)*delta_5(1,2)),
+                "T4ddg && T4ddg (2,2,1,0)");
+  test_for_zero(t4R_1(2,2,1,1) - (delta_3(2,1)*delta_5(2,1)-delta_3(2,1)*delta_5(1,2)),
+                "T4ddg && T4ddg (2,2,1,1)");
+  test_for_zero(t4R_1(2,2,1,2) - (delta_3(2,2)*delta_5(2,1)-delta_3(2,2)*delta_5(1,2)),
+                "T4ddg && T4ddg (2,2,1,2)");
+  test_for_zero(t4R_1(2,2,2,0) - (delta_3(2,0)*delta_5(2,2)-delta_3(2,0)*delta_5(2,2)),
+                "T4ddg && T4ddg (2,2,2,0)");
+  test_for_zero(t4R_1(2,2,2,1) - (delta_3(2,1)*delta_5(2,2)-delta_3(2,1)*delta_5(2,2)),
+                "T4ddg && T4ddg (2,2,2,1)");
+  test_for_zero(t4R_1(2,2,2,2) - (delta_3(2,2)*delta_5(2,2)-delta_3(2,2)*delta_5(2,2)),
+                "T4ddg && T4ddg (2,2,2,2)");
+
+
+  t4R_2(i,j,k,l)=(delta_2(i,k)*delta_7(j,l) && delta_2(i,l)*delta_7(k,j));
+
+  t4R_3(i,j,k,l)=t4R_1(i,j,k,l)+t4R_2(i,j,k,l);
+  test_for_zero(t4R_3(0,0,0,0) - (t4R_1(0,0,0,0)+t4R_2(0,0,0,0)),
+                "T4R + T4R (0,0,0,0)");
+  test_for_zero(t4R_3(0,0,0,1) - (t4R_1(0,0,0,1)+t4R_2(0,0,0,1)),
+                "T4R + T4R (0,0,0,1)");
+  test_for_zero(t4R_3(0,0,0,2) - (t4R_1(0,0,0,2)+t4R_2(0,0,0,2)),
+                "T4R + T4R (0,0,0,2)");
+  test_for_zero(t4R_3(0,0,1,0) - (t4R_1(0,0,1,0)+t4R_2(0,0,1,0)),
+                "T4R + T4R (0,0,1,0)");
+  test_for_zero(t4R_3(0,0,1,1) - (t4R_1(0,0,1,1)+t4R_2(0,0,1,1)),
+                "T4R + T4R (0,0,1,1)");
+  test_for_zero(t4R_3(0,0,1,2) - (t4R_1(0,0,1,2)+t4R_2(0,0,1,2)),
+                "T4R + T4R (0,0,1,2)");
+  test_for_zero(t4R_3(0,0,2,0) - (t4R_1(0,0,2,0)+t4R_2(0,0,2,0)),
+                "T4R + T4R (0,0,2,0)");
+  test_for_zero(t4R_3(0,0,2,1) - (t4R_1(0,0,2,1)+t4R_2(0,0,2,1)),
+                "T4R + T4R (0,0,2,1)");
+  test_for_zero(t4R_3(0,0,2,2) - (t4R_1(0,0,2,2)+t4R_2(0,0,2,2)),
+                "T4R + T4R (0,0,2,2)");
+  test_for_zero(t4R_3(0,1,0,0) - (t4R_1(0,1,0,0)+t4R_2(0,1,0,0)),
+                "T4R + T4R (0,1,0,0)");
+  test_for_zero(t4R_3(0,1,0,1) - (t4R_1(0,1,0,1)+t4R_2(0,1,0,1)),
+                "T4R + T4R (0,1,0,1)");
+  test_for_zero(t4R_3(0,1,0,2) - (t4R_1(0,1,0,2)+t4R_2(0,1,0,2)),
+                "T4R + T4R (0,1,0,2)");
+  test_for_zero(t4R_3(0,1,1,0) - (t4R_1(0,1,1,0)+t4R_2(0,1,1,0)),
+                "T4R + T4R (0,1,1,0)");
+  test_for_zero(t4R_3(0,1,1,1) - (t4R_1(0,1,1,1)+t4R_2(0,1,1,1)),
+                "T4R + T4R (0,1,1,1)");
+  test_for_zero(t4R_3(0,1,1,2) - (t4R_1(0,1,1,2)+t4R_2(0,1,1,2)),
+                "T4R + T4R (0,1,1,2)");
+  test_for_zero(t4R_3(0,1,2,0) - (t4R_1(0,1,2,0)+t4R_2(0,1,2,0)),
+                "T4R + T4R (0,1,2,0)");
+  test_for_zero(t4R_3(0,1,2,1) - (t4R_1(0,1,2,1)+t4R_2(0,1,2,1)),
+                "T4R + T4R (0,1,2,1)");
+  test_for_zero(t4R_3(0,1,2,2) - (t4R_1(0,1,2,2)+t4R_2(0,1,2,2)),
+                "T4R + T4R (0,1,2,2)");
+  test_for_zero(t4R_3(0,2,0,0) - (t4R_1(0,2,0,0)+t4R_2(0,2,0,0)),
+                "T4R + T4R (0,2,0,0)");
+  test_for_zero(t4R_3(0,2,0,1) - (t4R_1(0,2,0,1)+t4R_2(0,2,0,1)),
+                "T4R + T4R (0,2,0,1)");
+  test_for_zero(t4R_3(0,2,0,2) - (t4R_1(0,2,0,2)+t4R_2(0,2,0,2)),
+                "T4R + T4R (0,2,0,2)");
+  test_for_zero(t4R_3(0,2,1,0) - (t4R_1(0,2,1,0)+t4R_2(0,2,1,0)),
+                "T4R + T4R (0,2,1,0)");
+  test_for_zero(t4R_3(0,2,1,1) - (t4R_1(0,2,1,1)+t4R_2(0,2,1,1)),
+                "T4R + T4R (0,2,1,1)");
+  test_for_zero(t4R_3(0,2,1,2) - (t4R_1(0,2,1,2)+t4R_2(0,2,1,2)),
+                "T4R + T4R (0,2,1,2)");
+  test_for_zero(t4R_3(0,2,2,0) - (t4R_1(0,2,2,0)+t4R_2(0,2,2,0)),
+                "T4R + T4R (0,2,2,0)");
+  test_for_zero(t4R_3(0,2,2,1) - (t4R_1(0,2,2,1)+t4R_2(0,2,2,1)),
+                "T4R + T4R (0,2,2,1)");
+  test_for_zero(t4R_3(0,2,2,2) - (t4R_1(0,2,2,2)+t4R_2(0,2,2,2)),
+                "T4R + T4R (0,2,2,2)");
+  test_for_zero(t4R_3(1,0,0,0) - (t4R_1(1,0,0,0)+t4R_2(1,0,0,0)),
+                "T4R + T4R (1,0,0,0)");
+  test_for_zero(t4R_3(1,0,0,1) - (t4R_1(1,0,0,1)+t4R_2(1,0,0,1)),
+                "T4R + T4R (1,0,0,1)");
+  test_for_zero(t4R_3(1,0,0,2) - (t4R_1(1,0,0,2)+t4R_2(1,0,0,2)),
+                "T4R + T4R (1,0,0,2)");
+  test_for_zero(t4R_3(1,0,1,0) - (t4R_1(1,0,1,0)+t4R_2(1,0,1,0)),
+                "T4R + T4R (1,0,1,0)");
+  test_for_zero(t4R_3(1,0,1,1) - (t4R_1(1,0,1,1)+t4R_2(1,0,1,1)),
+                "T4R + T4R (1,0,1,1)");
+  test_for_zero(t4R_3(1,0,1,2) - (t4R_1(1,0,1,2)+t4R_2(1,0,1,2)),
+                "T4R + T4R (1,0,1,2)");
+  test_for_zero(t4R_3(1,0,2,0) - (t4R_1(1,0,2,0)+t4R_2(1,0,2,0)),
+                "T4R + T4R (1,0,2,0)");
+  test_for_zero(t4R_3(1,0,2,1) - (t4R_1(1,0,2,1)+t4R_2(1,0,2,1)),
+                "T4R + T4R (1,0,2,1)");
+  test_for_zero(t4R_3(1,0,2,2) - (t4R_1(1,0,2,2)+t4R_2(1,0,2,2)),
+                "T4R + T4R (1,0,2,2)");
+  test_for_zero(t4R_3(1,1,0,0) - (t4R_1(1,1,0,0)+t4R_2(1,1,0,0)),
+                "T4R + T4R (1,1,0,0)");
+  test_for_zero(t4R_3(1,1,0,1) - (t4R_1(1,1,0,1)+t4R_2(1,1,0,1)),
+                "T4R + T4R (1,1,0,1)");
+  test_for_zero(t4R_3(1,1,0,2) - (t4R_1(1,1,0,2)+t4R_2(1,1,0,2)),
+                "T4R + T4R (1,1,0,2)");
+  test_for_zero(t4R_3(1,1,1,0) - (t4R_1(1,1,1,0)+t4R_2(1,1,1,0)),
+                "T4R + T4R (1,1,1,0)");
+  test_for_zero(t4R_3(1,1,1,1) - (t4R_1(1,1,1,1)+t4R_2(1,1,1,1)),
+                "T4R + T4R (1,1,1,1)");
+  test_for_zero(t4R_3(1,1,1,2) - (t4R_1(1,1,1,2)+t4R_2(1,1,1,2)),
+                "T4R + T4R (1,1,1,2)");
+  test_for_zero(t4R_3(1,1,2,0) - (t4R_1(1,1,2,0)+t4R_2(1,1,2,0)),
+                "T4R + T4R (1,1,2,0)");
+  test_for_zero(t4R_3(1,1,2,1) - (t4R_1(1,1,2,1)+t4R_2(1,1,2,1)),
+                "T4R + T4R (1,1,2,1)");
+  test_for_zero(t4R_3(1,1,2,2) - (t4R_1(1,1,2,2)+t4R_2(1,1,2,2)),
+                "T4R + T4R (1,1,2,2)");
+  test_for_zero(t4R_3(1,2,0,0) - (t4R_1(1,2,0,0)+t4R_2(1,2,0,0)),
+                "T4R + T4R (1,2,0,0)");
+  test_for_zero(t4R_3(1,2,0,1) - (t4R_1(1,2,0,1)+t4R_2(1,2,0,1)),
+                "T4R + T4R (1,2,0,1)");
+  test_for_zero(t4R_3(1,2,0,2) - (t4R_1(1,2,0,2)+t4R_2(1,2,0,2)),
+                "T4R + T4R (1,2,0,2)");
+  test_for_zero(t4R_3(1,2,1,0) - (t4R_1(1,2,1,0)+t4R_2(1,2,1,0)),
+                "T4R + T4R (1,2,1,0)");
+  test_for_zero(t4R_3(1,2,1,1) - (t4R_1(1,2,1,1)+t4R_2(1,2,1,1)),
+                "T4R + T4R (1,2,1,1)");
+  test_for_zero(t4R_3(1,2,1,2) - (t4R_1(1,2,1,2)+t4R_2(1,2,1,2)),
+                "T4R + T4R (1,2,1,2)");
+  test_for_zero(t4R_3(1,2,2,0) - (t4R_1(1,2,2,0)+t4R_2(1,2,2,0)),
+                "T4R + T4R (1,2,2,0)");
+  test_for_zero(t4R_3(1,2,2,1) - (t4R_1(1,2,2,1)+t4R_2(1,2,2,1)),
+                "T4R + T4R (1,2,2,1)");
+  test_for_zero(t4R_3(1,2,2,2) - (t4R_1(1,2,2,2)+t4R_2(1,2,2,2)),
+                "T4R + T4R (1,2,2,2)");
+  test_for_zero(t4R_3(2,0,0,0) - (t4R_1(2,0,0,0)+t4R_2(2,0,0,0)),
+                "T4R + T4R (2,0,0,0)");
+  test_for_zero(t4R_3(2,0,0,1) - (t4R_1(2,0,0,1)+t4R_2(2,0,0,1)),
+                "T4R + T4R (2,0,0,1)");
+  test_for_zero(t4R_3(2,0,0,2) - (t4R_1(2,0,0,2)+t4R_2(2,0,0,2)),
+                "T4R + T4R (2,0,0,2)");
+  test_for_zero(t4R_3(2,0,1,0) - (t4R_1(2,0,1,0)+t4R_2(2,0,1,0)),
+                "T4R + T4R (2,0,1,0)");
+  test_for_zero(t4R_3(2,0,1,1) - (t4R_1(2,0,1,1)+t4R_2(2,0,1,1)),
+                "T4R + T4R (2,0,1,1)");
+  test_for_zero(t4R_3(2,0,1,2) - (t4R_1(2,0,1,2)+t4R_2(2,0,1,2)),
+                "T4R + T4R (2,0,1,2)");
+  test_for_zero(t4R_3(2,0,2,0) - (t4R_1(2,0,2,0)+t4R_2(2,0,2,0)),
+                "T4R + T4R (2,0,2,0)");
+  test_for_zero(t4R_3(2,0,2,1) - (t4R_1(2,0,2,1)+t4R_2(2,0,2,1)),
+                "T4R + T4R (2,0,2,1)");
+  test_for_zero(t4R_3(2,0,2,2) - (t4R_1(2,0,2,2)+t4R_2(2,0,2,2)),
+                "T4R + T4R (2,0,2,2)");
+  test_for_zero(t4R_3(2,1,0,0) - (t4R_1(2,1,0,0)+t4R_2(2,1,0,0)),
+                "T4R + T4R (2,1,0,0)");
+  test_for_zero(t4R_3(2,1,0,1) - (t4R_1(2,1,0,1)+t4R_2(2,1,0,1)),
+                "T4R + T4R (2,1,0,1)");
+  test_for_zero(t4R_3(2,1,0,2) - (t4R_1(2,1,0,2)+t4R_2(2,1,0,2)),
+                "T4R + T4R (2,1,0,2)");
+  test_for_zero(t4R_3(2,1,1,0) - (t4R_1(2,1,1,0)+t4R_2(2,1,1,0)),
+                "T4R + T4R (2,1,1,0)");
+  test_for_zero(t4R_3(2,1,1,1) - (t4R_1(2,1,1,1)+t4R_2(2,1,1,1)),
+                "T4R + T4R (2,1,1,1)");
+  test_for_zero(t4R_3(2,1,1,2) - (t4R_1(2,1,1,2)+t4R_2(2,1,1,2)),
+                "T4R + T4R (2,1,1,2)");
+  test_for_zero(t4R_3(2,1,2,0) - (t4R_1(2,1,2,0)+t4R_2(2,1,2,0)),
+                "T4R + T4R (2,1,2,0)");
+  test_for_zero(t4R_3(2,1,2,1) - (t4R_1(2,1,2,1)+t4R_2(2,1,2,1)),
+                "T4R + T4R (2,1,2,1)");
+  test_for_zero(t4R_3(2,1,2,2) - (t4R_1(2,1,2,2)+t4R_2(2,1,2,2)),
+                "T4R + T4R (2,1,2,2)");
+  test_for_zero(t4R_3(2,2,0,0) - (t4R_1(2,2,0,0)+t4R_2(2,2,0,0)),
+                "T4R + T4R (2,2,0,0)");
+  test_for_zero(t4R_3(2,2,0,1) - (t4R_1(2,2,0,1)+t4R_2(2,2,0,1)),
+                "T4R + T4R (2,2,0,1)");
+  test_for_zero(t4R_3(2,2,0,2) - (t4R_1(2,2,0,2)+t4R_2(2,2,0,2)),
+                "T4R + T4R (2,2,0,2)");
+  test_for_zero(t4R_3(2,2,1,0) - (t4R_1(2,2,1,0)+t4R_2(2,2,1,0)),
+                "T4R + T4R (2,2,1,0)");
+  test_for_zero(t4R_3(2,2,1,1) - (t4R_1(2,2,1,1)+t4R_2(2,2,1,1)),
+                "T4R + T4R (2,2,1,1)");
+  test_for_zero(t4R_3(2,2,1,2) - (t4R_1(2,2,1,2)+t4R_2(2,2,1,2)),
+                "T4R + T4R (2,2,1,2)");
+  test_for_zero(t4R_3(2,2,2,0) - (t4R_1(2,2,2,0)+t4R_2(2,2,2,0)),
+                "T4R + T4R (2,2,2,0)");
+  test_for_zero(t4R_3(2,2,2,1) - (t4R_1(2,2,2,1)+t4R_2(2,2,2,1)),
+                "T4R + T4R (2,2,2,1)");
+  test_for_zero(t4R_3(2,2,2,2) - (t4R_1(2,2,2,2)+t4R_2(2,2,2,2)),
+                "T4R + T4R (2,2,2,2)");
+
+  t4R_3(i,j,k,l)=t4R_1(i,j,k,l)-t4R_2(i,j,k,l);
+  test_for_zero(t4R_3(0,0,0,0) - (t4R_1(0,0,0,0)-t4R_2(0,0,0,0)),
+                "T4R - T4R (0,0,0,0)");
+  test_for_zero(t4R_3(0,0,0,1) - (t4R_1(0,0,0,1)-t4R_2(0,0,0,1)),
+                "T4R - T4R (0,0,0,1)");
+  test_for_zero(t4R_3(0,0,0,2) - (t4R_1(0,0,0,2)-t4R_2(0,0,0,2)),
+                "T4R - T4R (0,0,0,2)");
+  test_for_zero(t4R_3(0,0,1,0) - (t4R_1(0,0,1,0)-t4R_2(0,0,1,0)),
+                "T4R - T4R (0,0,1,0)");
+  test_for_zero(t4R_3(0,0,1,1) - (t4R_1(0,0,1,1)-t4R_2(0,0,1,1)),
+                "T4R - T4R (0,0,1,1)");
+  test_for_zero(t4R_3(0,0,1,2) - (t4R_1(0,0,1,2)-t4R_2(0,0,1,2)),
+                "T4R - T4R (0,0,1,2)");
+  test_for_zero(t4R_3(0,0,2,0) - (t4R_1(0,0,2,0)-t4R_2(0,0,2,0)),
+                "T4R - T4R (0,0,2,0)");
+  test_for_zero(t4R_3(0,0,2,1) - (t4R_1(0,0,2,1)-t4R_2(0,0,2,1)),
+                "T4R - T4R (0,0,2,1)");
+  test_for_zero(t4R_3(0,0,2,2) - (t4R_1(0,0,2,2)-t4R_2(0,0,2,2)),
+                "T4R - T4R (0,0,2,2)");
+  test_for_zero(t4R_3(0,1,0,0) - (t4R_1(0,1,0,0)-t4R_2(0,1,0,0)),
+                "T4R - T4R (0,1,0,0)");
+  test_for_zero(t4R_3(0,1,0,1) - (t4R_1(0,1,0,1)-t4R_2(0,1,0,1)),
+                "T4R - T4R (0,1,0,1)");
+  test_for_zero(t4R_3(0,1,0,2) - (t4R_1(0,1,0,2)-t4R_2(0,1,0,2)),
+                "T4R - T4R (0,1,0,2)");
+  test_for_zero(t4R_3(0,1,1,0) - (t4R_1(0,1,1,0)-t4R_2(0,1,1,0)),
+                "T4R - T4R (0,1,1,0)");
+  test_for_zero(t4R_3(0,1,1,1) - (t4R_1(0,1,1,1)-t4R_2(0,1,1,1)),
+                "T4R - T4R (0,1,1,1)");
+  test_for_zero(t4R_3(0,1,1,2) - (t4R_1(0,1,1,2)-t4R_2(0,1,1,2)),
+                "T4R - T4R (0,1,1,2)");
+  test_for_zero(t4R_3(0,1,2,0) - (t4R_1(0,1,2,0)-t4R_2(0,1,2,0)),
+                "T4R - T4R (0,1,2,0)");
+  test_for_zero(t4R_3(0,1,2,1) - (t4R_1(0,1,2,1)-t4R_2(0,1,2,1)),
+                "T4R - T4R (0,1,2,1)");
+  test_for_zero(t4R_3(0,1,2,2) - (t4R_1(0,1,2,2)-t4R_2(0,1,2,2)),
+                "T4R - T4R (0,1,2,2)");
+  test_for_zero(t4R_3(0,2,0,0) - (t4R_1(0,2,0,0)-t4R_2(0,2,0,0)),
+                "T4R - T4R (0,2,0,0)");
+  test_for_zero(t4R_3(0,2,0,1) - (t4R_1(0,2,0,1)-t4R_2(0,2,0,1)),
+                "T4R - T4R (0,2,0,1)");
+  test_for_zero(t4R_3(0,2,0,2) - (t4R_1(0,2,0,2)-t4R_2(0,2,0,2)),
+                "T4R - T4R (0,2,0,2)");
+  test_for_zero(t4R_3(0,2,1,0) - (t4R_1(0,2,1,0)-t4R_2(0,2,1,0)),
+                "T4R - T4R (0,2,1,0)");
+  test_for_zero(t4R_3(0,2,1,1) - (t4R_1(0,2,1,1)-t4R_2(0,2,1,1)),
+                "T4R - T4R (0,2,1,1)");
+  test_for_zero(t4R_3(0,2,1,2) - (t4R_1(0,2,1,2)-t4R_2(0,2,1,2)),
+                "T4R - T4R (0,2,1,2)");
+  test_for_zero(t4R_3(0,2,2,0) - (t4R_1(0,2,2,0)-t4R_2(0,2,2,0)),
+                "T4R - T4R (0,2,2,0)");
+  test_for_zero(t4R_3(0,2,2,1) - (t4R_1(0,2,2,1)-t4R_2(0,2,2,1)),
+                "T4R - T4R (0,2,2,1)");
+  test_for_zero(t4R_3(0,2,2,2) - (t4R_1(0,2,2,2)-t4R_2(0,2,2,2)),
+                "T4R - T4R (0,2,2,2)");
+  test_for_zero(t4R_3(1,0,0,0) - (t4R_1(1,0,0,0)-t4R_2(1,0,0,0)),
+                "T4R - T4R (1,0,0,0)");
+  test_for_zero(t4R_3(1,0,0,1) - (t4R_1(1,0,0,1)-t4R_2(1,0,0,1)),
+                "T4R - T4R (1,0,0,1)");
+  test_for_zero(t4R_3(1,0,0,2) - (t4R_1(1,0,0,2)-t4R_2(1,0,0,2)),
+                "T4R - T4R (1,0,0,2)");
+  test_for_zero(t4R_3(1,0,1,0) - (t4R_1(1,0,1,0)-t4R_2(1,0,1,0)),
+                "T4R - T4R (1,0,1,0)");
+  test_for_zero(t4R_3(1,0,1,1) - (t4R_1(1,0,1,1)-t4R_2(1,0,1,1)),
+                "T4R - T4R (1,0,1,1)");
+  test_for_zero(t4R_3(1,0,1,2) - (t4R_1(1,0,1,2)-t4R_2(1,0,1,2)),
+                "T4R - T4R (1,0,1,2)");
+  test_for_zero(t4R_3(1,0,2,0) - (t4R_1(1,0,2,0)-t4R_2(1,0,2,0)),
+                "T4R - T4R (1,0,2,0)");
+  test_for_zero(t4R_3(1,0,2,1) - (t4R_1(1,0,2,1)-t4R_2(1,0,2,1)),
+                "T4R - T4R (1,0,2,1)");
+  test_for_zero(t4R_3(1,0,2,2) - (t4R_1(1,0,2,2)-t4R_2(1,0,2,2)),
+                "T4R - T4R (1,0,2,2)");
+  test_for_zero(t4R_3(1,1,0,0) - (t4R_1(1,1,0,0)-t4R_2(1,1,0,0)),
+                "T4R - T4R (1,1,0,0)");
+  test_for_zero(t4R_3(1,1,0,1) - (t4R_1(1,1,0,1)-t4R_2(1,1,0,1)),
+                "T4R - T4R (1,1,0,1)");
+  test_for_zero(t4R_3(1,1,0,2) - (t4R_1(1,1,0,2)-t4R_2(1,1,0,2)),
+                "T4R - T4R (1,1,0,2)");
+  test_for_zero(t4R_3(1,1,1,0) - (t4R_1(1,1,1,0)-t4R_2(1,1,1,0)),
+                "T4R - T4R (1,1,1,0)");
+  test_for_zero(t4R_3(1,1,1,1) - (t4R_1(1,1,1,1)-t4R_2(1,1,1,1)),
+                "T4R - T4R (1,1,1,1)");
+  test_for_zero(t4R_3(1,1,1,2) - (t4R_1(1,1,1,2)-t4R_2(1,1,1,2)),
+                "T4R - T4R (1,1,1,2)");
+  test_for_zero(t4R_3(1,1,2,0) - (t4R_1(1,1,2,0)-t4R_2(1,1,2,0)),
+                "T4R - T4R (1,1,2,0)");
+  test_for_zero(t4R_3(1,1,2,1) - (t4R_1(1,1,2,1)-t4R_2(1,1,2,1)),
+                "T4R - T4R (1,1,2,1)");
+  test_for_zero(t4R_3(1,1,2,2) - (t4R_1(1,1,2,2)-t4R_2(1,1,2,2)),
+                "T4R - T4R (1,1,2,2)");
+  test_for_zero(t4R_3(1,2,0,0) - (t4R_1(1,2,0,0)-t4R_2(1,2,0,0)),
+                "T4R - T4R (1,2,0,0)");
+  test_for_zero(t4R_3(1,2,0,1) - (t4R_1(1,2,0,1)-t4R_2(1,2,0,1)),
+                "T4R - T4R (1,2,0,1)");
+  test_for_zero(t4R_3(1,2,0,2) - (t4R_1(1,2,0,2)-t4R_2(1,2,0,2)),
+                "T4R - T4R (1,2,0,2)");
+  test_for_zero(t4R_3(1,2,1,0) - (t4R_1(1,2,1,0)-t4R_2(1,2,1,0)),
+                "T4R - T4R (1,2,1,0)");
+  test_for_zero(t4R_3(1,2,1,1) - (t4R_1(1,2,1,1)-t4R_2(1,2,1,1)),
+                "T4R - T4R (1,2,1,1)");
+  test_for_zero(t4R_3(1,2,1,2) - (t4R_1(1,2,1,2)-t4R_2(1,2,1,2)),
+                "T4R - T4R (1,2,1,2)");
+  test_for_zero(t4R_3(1,2,2,0) - (t4R_1(1,2,2,0)-t4R_2(1,2,2,0)),
+                "T4R - T4R (1,2,2,0)");
+  test_for_zero(t4R_3(1,2,2,1) - (t4R_1(1,2,2,1)-t4R_2(1,2,2,1)),
+                "T4R - T4R (1,2,2,1)");
+  test_for_zero(t4R_3(1,2,2,2) - (t4R_1(1,2,2,2)-t4R_2(1,2,2,2)),
+                "T4R - T4R (1,2,2,2)");
+  test_for_zero(t4R_3(2,0,0,0) - (t4R_1(2,0,0,0)-t4R_2(2,0,0,0)),
+                "T4R - T4R (2,0,0,0)");
+  test_for_zero(t4R_3(2,0,0,1) - (t4R_1(2,0,0,1)-t4R_2(2,0,0,1)),
+                "T4R - T4R (2,0,0,1)");
+  test_for_zero(t4R_3(2,0,0,2) - (t4R_1(2,0,0,2)-t4R_2(2,0,0,2)),
+                "T4R - T4R (2,0,0,2)");
+  test_for_zero(t4R_3(2,0,1,0) - (t4R_1(2,0,1,0)-t4R_2(2,0,1,0)),
+                "T4R - T4R (2,0,1,0)");
+  test_for_zero(t4R_3(2,0,1,1) - (t4R_1(2,0,1,1)-t4R_2(2,0,1,1)),
+                "T4R - T4R (2,0,1,1)");
+  test_for_zero(t4R_3(2,0,1,2) - (t4R_1(2,0,1,2)-t4R_2(2,0,1,2)),
+                "T4R - T4R (2,0,1,2)");
+  test_for_zero(t4R_3(2,0,2,0) - (t4R_1(2,0,2,0)-t4R_2(2,0,2,0)),
+                "T4R - T4R (2,0,2,0)");
+  test_for_zero(t4R_3(2,0,2,1) - (t4R_1(2,0,2,1)-t4R_2(2,0,2,1)),
+                "T4R - T4R (2,0,2,1)");
+  test_for_zero(t4R_3(2,0,2,2) - (t4R_1(2,0,2,2)-t4R_2(2,0,2,2)),
+                "T4R - T4R (2,0,2,2)");
+  test_for_zero(t4R_3(2,1,0,0) - (t4R_1(2,1,0,0)-t4R_2(2,1,0,0)),
+                "T4R - T4R (2,1,0,0)");
+  test_for_zero(t4R_3(2,1,0,1) - (t4R_1(2,1,0,1)-t4R_2(2,1,0,1)),
+                "T4R - T4R (2,1,0,1)");
+  test_for_zero(t4R_3(2,1,0,2) - (t4R_1(2,1,0,2)-t4R_2(2,1,0,2)),
+                "T4R - T4R (2,1,0,2)");
+  test_for_zero(t4R_3(2,1,1,0) - (t4R_1(2,1,1,0)-t4R_2(2,1,1,0)),
+                "T4R - T4R (2,1,1,0)");
+  test_for_zero(t4R_3(2,1,1,1) - (t4R_1(2,1,1,1)-t4R_2(2,1,1,1)),
+                "T4R - T4R (2,1,1,1)");
+  test_for_zero(t4R_3(2,1,1,2) - (t4R_1(2,1,1,2)-t4R_2(2,1,1,2)),
+                "T4R - T4R (2,1,1,2)");
+  test_for_zero(t4R_3(2,1,2,0) - (t4R_1(2,1,2,0)-t4R_2(2,1,2,0)),
+                "T4R - T4R (2,1,2,0)");
+  test_for_zero(t4R_3(2,1,2,1) - (t4R_1(2,1,2,1)-t4R_2(2,1,2,1)),
+                "T4R - T4R (2,1,2,1)");
+  test_for_zero(t4R_3(2,1,2,2) - (t4R_1(2,1,2,2)-t4R_2(2,1,2,2)),
+                "T4R - T4R (2,1,2,2)");
+  test_for_zero(t4R_3(2,2,0,0) - (t4R_1(2,2,0,0)-t4R_2(2,2,0,0)),
+                "T4R - T4R (2,2,0,0)");
+  test_for_zero(t4R_3(2,2,0,1) - (t4R_1(2,2,0,1)-t4R_2(2,2,0,1)),
+                "T4R - T4R (2,2,0,1)");
+  test_for_zero(t4R_3(2,2,0,2) - (t4R_1(2,2,0,2)-t4R_2(2,2,0,2)),
+                "T4R - T4R (2,2,0,2)");
+  test_for_zero(t4R_3(2,2,1,0) - (t4R_1(2,2,1,0)-t4R_2(2,2,1,0)),
+                "T4R - T4R (2,2,1,0)");
+  test_for_zero(t4R_3(2,2,1,1) - (t4R_1(2,2,1,1)-t4R_2(2,2,1,1)),
+                "T4R - T4R (2,2,1,1)");
+  test_for_zero(t4R_3(2,2,1,2) - (t4R_1(2,2,1,2)-t4R_2(2,2,1,2)),
+                "T4R - T4R (2,2,1,2)");
+  test_for_zero(t4R_3(2,2,2,0) - (t4R_1(2,2,2,0)-t4R_2(2,2,2,0)),
+                "T4R - T4R (2,2,2,0)");
+  test_for_zero(t4R_3(2,2,2,1) - (t4R_1(2,2,2,1)-t4R_2(2,2,2,1)),
+                "T4R - T4R (2,2,2,1)");
+  test_for_zero(t4R_3(2,2,2,2) - (t4R_1(2,2,2,2)-t4R_2(2,2,2,2)),
+                "T4R - T4R (2,2,2,2)");
+
+//   t3as_1(i,j,k)=t4R_1(i,j,k,l)*t1_2(l);
+//   t3as_1(i,j,k)=t1_2(l)*t4R_1(i,j,k,l);
+//   t3as_1(i,j,k)=t4R_1(i,j,l,k)*t1_2(l);
+//   t3as_1(i,j,k)=t1_2(l)*t4R_1(i,j,l,k);
+//   t3as_1(i,j,k)=t4R_1(i,l,j,k)*t1_2(l);
+//   t3as_1(i,j,k)=t1_2(l)*t4R_1(i,l,j,k);
+//   t3as_1(i,j,k)=t4R_1(l,i,j,k)*t1_2(l);
+//   t3as_1(i,j,k)=t1_2(l)*t4R_1(l,i,j,k);
+
+//   cout << '\n';
+
+//   test_for_zero(t4R_1(i,j,k,l)*t4ddg_2(i,j,k,l)
+//       ); test_for_zero(t4ddg_2(i,j,k,l)*t4R_1(i,j,k,l)
+//       ); test_for_zero(t4R_1(i,j,k,l)*t4ddg_2(i,k,j,l)
+//       ); test_for_zero(t4ddg_2(i,k,j,l)*t4R_1(i,j,k,l)
+//       ); test_for_zero(t4R_3(i,j,k,l)*t4ddg_2(i,j,k,l)
+//       ); test_for_zero(t4ddg_2(i,j,k,l)*t4R_3(i,j,k,l)
+//       ); test_for_zero(t4R_3(i,j,k,l)*t4ddg_2(i,k,j,l)
+//       ); test_for_zero(t4ddg_2(i,k,j,l)*t4R_3(i,j,k,l));
+
+//   cout << '\n';
+
+//   t2s_1(j,l)=t4R_1(i,j,k,l)*t2s_2(i,k);
+//   t2s_1(j,l)=t2s_2(i,k)*t4R_1(i,j,k,l);
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T4R.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T4R.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+extern
+void test_T4R(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+	      Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+	      Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+	      const Tensor2<double,3,3> &t2_3,
+	      Tensor2_symmetric<double,3> &t2s_1,
+	      const Tensor2_symmetric<double,3> &t2s_2,
+	      const Tensor2_symmetric<double,3> &t2s_3,
+	      Tensor3_dg<double,3,3> &t3dg_1,
+	      const Tensor3_dg<double,3,3> &t3dg_2,
+	      const Tensor3_dg<double,3,3> &t3dg_3,
+	      Tensor3_antisymmetric<double,3,3> &t3as_1,
+	      const Tensor3_antisymmetric<double,3,3> &t3as_2,
+	      const Tensor3_antisymmetric<double,3,3> &t3as_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T4ddg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T4ddg.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+extern
+void test_T4ddg(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T4ddgII.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T4ddgII.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,13 @@
+extern void test_T4ddgII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		       const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T4ddgIII.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T4ddgIII.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,13 @@
+extern void test_T4ddgIII(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		       const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T4ddgIV.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T4ddgIV.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,13 @@
+extern void test_T4ddgIV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		       const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_T4ddgV.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_T4ddgV.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,13 @@
+extern void test_T4ddgV(const int &T, Tensor0<double*> &t0_1, const Tensor0<double*> &t0_2,
+		Tensor1<double,3> &t1_1, const Tensor1<double,3> &t1_2,
+		Tensor2<double,3,3> &t2_1, const Tensor2<double,3,3> &t2_2,
+		const Tensor2<double,3,3> &t2_3,
+		Tensor2_symmetric<double,3> &t2s_1,
+		const Tensor2_symmetric<double,3> &t2s_2,
+		const Tensor2_symmetric<double,3> &t2s_3,
+		Tensor3_dg<double,3,3> &t3dg_1,
+		const Tensor3_dg<double,3,3> &t3dg_2,
+		const Tensor3_dg<double,3,3> &t3dg_3,
+		Tensor3_christof<double,3,3> &t3ch_1,
+		const Tensor3_christof<double,3,3> &t3ch_2,
+		       const Tensor3_christof<double,3,3> &t3ch_3);
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/test_for_zero.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/test_for_zero.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,11 @@
+#include <iostream>
+#include <cmath>
+
+template<class T>
+void test_for_zero(const T &t, const char *s)
+{
+  if(std::abs(t)<1e-14)
+    std::cout << "PASS: " << s << std::endl;
+  else
+    std::cout << "FAIL: " << s << " " << std::abs(t) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/testcases.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/testcases.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,80 @@
+#include <iostream>
+#include "../../FTensor.h"
+using namespace FTensor;
+using namespace std;
+
+#include "test_T0.h"
+#include "test_T1.h"
+#include "test_T2.h"
+#include "test_T2s.h"
+#include "test_T3.h"
+#include "test_T3II.h"
+#include "test_T3dg.h"
+#include "test_T3ch.h"
+#include "test_T3as.h"
+#include "test_T4ddg.h"
+#include "test_T4ddgII.h"
+#include "test_T4ddgIII.h"
+#include "test_T4ddgIV.h"
+#include "test_T4ddgV.h"
+#include "test_T4R.h"
+
+int main()
+{
+  double t01(12), t02(14);
+
+  Tensor0<double *> t0_1(&t01), t0_2(&t02);
+  Tensor1<double,3> t1_1(1,2,3), t1_2(4,5,6), t1_3(7,8,9);
+  Tensor2<double,3,3> t2_1(10,20,30,40,50,60,70,80,90),
+    t2_2(11,21,31,41,51,61,71,81,91),
+    t2_3(12,22,32,42,52,62,72,82,92);
+  Tensor2_symmetric<double,3> t2s_1(13,23,33,43,53,63),
+    t2s_2(14,24,34,44,54,64), t2s_3(15,25,35,45,55,65);
+  Tensor3_dg<double,3,3> t3dg_1(101,102,103,104,105,106,107,108,109,110,111,
+				112,113,114,115,116,117,118),
+    t3dg_2(201,202,203,204,205,206,207,208,209,210,211,
+	   212,213,214,215,216,217,218),
+    t3dg_3(301,302,303,304,305,306,307,308,309,310,311,
+	   312,313,314,315,316,317,318);
+  Tensor3_christof<double,3,3>
+    t3ch_1(401,402,403,404,405,406,407,408,409,410,411,
+	   412,413,414,415,416,417,418),
+    t3ch_2(501,502,503,504,505,506,507,508,509,510,511,
+	   512,513,514,515,516,517,518),
+    t3ch_3(601,602,603,604,605,606,607,608,609,610,611,
+	   612,613,614,615,616,617,618);
+  Tensor3_antisymmetric<double,3,3>
+    t3as_1(701,702,703,704,705,706,707,708,709),
+    t3as_2(801,802,803,804,805,806,807,808,809),
+    t3as_3(901,902,903,904,905,906,907,908,909);
+
+  test_T0(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T1(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2s(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T3(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+ 	  t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3II(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+ 	    t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3dg(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+ 	    t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3ch(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+	    t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3as(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+ 	    t3dg_1,t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+  test_T4ddg(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+ 	     t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T4ddgII(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+	       t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T4ddgIII(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+		t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T4ddgIV(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+	       t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T4ddgV(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+	      t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T4R(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+  	   t3dg_1,t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+
+
+  cout << '\n';
+}
diff -r 000000000000 -r 34fc4fd9248b tests/conformance/testcases_compiler.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/conformance/testcases_compiler.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,52 @@
+#include <iostream>
+#include "../../FTensor.h"
+using namespace FTensor;
+using namespace std;
+
+#include "test_T0.h"
+#include "test_T1.h"
+#include "test_T2.h"
+#include "test_T2s.h"
+#include "test_T3ch.h"
+#include "test_T3as.h"
+
+int main()
+{
+  double t01(12), t02(14);
+
+  Tensor0<double *> t0_1(&t01), t0_2(&t02);
+  Tensor1<double,3> t1_1(1,2,3), t1_2(4,5,6), t1_3(7,8,9);
+  Tensor2<double,3,3> t2_1(10,20,30,40,50,60,70,80,90),
+    t2_2(11,21,31,41,51,61,71,81,91),
+    t2_3(12,22,32,42,52,62,72,82,92);
+  Tensor2_symmetric<double,3> t2s_1(13,23,33,43,53,63),
+    t2s_2(14,24,34,44,54,64), t2s_3(15,25,35,45,55,65);
+  Tensor3_dg<double,3,3> t3dg_1(101,102,103,104,105,106,107,108,109,110,111,
+				112,113,114,115,116,117,118),
+    t3dg_2(201,202,203,204,205,206,207,208,209,210,211,
+	   212,213,214,215,216,217,218),
+    t3dg_3(301,302,303,304,305,306,307,308,309,310,311,
+	   312,313,314,315,316,317,318);
+  Tensor3_christof<double,3,3>
+    t3ch_1(401,402,403,404,405,406,407,408,409,410,411,
+	   412,413,414,415,416,417,418),
+    t3ch_2(501,502,503,504,505,506,507,508,509,510,511,
+	   512,513,514,515,516,517,518),
+    t3ch_3(601,602,603,604,605,606,607,608,609,610,611,
+	   612,613,614,615,616,617,618);
+  Tensor3_antisymmetric<double,3,3>
+    t3as_1(701,702,703,704,705,706,707,708,709),
+    t3as_2(801,802,803,804,805,806,807,808,809),
+    t3as_3(901,902,903,904,905,906,907,908,909);
+
+  test_T0(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T1(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T2s(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3);
+  test_T3ch(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+	    t3dg_1,t3dg_2,t3dg_3,t3ch_1,t3ch_2,t3ch_3);
+  test_T3as(13,t0_1,t0_2,t1_1,t1_2,t2_1,t2_2,t2_3,t2s_1,t2s_2,t2s_3,
+ 	    t3dg_1,t3dg_2,t3dg_3,t3as_1,t3as_2,t3as_3);
+
+  cout << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/Makefile	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,49 @@
+# CXX = /home/boo/foreign_compilers/usr/local/KAI/KCC.pu-4.0d-1/KCC_BASE/bin/KCC
+# #CXXFLAGS=-Drestrict= --max_pending_instantiations 1000
+# CXXFLAGS=--restrict --no_exceptions --max_pending_instantiations 100
+# # CXXFLAGS=+K3 --restrict --no_exceptions --inline_auto_space_time=750000000000000 --inline_implicit_space_time=200000000000000 --inline_generated_space_time=40000000000000.0 --inline_auto_space_time=100000000000000.0 --max_pending_instantiations 100
+
+CXX = g++-3.2
+CXXOPTIMIZE=-O3 -finline-functions -finline-limit-1000 -funroll-loops
+CXXFLAGS=-ftemplate-depth-100 -Drestrict= $(CXXOPTIMIZE)
+# CXXFLAGS=-O3 -ftemplate-depth-100 -Drestrict= -fomit-frame-pointer -finline-functions -finline-limit-1000000000000 -ffast-math -fno-rtti -fno-exceptions
+# CXXFLAGS=-ftemplate-depth-100 -Drestrict=__restrict__
+# CXXFLAGS=-ansi -ftemplate-depth-100 -Drestrict=
+# CXXFLAGS=-O3 -ftemplate-depth-100 -Drestrict=__restrict__
+
+
+# CXX = icc
+# # CXXFLAGS= -restrict -O0
+# # CXXFLAGS= -restrict -O0 -Qoption,cpp,--pending_instantiations,1000
+# # CXXFLAGS= -restrict -O3
+# # CXXFLAGS= -restrict -O3 -tpp6 -xi
+# # CXXFLAGS= -restrict -O3 -tpp6 -xi -ip
+# CXXFLAGS= -restrict -O3 -tpp6 -xi -ipo
+# #CXXFLAGS= -restrict -O0 -g -I/home/boo/foreign_compilers/opt/intel/compiler50/ia32/include -I/usr/local/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/include
+# #CXXFLAGS= -restrict -O0 -g -L/home/boo/foreign_compilers/opt/intel/compiler50/ia32/lib -lcprts
+# #CXXFLAGS= -restrict -O0 -g -lcprts
+# # CXXFLAGS= -restrict -I/home/boo/intel_compiler/opt/intel/compiler50/ia32/include -I/usr/local/lib/gcc-lib/i686-pc-linux-gnu/2.95.3/include -O3 -tpp6 -xi
+# # # CXXFLAGS= -Drestrict= -I/home/boo/intel_compiler/opt/intel/compiler50/ia32/include -I/usr/lib/gcc-lib/i386-linux/2.95.2/include -O3 -tpp6 -xi -ip
+
+# CXX = pgCC
+# # CXXFLAGS = -Drestrict= -O2 -Munroll -Mnoframe  -Minline=levels:10 --no_exceptions -Mvect -Mvect=assoc -Mneginfo=loop
+
+# CXXFLAGS = -Drestrict= --pending_instantiations=1000
+# # CXXFLAGS = -Drestrict= -fast -Minline=levels:10 --no_exceptions
+
+# # CXXFLAGS = -Drestrict= -O2 -Munroll -Mnoframe  -Minline=levels:100 --no_exceptions
+
+
+% :: %,v
+
+all: little littlefast example examplefast speed_test one_over one_over_fast
+
+
+one_over: one_over_1_minus_x1 one_over_1_minus_x2 one_over_1_minus_x3 one_over_1_minus_x4 one_over_1_minus_x5 one_over_1_minus_x6 one_over_1_minus_x7 one_over_1_minus_x8 one_over_1_minus_x9
+one_over_fast: one_over_1_minus_x_fast1 one_over_1_minus_x_fast2 one_over_1_minus_x_fast3 one_over_1_minus_x_fast4 one_over_1_minus_x_fast5 one_over_1_minus_x_fast6 one_over_1_minus_x_fast7 one_over_1_minus_x_fast8 one_over_1_minus_x_fast9
+
+algebra3: algebra3_test1 algebra3_test2 algebra3_test3 algebra3_test4 algebra3_test5 algebra3_test6 algebra3_test7 algebra3_test8 algebra3_test9
+
+
+clean:
+	rm -f *.o little littlefast example examplefast speed_test one_over_1_minus_x1 one_over_1_minus_x2 one_over_1_minus_x3 one_over_1_minus_x4 one_over_1_minus_x5 one_over_1_minus_x6 one_over_1_minus_x7 one_over_1_minus_x8 one_over_1_minus_x9 one_over_1_minus_x_fast1 one_over_1_minus_x_fast2 one_over_1_minus_x_fast3 one_over_1_minus_x_fast4 one_over_1_minus_x_fast5 one_over_1_minus_x_fast6 one_over_1_minus_x_fast7 one_over_1_minus_x_fast8 one_over_1_minus_x_fast9 algebra3_test1 algebra3_test2 algebra3_test3 algebra3_test4 algebra3_test5 algebra3_test6 algebra3_test7 algebra3_test8 algebra3_test9
diff -r 000000000000 -r 34fc4fd9248b tests/speed/Number_test.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/Number_test.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,39 @@
+#include <iostream>
+#include "../FTensor.h"
+
+using namespace FTensor;
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> x(2,3,4);
+  Tensor1<double,3> n(5,6,7);
+  Tensor2 t2(1,2,3,4,5,6,7,8,9);
+
+  const Index<'i',3> i;
+  const Index<'j'> j;
+  const Number<0> N0;
+  const Number<1> N1;
+  const Number<2> N2;
+
+  for(int ii=0;ii<100000000;ii++)
+    {
+      y(i)+=(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//    	-(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//  -(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//  -(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//  -(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+//  -(x(i)+n(i)+t2(i,N0))+(x(i)+n(i)+t2(i,N0))
+	;
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
+
diff -r 000000000000 -r 34fc4fd9248b tests/speed/acoustic.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/acoustic.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,108 @@
+#include <iostream>
+#include <cmath>
+#include <cstdlib>
+#include <vector>
+using namespace std;
+
+#include "../../FTensor.h"
+
+void initial(double P1[], double P2[], double P3[],
+	     double c[], const int N)
+{
+  int cr = N/2-1;
+  int cc = 7.0*N/8.0-1;
+  float s2 = 64.0 * 9.0 / pow(N/2.0,2.0);
+  
+  for(int i=0;i<N;++i)
+    for(int j=0;j<N;++j)
+      {
+	c[i+N*j]=0.2;
+	P1[i+N*j] = 0.0;
+	P2[i+N*j] = exp(-(pow(i-cr,2.0)+pow(j-cc,2.0)) * s2);
+	P3[i+N*j] = 0.0;
+      }
+
+  const int blockLeft = 0;
+  const int blockRight = 2 * N / 5.0;
+  const int blockTop = N / 3.0;
+  const int blockBottom = 2 * N / 3.0;
+
+  for(int i=blockTop; i<blockBottom; ++i)
+    for(int j=blockLeft; j<blockRight; ++j)
+      c[i+N*j] = 0.5;
+
+  int channelLeft = 4*N/5.0;
+  int channelRight = N;
+  int channel1Height = 3*N/8.0;
+  int channel2Height = 5*N/8.0;
+  for(int i=channelLeft; i<channelRight; ++i)
+    for(int j=channel1Height; j<channel2Height; ++j)
+      c[i+N*j]=0;
+}
+
+void FTen(double P1_[], double P2_[], double P3_[],
+	    double c_[], const int N)
+{
+  FTensor::Tensor0<double*> P1(P1_), P2(P2_), P3(P3_), c(c_);
+  
+  FTensor::Tensor1<int,2> d_ijk(1,N);
+  FTensor::Tensor1<double,2> d_xyz(1,1);
+  FTensor::Index<'l',2> l;
+  FTensor::Index<'m',2> m;
+  for(int j=0;j<N;++j)
+    for(int i=0;i<N;++i)
+      {
+	if(i!=0 && i!=N-1 && j!=0 && j!=N-1)
+	  {
+//  	    P3 = 2*P2 - P1;
+	    P3 = 2*P2 - P1
+	      + c*(dd(P2,l,m,d_ijk,d_xyz)(0,0)
+		   + dd(P2,l,m,d_ijk,d_xyz)(1,1));
+	  }
+	++P1;
+	++P2;
+	++P3;
+	++c;
+      }
+//    cout << P3_[(N/2-1)+N*((7*N)/8-1)] << endl;
+}
+
+
+void simple(double P1[], double P2[], double P3[],
+	    double c[], const int N)
+{
+  for(int j=1;j<N-1;++j)
+    for(int i=1;i<N-1;++i)
+      {
+//  	P3[i+N*j] = 2*P2[i+N*j] - P1[i+N*j];
+	P3[i+N*j] = (2-4*c[i+N*j])*P2[i+N*j] - P1[i+N*j]
+	  + c[i+N*j]*(P2[i-1+N*j] + P2[i+1+N*j]
+		      + P2[i+N*(j-1)] + P2[i+N*(j+1)]);
+      }
+//    cout << P3[(N/2-1)+N*((7*N)/8-1)] << endl;
+}
+
+
+int main(int argc, char *argv[])
+{
+  const int N=atoi(argv[1]);
+
+  vector<double> P1(N*N), P2(N*N), P3(N*N), c(N*N);
+
+  initial(&c[0],&P1[0],&P2[0],&P3[0],N);
+
+
+  const int niters=atoi(argv[2]);
+
+  for(int i=0;i<niters;++i)
+    {    
+//        simple(&P1[0],&P2[0],&P3[0],&c[0],N);
+//        simple(&P2[0],&P3[0],&P1[0],&c[0],N);
+//        simple(&P3[0],&P1[0],&P2[0],&c[0],N);
+      FTen(&P1[0],&P2[0],&P3[0],&c[0],N);
+      FTen(&P2[0],&P3[0],&P1[0],&c[0],N);
+      FTen(&P3[0],&P1[0],&P2[0],&c[0],N);
+    }
+}
+
+
diff -r 000000000000 -r 34fc4fd9248b tests/speed/example.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/example.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,102 @@
+#include <iostream>
+using namespace std;
+#include "../../FTensor.h"
+using namespace FTensor;
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> x(2,3,4);
+  Tensor1<double,3> n(5,6,7);
+  const Index<'i',3> i;
+
+  for(int j=0;j<10000000;j++)
+    {
+      y(i)=x(i)+n(i);
+      x(i)=y(i)-n(i);
+      n(i)=n(i)+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))
+	+(y(i)-x(i))-(y(i)-x(i));
+
+      n(i)=n(i)+y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
+ +y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
++y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// +y(i)-x(i)
+// 	+y(i)-x(i)	
+	;
+
+//        n(i)=(y(i)-x(i))*(y(i)-x(i))/(n(i));
+// n(i)=(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))/(n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i));
+    }
+  cout << y(0) << " " << y(1) << " " << y(2) << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/examplefast.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/examplefast.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,25 @@
+#include <iostream>
+using namespace std;
+int main()
+{
+  double x[3],y[3],n[3];
+
+  y[0]=0; y[1]=1; y[2]=2;
+  x[0]=2; x[1]=3; x[2]=4;
+  n[0]=5; n[1]=6; n[2]=7;
+  for(int i=1;i<10000000;i++)
+    {
+      y[0]=(x[0]+n[0]);
+      y[1]=(x[1]+n[1]);
+      y[2]=(x[2]+n[2]);
+
+      x[0]=(y[0]-n[0]);
+      x[1]=(y[1]-n[1]);
+      x[2]=(y[2]-n[2]);
+
+      n[0]=n[0]+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0]);
+      n[1]=n[1]+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1]);
+      n[2]=n[2]+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2]);
+    }
+  cout << y[0] << " " << y[1] << " " << y[2] << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/little.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/little.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,68 @@
+#include <iostream>
+#include "../../FTensor.h"
+
+using namespace FTensor;
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+
+//    Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> x(2,3,4);
+  Tensor1<double,3> n(5,6,7);
+//    Tensor2 t2(1,2,3,4,5,6,7,8,9);
+//    Tensor2 t2e(9,8,7,6,5,4,3,2,1);
+//    Tensor2_symmetric t2s(1,2,3,4,5,6);
+//    Tensor2_symmetric t2es(9,8,7,6,5,4);
+
+  const Index<'i',3> i;
+//    const Index<'j'> j;
+//    const Index<'k'> k;
+
+//    y(i)=-n(i)+2.0;
+//    y(i)+=n(i)-2.0;
+//    y(i)-=n(i)*2.0;
+//    y(i)+=2.0;
+//    y(i)-=2.0;
+//    y(i)*=2.0;
+//    y(i)/=2.0;
+//    x(i)=2.0+y(i)-n(i)/2.0;
+//    n(i)=2.0-y(i)+2.0*x(i);
+//    n(i)=-(y(i)+x(i))*n(i)*0.0+1.0;
+//    t2(i,j)=t2(i,j)+2.0*t2e(i,j)-t2(i,j)*2.0;
+//    t2e(i,j)=n(k)*n(i)*(-t2(k,j));
+//    x(i)=t2e(i,j)*n(j) - n(j)*t2e(i,j);
+//    n(i)=t2e(j,i)*n(j) - n(j)*t2e(j,i) + t2s(i,j)*y(j);
+//    n(i)+=(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i));
+//  //    n(i)=(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))*(y(i)-x(i))/(n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i)*n(i));
+
+  for(int ii=0;ii<100000000;ii++)
+    {
+//        const Index<'i',3> i;
+
+//    n(i)+=(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i))+(y(i)-x(i))-(y(i)-x(i));
+
+//        y(i)+=x(i)+n(i);
+
+
+      y(i)+=(x(i)+n(i))
+    	-(x(i)+n(i))+(x(i)+n(i))
+    	-(x(i)+n(i))+(x(i)+n(i))
+//      	-(x(i)+n(i))+(x(i)+n(i))
+//    	-(x(i)+n(i))+(x(i)+n(i))
+//    	-(x(i)+n(i))+(x(i)+n(i))
+//    	-(x(i)+n(i))+(x(i)+n(i))
+//    	-(x(i)+n(i))+(x(i)+n(i))
+//    	-(x(i)+n(i))+(x(i)+n(i))
+//    	-(x(i)+n(i))+(x(i)+n(i))
+//  -(x(i)+n(i))+(x(i)+n(i))
+//  -(x(i)+n(i))+(x(i)+n(i))
+//  -(x(i)+n(i))+(x(i)+n(i))
+//  -(x(i)+n(i))+(x(i)+n(i))
+	;
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+//         << x(0) << " " << x(1) << " " << x(2) << endl
+//         << n(0) << " " << n(1) << " " << n(2) << endl
+//         << y(i)*n(i) << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/littlefast.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/littlefast.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,34 @@
+#include <iostream>
+
+int main()
+{
+  double y[3],x[3],n[3];
+
+  y[0]=0;
+  y[1]=1;
+  y[2]=2;
+
+  x[0]=2;
+  x[1]=3;
+  x[2]=4;
+
+  n[0]=5;
+  n[1]=6;
+  n[2]=7;
+
+  for(int i=0;i<100000000;i++)
+    {
+//        y[0]=y[0]+n[0];
+//        y[1]=y[1]+n[1];
+//        y[2]=y[2]+n[2];
+
+  n[0]+=(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0])+(y[0]-x[0])-(y[0]-x[0]);
+  n[1]+=(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1])+(y[1]-x[1])-(y[1]-x[1]);
+  n[2]+=(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2])+(y[2]-x[2])-(y[2]-x[2]);
+
+      y[0]+=x[0]+n[0];
+      y[1]+=x[1]+n[1];
+      y[2]+=x[2]+n[2];
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+
+  for(int ii=0;ii<100000000;ii++)
+    {
+          func1(y,a1);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,190 @@
+#include "../../FTensor.h"
+using namespace FTensor;
+
+inline void func1(Tensor1<double,3> &y, Tensor1<double,3> &a1)
+{
+  const Index<'i',3> i;
+
+  y(i)+=a1(i);
+  a1(i)*=0.1;
+  return;
+}
+
+inline void func2(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2)
+{
+  const Index<'i',3> i;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  return;
+}
+
+inline void func3(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2, Tensor1<double,3> &a3)
+{
+  const Index<'i',3> i;
+  const Index<'j',3> j;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    + 3*(a1(j)*a2(j))*a3(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  a3(i)*=0.3;
+  return;
+}
+
+inline void func4(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2, Tensor1<double,3> &a3,
+		  Tensor1<double,3> &a4)
+{
+  const Index<'i',3> i;
+  const Index<'j',3> j;
+  const Index<'k',3> k;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    + 3*(a1(j)*a2(j))*a3(i)
+    + 4*(a1(j)*a3(j))*(a2(k)*a2(k))*a4(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  a3(i)*=0.3;
+  a4(i)*=0.4;
+  return;
+}
+
+inline void func5(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2, Tensor1<double,3> &a3,
+		  Tensor1<double,3> &a4, Tensor1<double,3> &a5)
+{
+  const Index<'i',3> i;
+  const Index<'j',3> j;
+  const Index<'k',3> k;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    + 3*(a1(j)*a2(j))*a3(i)
+    + 4*(a1(j)*a3(j))*(a2(k)*a2(k))*a4(i)
+    + 5*(a1(j)*a4(j))*(a2(k)*a3(k))*a5(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  a3(i)*=0.3;
+  a4(i)*=0.4;
+  a5(i)*=0.5;
+  return;
+}
+
+inline void func6(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2, Tensor1<double,3> &a3,
+		  Tensor1<double,3> &a4, Tensor1<double,3> &a5, Tensor1<double,3> &a6)
+{
+  const Index<'i',3> i;
+  const Index<'j',3> j;
+  const Index<'k',3> k;
+  const Index<'l',3> l;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    + 3*(a1(j)*a2(j))*a3(i)
+    + 4*(a1(j)*a3(j))*(a2(k)*a2(k))*a4(i)
+    + 5*(a1(j)*a4(j))*(a2(k)*a3(k))*a5(i)
+    + 6*(a1(j)*a5(j))*(a2(k)*a4(k))*(a3(l)*a3(l))*a6(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  a3(i)*=0.3;
+  a4(i)*=0.4;
+  a5(i)*=0.5;
+  a6(i)*=0.6;
+  return;
+}
+
+inline void func7(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2, Tensor1<double,3> &a3,
+		  Tensor1<double,3> &a4, Tensor1<double,3> &a5, Tensor1<double,3> &a6, Tensor1<double,3> &a7)
+{
+  const Index<'i',3> i;
+  const Index<'j',3> j;
+  const Index<'k',3> k;
+  const Index<'l',3> l;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    + 3*(a1(j)*a2(j))*a3(i)
+    + 4*(a1(j)*a3(j))*(a2(k)*a2(k))*a4(i)
+    + 5*(a1(j)*a4(j))*(a2(k)*a3(k))*a5(i)
+    + 6*(a1(j)*a5(j))*(a2(k)*a4(k))*(a3(l)*a3(l))*a6(i)
+    + 7*(a1(j)*a6(j))*(a2(k)*a5(k))*(a3(l)*a4(l))*a7(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  a3(i)*=0.3;
+  a4(i)*=0.4;
+  a5(i)*=0.5;
+  a6(i)*=0.6;
+  a7(i)*=0.7;
+  return;
+}
+
+inline void func8(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2, Tensor1<double,3> &a3,
+		  Tensor1<double,3> &a4, Tensor1<double,3> &a5, Tensor1<double,3> &a6, Tensor1<double,3> &a7,
+		  Tensor1<double,3> &a8)
+{
+  const Index<'i',3> i;
+  const Index<'j',3> j;
+  const Index<'k',3> k;
+  const Index<'l',3> l;
+  const Index<'m',3> m;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    + 3*(a1(j)*a2(j))*a3(i)
+    + 4*(a1(j)*a3(j))*(a2(k)*a2(k))*a4(i)
+    + 5*(a1(j)*a4(j))*(a2(k)*a3(k))*a5(i)
+    + 6*(a1(j)*a5(j))*(a2(k)*a4(k))*(a3(l)*a3(l))*a6(i)
+    + 7*(a1(j)*a6(j))*(a2(k)*a5(k))*(a3(l)*a4(l))*a7(i)
+    + 8*(a1(j)*a7(j))*(a2(k)*a6(k))*(a3(l)*a5(l))*(a4(m)*a4(m))*a8(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  a3(i)*=0.3;
+  a4(i)*=0.4;
+  a5(i)*=0.5;
+  a6(i)*=0.6;
+  a7(i)*=0.7;
+  a8(i)*=0.8;
+  return;
+}
+
+inline void func9(Tensor1<double,3> &y, Tensor1<double,3> &a1, Tensor1<double,3> &a2, Tensor1<double,3> &a3,
+		  Tensor1<double,3> &a4, Tensor1<double,3> &a5, Tensor1<double,3> &a6, Tensor1<double,3> &a7,
+		  Tensor1<double,3> &a8, Tensor1<double,3> &a9)
+{
+  const Index<'i',3> i;
+  const Index<'j',3> j;
+  const Index<'k',3> k;
+  const Index<'l',3> l;
+  const Index<'m',3> m;
+
+  y(i)+=a1(i)
+    + 2*a2(i)
+    + 3*(a1(j)*a2(j))*a3(i)
+    + 4*(a1(j)*a3(j))*(a2(k)*a2(k))*a4(i)
+    + 5*(a1(j)*a4(j))*(a2(k)*a3(k))*a5(i)
+    + 6*(a1(j)*a5(j))*(a2(k)*a4(k))*(a3(l)*a3(l))*a6(i)
+    + 7*(a1(j)*a6(j))*(a2(k)*a5(k))*(a3(l)*a4(l))*a7(i)
+    + 8*(a1(j)*a7(j))*(a2(k)*a6(k))*(a3(l)*a5(l))*(a4(m)*a4(m))*a8(i)
+    + 9*(a1(j)*a8(j))*(a2(k)*a7(k))*(a3(l)*a6(l))*(a4(m)*a5(m))*a9(i)
+    ;
+  a1(i)*=0.1;
+  a2(i)*=0.2;
+  a3(i)*=0.3;
+  a4(i)*=0.4;
+  a5(i)*=0.5;
+  a6(i)*=0.6;
+  a7(i)*=0.7;
+  a8(i)*=0.8;
+  a9(i)*=0.9;
+  return;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x1.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x1.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+
+  for(int ii=0;ii<100000000;ii++)
+    {
+          func1(y,a1);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x2.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x2.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,15 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+
+  for(int ii=0;ii<100000000;ii++)
+    {
+      func2(y,a1,a2);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x3.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x3.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,16 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+  Tensor1<double,3> a3(8,9,10);
+
+  for(int ii=0;ii<10000000;ii++)
+    {
+      func3(y,a1,a2,a3);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x4.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x4.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,17 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+  Tensor1<double,3> a3(8,9,10);
+  Tensor1<double,3> a4(11,12,13);
+
+  for(int ii=0;ii<10000000;ii++)
+    {
+      func4(y,a1,a2,a3,a4);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x5.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x5.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,18 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+  Tensor1<double,3> a3(8,9,10);
+  Tensor1<double,3> a4(11,12,13);
+  Tensor1<double,3> a5(14,15,16);
+
+  for(int ii=0;ii<10000000;ii++)
+    {
+      func5(y,a1,a2,a3,a4,a5);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x6.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x6.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,19 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+  Tensor1<double,3> a3(8,9,10);
+  Tensor1<double,3> a4(11,12,13);
+  Tensor1<double,3> a5(14,15,16);
+  Tensor1<double,3> a6(17,18,19);
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+      func6(y,a1,a2,a3,a4,a5,a6);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x7.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x7.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,20 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+  Tensor1<double,3> a3(8,9,10);
+  Tensor1<double,3> a4(11,12,13);
+  Tensor1<double,3> a5(14,15,16);
+  Tensor1<double,3> a6(17,18,19);
+  Tensor1<double,3> a7(20,21,22);
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+      func7(y,a1,a2,a3,a4,a5,a6,a7);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x8.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x8.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,21 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+  Tensor1<double,3> a3(8,9,10);
+  Tensor1<double,3> a4(11,12,13);
+  Tensor1<double,3> a5(14,15,16);
+  Tensor1<double,3> a6(17,18,19);
+  Tensor1<double,3> a7(20,21,22);
+  Tensor1<double,3> a8(23,24,25);
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+	  func8(y,a1,a2,a3,a4,a5,a6,a7,a8);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x9.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x9.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,22 @@
+#include <iostream>
+#include "one_over_1_minus_x.h"
+
+int main()
+{
+  Tensor1<double,3> y(0,1,2);
+  Tensor1<double,3> a1(2,3,4);
+  Tensor1<double,3> a2(5,6,7);
+  Tensor1<double,3> a3(8,9,10);
+  Tensor1<double,3> a4(11,12,13);
+  Tensor1<double,3> a5(14,15,16);
+  Tensor1<double,3> a6(17,18,19);
+  Tensor1<double,3> a7(20,21,22);
+  Tensor1<double,3> a8(23,24,25);
+  Tensor1<double,3> a9(26,27,28);
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+      func9(y,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+    }
+  std::cout << y(0) << " " << y(1) << " " << y(2) << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,379 @@
+#include <iostream>
+
+inline void func1(double * restrict y, double * restrict a1)
+{
+  y[0]+=a1[0];
+  y[1]+=a1[1];
+  y[2]+=a1[2];
+  a1[0]*=0.1;
+  a1[1]*=0.1;
+  a1[2]*=0.1;
+  return;
+}
+
+inline void func2(double * restrict y, double * restrict a1, double * restrict a2)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  return;
+}
+
+inline void func3(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  return;
+}
+
+inline void func4(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  return;
+}
+
+inline void func5(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  return;
+}
+
+inline void func6(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  return;
+}
+
+inline void func7(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6, double * restrict a7)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a7[0]*=0.7;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a7[1]*=0.7;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  a7[2]*=0.7;
+  return;
+}
+
+inline void func8(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6, double * restrict a7,
+		  double * restrict a8)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[0]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[1]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[2]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a7[0]*=0.7;
+  a8[0]*=0.8;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a7[1]*=0.7;
+  a8[1]*=0.8;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  a7[2]*=0.7;
+  a8[2]*=0.8;
+  return;
+}
+
+inline void func9(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6, double * restrict a7,
+		  double * restrict a8, double * restrict a9)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[0]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[0]
+    + 9*(a1[0]*a8[0]+a1[1]*a8[1]+a1[2]*a8[2])*(a2[0]*a7[0]+a2[1]*a7[1]+a2[2]*a7[2])*(a3[0]*a6[0]+a3[1]*a6[1]+a3[2]*a6[2])*(a4[0]*a5[0]+a4[1]*a5[1]+a4[2]*a5[2])*a9[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[1]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[1]
+    + 9*(a1[0]*a8[0]+a1[1]*a8[1]+a1[2]*a8[2])*(a2[0]*a7[0]+a2[1]*a7[1]+a2[2]*a7[2])*(a3[0]*a6[0]+a3[1]*a6[1]+a3[2]*a6[2])*(a4[0]*a5[0]+a4[1]*a5[1]+a4[2]*a5[2])*a9[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[2]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[2]
+    + 9*(a1[0]*a8[0]+a1[1]*a8[1]+a1[2]*a8[2])*(a2[0]*a7[0]+a2[1]*a7[1]+a2[2]*a7[2])*(a3[0]*a6[0]+a3[1]*a6[1]+a3[2]*a6[2])*(a4[0]*a5[0]+a4[1]*a5[1]+a4[2]*a5[2])*a9[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a7[0]*=0.7;
+  a8[0]*=0.8;
+  a9[0]*=0.9;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a7[1]*=0.7;
+  a8[1]*=0.8;
+  a9[1]*=0.9;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  a7[2]*=0.7;
+  a8[2]*=0.8;
+  a9[2]*=0.9;
+  return;
+}
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+  double a4[]={11,12,13};
+  double a5[]={14,15,16};
+  double a6[]={17,18,19};
+  double a7[]={20,21,22};
+  double a8[]={23,24,25};
+  double a9[]={26,27,28};
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+//          func1(y,a1);
+//            func2(y,a1,a2);
+      func3(y,a1,a2,a3);
+//            func4(y,a1,a2,a3,a4);
+//            func5(y,a1,a2,a3,a4,a5);
+//            func6(y,a1,a2,a3,a4,a5,a6);
+//        func7(y,a1,a2,a3,a4,a5,a6,a7);
+//        func8(y,a1,a2,a3,a4,a5,a6,a7,a8);
+//        func9(y,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+//         << x(0) << " " << x(1) << " " << x(2) << endl
+//         << n(0) << " " << n(1) << " " << n(2) << endl
+//         << y(i)*n(i) << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast.h	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,346 @@
+inline void func1(double * restrict y, double * restrict a1)
+{
+  y[0]+=a1[0];
+  y[1]+=a1[1];
+  y[2]+=a1[2];
+  a1[0]*=0.1;
+  a1[1]*=0.1;
+  a1[2]*=0.1;
+  return;
+}
+
+inline void func2(double * restrict y, double * restrict a1, double * restrict a2)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  return;
+}
+
+inline void func3(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  return;
+}
+
+inline void func4(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  return;
+}
+
+inline void func5(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  return;
+}
+
+inline void func6(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  return;
+}
+
+inline void func7(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6, double * restrict a7)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a7[0]*=0.7;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a7[1]*=0.7;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  a7[2]*=0.7;
+  return;
+}
+
+inline void func8(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6, double * restrict a7,
+		  double * restrict a8)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[0]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[1]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[2]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a7[0]*=0.7;
+  a8[0]*=0.8;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a7[1]*=0.7;
+  a8[1]*=0.8;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  a7[2]*=0.7;
+  a8[2]*=0.8;
+  return;
+}
+
+inline void func9(double * restrict y, double * restrict a1, double * restrict a2, double * restrict a3,
+		  double * restrict a4, double * restrict a5, double * restrict a6, double * restrict a7,
+		  double * restrict a8, double * restrict a9)
+{
+  y[0]+=a1[0]
+    + 2*a2[0]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[0]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[0]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[0]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[0]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[0]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[0]
+    + 9*(a1[0]*a8[0]+a1[1]*a8[1]+a1[2]*a8[2])*(a2[0]*a7[0]+a2[1]*a7[1]+a2[2]*a7[2])*(a3[0]*a6[0]+a3[1]*a6[1]+a3[2]*a6[2])*(a4[0]*a5[0]+a4[1]*a5[1]+a4[2]*a5[2])*a9[0]
+    ;
+  y[1]+=a1[1]
+    + 2*a2[1]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[1]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[1]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[1]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[1]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[1]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[1]
+    + 9*(a1[0]*a8[0]+a1[1]*a8[1]+a1[2]*a8[2])*(a2[0]*a7[0]+a2[1]*a7[1]+a2[2]*a7[2])*(a3[0]*a6[0]+a3[1]*a6[1]+a3[2]*a6[2])*(a4[0]*a5[0]+a4[1]*a5[1]+a4[2]*a5[2])*a9[1]
+    ;
+  y[2]+=a1[2]
+    + 2*a2[2]
+    + 3*(a1[0]*a2[0]+a1[1]*a2[1]+a1[2]*a2[2])*a3[2]
+    + 4*(a1[0]*a3[0]+a1[1]*a3[1]+a1[2]*a3[2])*(a2[0]*a2[0]+a2[1]*a2[1]+a2[2]*a2[2])*a4[2]
+    + 5*(a1[0]*a4[0]+a1[1]*a4[1]+a1[2]*a4[2])*(a2[0]*a3[0]+a2[1]*a3[1]+a2[2]*a3[2])*a5[2]
+    + 6*(a1[0]*a5[0]+a1[1]*a5[1]+a1[2]*a5[2])*(a2[0]*a4[0]+a2[1]*a4[1]+a2[2]*a4[2])*(a3[0]*a3[0]+a3[1]*a3[1]+a3[2]*a3[2])*a6[2]
+    + 7*(a1[0]*a6[0]+a1[1]*a6[1]+a1[2]*a6[2])*(a2[0]*a5[0]+a2[1]*a5[1]+a2[2]*a5[2])*(a3[0]*a4[0]+a3[1]*a4[1]+a3[2]*a4[2])*a7[2]
+    + 8*(a1[0]*a7[0]+a1[1]*a7[1]+a1[2]*a7[2])*(a2[0]*a6[0]+a2[1]*a6[1]+a2[2]*a6[2])*(a3[0]*a5[0]+a3[1]*a5[1]+a3[2]*a5[2])*(a4[0]*a4[0]+a4[1]*a4[1]+a4[2]*a4[2])*a8[2]
+    + 9*(a1[0]*a8[0]+a1[1]*a8[1]+a1[2]*a8[2])*(a2[0]*a7[0]+a2[1]*a7[1]+a2[2]*a7[2])*(a3[0]*a6[0]+a3[1]*a6[1]+a3[2]*a6[2])*(a4[0]*a5[0]+a4[1]*a5[1]+a4[2]*a5[2])*a9[2]
+    ;
+  a1[0]*=0.1;
+  a2[0]*=0.2;
+  a3[0]*=0.3;
+  a4[0]*=0.4;
+  a5[0]*=0.5;
+  a6[0]*=0.6;
+  a7[0]*=0.7;
+  a8[0]*=0.8;
+  a9[0]*=0.9;
+  a1[1]*=0.1;
+  a2[1]*=0.2;
+  a3[1]*=0.3;
+  a4[1]*=0.4;
+  a5[1]*=0.5;
+  a6[1]*=0.6;
+  a7[1]*=0.7;
+  a8[1]*=0.8;
+  a9[1]*=0.9;
+  a1[2]*=0.1;
+  a2[2]*=0.2;
+  a3[2]*=0.3;
+  a4[2]*=0.4;
+  a5[2]*=0.5;
+  a6[2]*=0.6;
+  a7[2]*=0.7;
+  a8[2]*=0.8;
+  a9[2]*=0.9;
+  return;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast1.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast1.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,14 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+
+  for(int ii=0;ii<100000000;ii++)
+    {
+      func1(y,a1);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast2.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast2.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,15 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+
+  for(int ii=0;ii<100000000;ii++)
+    {
+      func2(y,a1,a2);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast3.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast3.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,16 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+
+  for(int ii=0;ii<10000000;ii++)
+    {
+      func3(y,a1,a2,a3);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast4.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast4.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,17 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+  double a4[]={11,12,13};
+
+  for(int ii=0;ii<10000000;ii++)
+    {
+      func4(y,a1,a2,a3,a4);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast5.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast5.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,18 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+  double a4[]={11,12,13};
+  double a5[]={14,15,16};
+
+  for(int ii=0;ii<10000000;ii++)
+    {
+          func5(y,a1,a2,a3,a4,a5);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast6.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast6.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,19 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+  double a4[]={11,12,13};
+  double a5[]={14,15,16};
+  double a6[]={17,18,19};
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+      func6(y,a1,a2,a3,a4,a5,a6);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast7.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast7.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,21 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+  double a4[]={11,12,13};
+  double a5[]={14,15,16};
+  double a6[]={17,18,19};
+  double a7[]={20,21,22};
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+      func7(y,a1,a2,a3,a4,a5,a6,a7);
+
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast8.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast8.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,21 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+  double a4[]={11,12,13};
+  double a5[]={14,15,16};
+  double a6[]={17,18,19};
+  double a7[]={20,21,22};
+  double a8[]={23,24,25};
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+      func8(y,a1,a2,a3,a4,a5,a6,a7,a8);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_1_minus_x_fast9.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_1_minus_x_fast9.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,22 @@
+#include <iostream>
+#include "one_over_1_minus_x_fast.h"
+
+int main()
+{
+  double y[]={0,1,2};
+  double a1[]={2,3,4};
+  double a2[]={5,6,7};
+  double a3[]={8,9,10};
+  double a4[]={11,12,13};
+  double a5[]={14,15,16};
+  double a6[]={17,18,19};
+  double a7[]={20,21,22};
+  double a8[]={23,24,25};
+  double a9[]={26,27,28};
+
+  for(int ii=0;ii<1000000;ii++)
+    {
+      func9(y,a1,a2,a3,a4,a5,a6,a7,a8,a9);
+    }
+  std::cout << y[0] << " " << y[1] << " " << y[2] << std::endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/one_over_script
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/one_over_script	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,104 @@
+#!/bin/bash
+
+# Make the files if they aren't already.  Useful if running this test
+# multiple times.
+
+make one_over one_over_fast
+
+# Run the tests, putting the output into files to see that they
+# performed the same computation.
+
+echo "fast 1"
+time ./one_over_1_minus_x_fast1 > output_fast1
+echo "Tensor 1"
+time ./one_over_1_minus_x1 > output1
+echo "fast 2"
+time ./one_over_1_minus_x_fast2 > output_fast2
+echo "Tensor 2"
+time ./one_over_1_minus_x2 > output2
+echo "fast 3"
+time ./one_over_1_minus_x_fast3 > output_fast3
+echo "Tensor 3"
+time ./one_over_1_minus_x3 > output3
+echo "fast 4"
+time ./one_over_1_minus_x_fast4 > output_fast4
+echo "Tensor 4"
+time ./one_over_1_minus_x4 > output4
+echo "fast 5"
+time ./one_over_1_minus_x_fast5 > output_fast5
+echo "Tensor 5"
+time ./one_over_1_minus_x5 > output5
+echo "fast 6"
+time ./one_over_1_minus_x_fast6 > output_fast6
+echo "Tensor 6"
+time ./one_over_1_minus_x6 > output6
+echo "fast 7"
+time ./one_over_1_minus_x_fast7 > output_fast7
+echo "Tensor 7"
+time ./one_over_1_minus_x7 > output7
+echo "fast 8"
+time ./one_over_1_minus_x_fast8 > output_fast8
+echo "Tensor 8"
+time ./one_over_1_minus_x8 > output8
+echo "fast 9"
+time ./one_over_1_minus_x_fast9 > output_fast9
+echo "Tensor 9"
+time ./one_over_1_minus_x9 > output9
+
+# Check that the two versions (ordinary arrays and FTensor's)
+# performed the same computation.
+
+if diff output1 output_fast1; then
+    echo PASS: one_over_1_minus_x1
+else
+    echo FAIL: one_over_1_minus_x1
+fi
+
+if diff output2 output_fast2; then
+    echo PASS: one_over_2_minus_x2
+else
+    echo FAIL: one_over_2_minus_x2
+fi
+
+if diff output3 output_fast3; then
+    echo PASS: one_over_3_minus_x3
+else
+    echo FAIL: one_over_3_minus_x3
+fi
+
+if diff output4 output_fast4; then
+    echo PASS: one_over_4_minus_x4
+else
+    echo FAIL: one_over_4_minus_x4
+fi
+
+if diff output5 output_fast5; then
+    echo PASS: one_over_5_minus_x5
+else
+    echo FAIL: one_over_5_minus_x5
+fi
+
+if diff output6 output_fast6; then
+    echo PASS: one_over_6_minus_x6
+else
+    echo FAIL: one_over_6_minus_x6
+fi
+
+if diff output7 output_fast7; then
+    echo PASS: one_over_7_minus_x7
+else
+    echo FAIL: one_over_7_minus_x7
+fi
+
+if diff output8 output_fast8; then
+    echo PASS: one_over_8_minus_x8
+else
+    echo FAIL: one_over_8_minus_x8
+fi
+
+if diff output9 output_fast9; then
+    echo PASS: one_over_9_minus_x9
+else
+    echo FAIL: one_over_9_minus_x9
+fi
+
diff -r 000000000000 -r 34fc4fd9248b tests/speed/simple.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/simple.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,41 @@
+#include <iostream>
+using namespace std;
+
+void temp(int x, int y=10)
+{
+  cout << x << " " << y << endl;
+}
+
+
+//  template<class T, int Dim>
+//  class helper;
+
+//  template<class T>
+//  class helper<T,1>
+//  {
+//  public:
+//    helper(T temp[1], T a)
+//    {
+//      temp[0]=a;
+//    }
+//  };
+
+//  template<class T, int Dim>
+//  class simp
+//  {
+//  public:
+//    T temp[Dim];
+//    simp(T a)
+//    {
+//      helper<T,Dim>(temp,a);
+//    }
+//  };
+
+int main()
+{
+  temp(10);
+  temp(10,20);
+
+//    simp<int,1> ttx(12);
+//    cout << ttx.temp[0] << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/single.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/single.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,86 @@
+#include <iostream.h>
+#include <ostream.h>
+template<char i>
+class Index
+{
+public:
+  Index() {};
+};
+
+class Tensor1;
+
+template <class A, char i>
+class Tensor1_Expr
+{
+  A *iter;
+public:
+  Tensor1_Expr(A *a): iter(a) {}
+  double & operator()(const int N)
+  {
+    return (*iter)(N);
+  }
+  double operator()(const int N) const
+  {
+    return (*iter)(N);
+  }
+
+  const A operator=(const Tensor1_Expr<Tensor1,'i'> &result)
+  {
+    cout << "equaling" << endl;
+    iter->data0=result(0);
+    iter->data1=result(1);
+    iter->data2=result(2);
+    return *iter;
+  }
+
+//    template<class B>
+//    const A operator=(const Tensor1_Expr<B,'i'> &result)
+//    {
+//      cout << "equaling" << endl;
+//      iter->data0=result(0);
+//      iter->data1=result(1);
+//      iter->data2=result(2);
+//      return iter;
+//    }
+};
+
+class Tensor1
+{
+public:
+  double data0, data1, data2;
+public:
+  Tensor1(double d0, double d1, double d2): data0(d0), data1(d1), data2(d2) {}
+  double & operator()(const int N)
+  {
+    return N==0 ? data0 : (N==1 ? data1 : data2);
+  }
+
+  double operator()(const int N) const
+  {
+    return N==0 ? data0 : (N==1 ? data1 : data2);
+  }
+
+  template<char i>
+  Tensor1_Expr<Tensor1,i> operator()(const Index<i> index)
+  {
+    return Tensor1_Expr<Tensor1,i>(this);
+  }
+
+  friend ostream& operator<<(ostream& s, const Tensor1 &a);
+};
+
+ostream& operator<<(ostream& s, const Tensor1 &a)
+{
+  return s << a.data0 << " " << a.data1 << " " << a.data2 << " ";
+}
+
+int main()
+{
+  Tensor1 y(0,1,2);
+  Tensor1 x(2,3,4);
+  const Index<'i'> i;
+
+  y(i)=x(i);
+
+  cout << y << endl;
+}
diff -r 000000000000 -r 34fc4fd9248b tests/speed/speed_test.C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/speed/speed_test.C	Sun Dec 13 19:57:42 2009 -0800
@@ -0,0 +1,127 @@
+/* Tests the difference that loop fusion makes. */
+
+const int N=60000;
+
+void fused(const double metric[6][N], double inverse[6][N])
+{
+  for(int i=0;i<N;++i)
+    {
+      double det=metric[0][i]*metric[3][i]*metric[5][i] 
+	+ metric[1][i]*metric[4][i]*metric[2][i]
+	+ metric[2][i]*metric[1][i]*metric[4][i]
+	- metric[0][i]*metric[4][i]*metric[4][i]
+	- metric[1][i]*metric[1][i]*metric[5][i]
+	- metric[2][i]*metric[3][i]*metric[2][i];
+      inverse[0][i]=
+	(metric[3][i]*metric[5][i] - metric[4][i]*metric[4][i])/det;
+      inverse[1][i]=
+	(metric[2][i]*metric[4][i] - metric[1][i]*metric[5][i])/det;
+      inverse[2][i]=
+	(metric[1][i]*metric[4][i] - metric[2][i]*metric[3][i])/det;
+      inverse[3][i]=
+	(metric[0][i]*metric[5][i] - metric[2][i]*metric[2][i])/det;
+      inverse[4][i]=
+	(metric[2][i]*metric[1][i] - metric[0][i]*metric[4][i])/det;
+      inverse[5][i]=
+	(metric[3][i]*metric[0][i] - metric[1][i]*metric[1][i])/det;
+    }
+}
+
+void fused_big(const double metric[6][N], double inverse[6][N])
+{
+  double det[N];
+  for(int i=0;i<N;++i)
+    {
+      det[i]=metric[0][i]*metric[3][i]*metric[5][i] 
+	+ metric[1][i]*metric[4][i]*metric[2][i]
+	+ metric[2][i]*metric[1][i]*metric[4][i]
+	- metric[0][i]*metric[4][i]*metric[4][i]
+	- metric[1][i]*metric[1][i]*metric[5][i]
+	- metric[2][i]*metric[3][i]*metric[2][i];
+    }
+  for(int i=0;i<N;++i)
+    {
+      inverse[0][i]=
+	(metric[3][i]*metric[5][i] - metric[4][i]*metric[4][i])/det[i];
+    }
+  for(int i=0;i<N;++i)
+    {
+      inverse[1][i]=
+	(metric[2][i]*metric[4][i] - metric[1][i]*metric[5][i])/det[i];
+    }
+  for(int i=0;i<N;++i)
+    {
+      inverse[2][i]=
+	(metric[1][i]*metric[4][i] - metric[2][i]*metric[3][i])/det[i];
+    }
+  for(int i=0;i<N;++i)
+    {
+      inverse[3][i]=
+	(metric[0][i]*metric[5][i] - metric[2][i]*metric[2][i])/det[i];
+    }
+  for(int i=0;i<N;++i)
+    {
+      inverse[4][i]=
+	(metric[2][i]*metric[1][i] - metric[0][i]*metric[4][i])/det[i];
+    }
+  for(int i=0;i<N;++i)
+    {
+      inverse[5][i]=
+	(metric[3][i]*metric[0][i] - metric[1][i]*metric[1][i])/det[i];
+    }
+}
+
+
+void unfused(const double metric[6][N], double inverse[6][N])
+{
+  double det[N];
+
+  for(int i=0;i<N;++i)
+    det[i]=metric[0][i]*metric[3][i]*metric[5][i] 
+      + metric[1][i]*metric[4][i]*metric[2][i]
+      + metric[2][i]*metric[1][i]*metric[4][i]
+      - metric[0][i]*metric[4][i]*metric[4][i]
+      - metric[1][i]*metric[1][i]*metric[5][i]
+      - metric[2][i]*metric[3][i]*metric[2][i];
+  for(int i=0;i<N;++i)
+    inverse[0][i]=
+      (metric[3][i]*metric[5][i] - metric[4][i]*metric[4][i])/det[i];
+  for(int i=0;i<N;++i)
+    inverse[1][i]=
+      (metric[2][i]*metric[4][i] - metric[1][i]*metric[5][i])/det[i];
+  for(int i=0;i<N;++i)
+    inverse[2][i]=
+      (metric[1][i]*metric[4][i] - metric[2][i]*metric[3][i])/det[i];
+  for(int i=0;i<N;++i)
+    inverse[3][i]=
+      (metric[0][i]*metric[5][i] - metric[2][i]*metric[2][i])/det[i];
+  for(int i=0;i<N;++i)
+    inverse[4][i]=
+      (metric[2][i]*metric[1][i] - metric[0][i]*metric[4][i])/det[i];
+  for(int i=0;i<N;++i)
+    inverse[5][i]=
+      (metric[3][i]*metric[0][i] - metric[1][i]*metric[1][i])/det[i];
+}
+
+#include <ctime>
+#include <iostream>
+
+using namespace std;
+int main()
+{
+  double metric[6][N], inverse[6][N];
+  
+  for(int j=0;j<6;++j)
+    for(int i=0;i<N;++i)
+      metric[j][i]=1+i+j;
+
+  const int iterations=30;
+
+  for(int i=0;i<iterations;++i)
+    {
+//        fused_big(metric,inverse);
+//        fused(metric,inverse);
+//        unfused(metric,inverse);
+    }
+}
+



More information about the CIG-COMMITS mailing list