%mathpiper,def="Dot"

//////
// dot product for vectors and matrices (dr)
//////

LocalSymbols(Dot0,Dot1)
[
// vector . vector
Dot(t1_IsVector,t2_IsVector)_(Length(t1)=Length(t2)) <--
   Dot0(t1,t2,Length(t1));

// matrix . vector
Dot(t1_IsMatrix,t2_IsVector)_(Length(t1[1])=Length(t2)) <--
[
   Local(i,n,m,result);
   n:=Length(t1);
   m:=Length(t2);
   result:=List();
   For(i:=1,i<=n,i++)
	DestructiveInsert(result,1,Dot0(t1[i],t2,m));
   DestructiveReverse(result);
];

// vector . matrix
Dot(t1_IsVector,t2_IsMatrix)_(Length(t1)=Length(t2)
                               And Length(t2[1])>0) <--
   Dot1(t1,t2,Length(t1),Length(t2[1]));

// matrix . matrix
Dot(t1_IsMatrix,t2_IsMatrix)_(Length(t1[1])=Length(t2)
                                  And Length(t2[1])>0) <--
[
   Local(i,n,k,l,result);
   n:=Length(t1);
   k:=Length(t2);
   l:=Length(t2[1]);
   result:=List();
   For(i:=1,i<=n,i++)
      DestructiveInsert(result,1,Dot1(t1[i],t2,k,l));
   DestructiveReverse(result);
];

// vector . vector
Dot0(_t1,_t2,_n) <--
[
   Local(i,result);
   result:=0;
   For(i:=1,i<=n,i++)
      result:=result+t1[i]*t2[i];
   result;
];

// vector . matrix
// m vector length
// n number of matrix cols
Dot1(_t1,_t2,_m,_n) <--
[
   Local(i,j,result);
   result:=ZeroVector(n);
   For(i:=1,i<=n,i++)
      For(j:=1,j<=m,j++)
         result[i]:=result[i]+t1[j]*t2[j][i];
   result;
];

]; // LocalSymbols(Dot0,Dot1)

%/mathpiper



%mathpiper_docs,name="Dot",categories="User Functions;Linear Algebra"
*CMD Dot --- get dot product of tensors
*STD
*CALL
	Dot(t1,t2)

*PARMS

{t1,t2} -- tensor lists (currently only vectors and matrices are supported)

*DESC

{Dot} returns the dot (aka inner) product of two tensors t1 and t2. The last
index of t1 and the first index of t2 are contracted. Currently {Dot} works
only for vectors and matrices. {Dot}-multiplication of two vectors, a matrix
with a vector (and vice versa) or two matrices yields either a scalar, a
vector or a matrix.

*E.G.

In> Dot({1,2},{3,4})
Result: 11;
In> Dot({{1,2},{3,4}},{5,6})
Result: {17,39};
In> Dot({5,6},{{1,2},{3,4}})
Result: {23,34};
In> Dot({{1,2},{3,4}},{{5,6},{7,8}})
Result: {{19,22},{43,50}};

*SEE Outer, Cross, IsScalar, IsVector, IsMatrix
%/mathpiper_docs