changeset 11711:c53226c6cd5c octave-forge

linear-algebra: multidimensional arrays multiplication
author jpicarbajal
date Sun, 19 May 2013 16:18:11 +0000
parents 4f5471a9bce6
children f4c52c68f744
files main/linear-algebra/inst/ndmult.m
diffstat 1 files changed, 139 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/linear-algebra/inst/ndmult.m	Sun May 19 16:18:11 2013 +0000
@@ -0,0 +1,139 @@
+## Copyright (C) 2013 - Juan Pablo Carbajal
+##
+## 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 3 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, see <http://www.gnu.org/licenses/>.
+
+## Author: Juan Pablo Carbajal <ajuanpi+dev@gmail.com>
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{C} =} ndmult (@var{A},@var{B},@var{dim})
+## Multidimensional scalar product
+##
+## Given multidimensional arrays @var{A} and @var{B} with entries
+## A(i1,12,@dots{},in) and B(j1,j2,@dots{},jm) and the 1-by-2 dimesion array @var{dim}
+## with entries [N,K]. Assume that
+##
+## @example
+## shape(@var{A},N) == shape(@var{B},K)
+## @end example
+##
+## Then the function calculates the product
+##
+## @example
+## @group
+##
+## C (i1,@dots{},iN-1,iN+1,@dots{},in,j1,@dots{},jK-1,jK+1,@dots{},jm) =
+##  = sum_over_s A(i1,@dots{},iN-1,s,iN+1,@dots{},in)*B(j1,@dots{},jK-1,s,jK+1,@dots{},jm)
+##
+## @end group
+## @end example
+##
+## For example if @command{size(@var{A}) == [2,3,4]} and @command{size(@var{B}) == [5,3]}
+## then the @command{@var{C} = ndmult(A,B,[2,2])} produces @command{size(@var{C}) == [2,4,5]}.
+##
+## This function is useful, for example,  when calculating grammian matrices of a set of signals
+## produced from different experiments.
+## @example
+##   nT      = 100;
+##   t       = 2*pi*linspace (0,1,nT)';
+##   signals = zeros(nT,3,2); % 2 experiments measuring 3 signals at nT timestamps
+##
+##   signals(:,:,1) = [sin(2*t) cos(2*t) sin(4*t).^2];
+##   signals(:,:,2) = [sin(2*t+pi/4) cos(2*t+pi/4) sin(4*t+pi/6).^2];
+##
+##   sT(:,:,1) = signals(:,:,1)';
+##   sT(:,:,2) = signals(:,:,2)';
+##   G = ndmult (signals,sT,[1 2]);
+##
+## @end example
+## In the example G contains the scalar product of all the singals against each other.
+## This can be verified in the following way:
+## @example
+##   sA = 1 eA = 1; % First signal in first experiment;
+##   sB = 1 eA = 2; % First signal in second experiment;
+##   [G(s1,e1,s2,e2)  signals(:,s1,e1)'*signals(:,s2,e2)]
+## @end example
+## You may want to reoeder the scalar products into a 2-by-2 arrangement (representing pairs of experiments)
+## of gramian matrices. The following command @command{G = permute(G,[1 3 2 4])} does it.
+##
+## @end deftypefn
+
+function M = ndmult (A,B,dim)
+
+  dA = dim(1);
+  dB = dim(2);
+
+  sA   = size (A);
+  nA   = length (sA);
+  perA = [1:(dA-1) (dA+1):(nA-1) nA dA](1:nA);
+  Ap = permute (A, perA);
+  Ap = reshape (Ap, prod (sA(perA(1:end-1))), sA(perA(end)));
+
+  sB   = size (B);
+  nB   = length (sB);
+  perB = [dB 1:(dB-1) (dB+1):(nB-1) nB](1:nB);
+  Bp = permute (B, perB);
+  Bp = reshape (Bp, sB(perB(1)), prod (sB(perB(2:end))));
+
+  M  = Ap * Bp;
+  s = [sA(perA(1:end-1)) sB(perB(2:end))];
+  M  = squeeze (reshape (M, s));
+
+endfunction
+
+%!demo
+%! A =@(l)[1 l; 0 1];
+%! N = 5;
+%! p = linspace (-1,1,N);
+%! T = zeros (2,2,N);
+%! # A book of x-shears, one transformation per page.
+%! for i=1:N
+%!   T(:,:,i) = A(p(i));
+%! endfor
+%!
+%! # The unit square
+%! P = [0 0; 1 0; 1 1; 0 1];
+%!
+%! C = ndmult (T,P,[2 2]);
+%! # Re-order to get a book of polygons
+%! C = permute (C,[3 1 2]);
+%!
+%! try
+%!   pkg load geometry
+%!   do_plot = true;
+%! catch
+%!   printf ("Geometry package needed to plot this demo\n.");
+%!   do_plot = false;
+%! end
+%! if do_plot
+%!   clf
+%!   drawPolygon (P,"k","linewidth",2);
+%!   hold on
+%!   c = jet(N);
+%!   for i=1:N
+%!     drawPolygon (C(:,:,i),":","color",c(i,:),"linewidth",2);
+%!   endfor
+%!   axis equal
+%!   set(gca,"visible","off");
+%!   hold off
+%! endif
+%!
+%! # -------------------------------------------------
+%! # The handler A describes a parametrized planar geometrical
+%! # transformation (shear in the x-direction).
+%! # Choosing N values of the parameter we obtain a 2x2xN matrix.
+%! # We can apply all these transformations to the poligon defined
+%! # by matrix P in one operation.
+%! # The poligon resulting from the i-th parameter value is stored
+%! # in C(:,:,i).
+%! # You can plot them using the geometry package.