Convert ode45() to scilab - matlab

I'm trying to convert this script from matlab to scilab. I tried the scilab tool for conversion but it crashes with no output so I'm doing it by hand. This is what I got by changing the comments from % to //. #markovprocessfunc refers to another file I was able to convert with the scilab automatic tool.
// Markovprocess
// Main program of the markovprocess simulation
// The system is defined by the generator matrix A
// Ulf Jeppsson, January 2017
global B
// Define the duration of the simulation
disp(' ')
disp('Automation 2017, Markov processes')
disp(' ')
tend = input('Set simulation time = ');
disp(' ')
// Make a new simulation with the same A matrix?
yes = input('Keep the old A matrix? (yes=1, no=0) ');
disp(' ')
if yes>0.9
A
else
disp('Provide the A generator matrix (on the form [ x x .. ; x ...], or give the name of a predefined matrix in the Matlab workspace)')
A = input('A = ')
end
// The generator matrix A is transposed to a matrix B
B = A';
//define the initial condition p(0) (a row vector)
p = input('Define initial condition, p (row) vector (on the form [ x x .. ]) ');
// The row vector p is transposed to a column vector x0
x0 = p';
//Solve the differential equation
[t,x] = ode45(#markovprocessfunc,[0,tend],x0);
// Plot the results
plot(t,x)
grid on;
xlabel('Time')
ylabel('Probabilities')
m=length(A);
if m==2
legend('s1', 's2')
end
if m==3
legend('s1', 's2','s3')
end
if m==4
legend('s1', 's2','s3', 's4')
end
if m==5
legend('s1', 's2','s3', 's4', 's5')
end
if m==6
legend('s1', 's2','s3', 's4', 's5', 's6')
end
if m==7
legend('s1', 's2','s3', 's4', 's5', 's6', 's7')
end
if m==8
legend('s1', 's2','s3', 's4', 's5', 's6', 's7', 's8')
end
title('Markov Process')
m = size(A,1);
aa = A'; //transpose the A matrix
aa(m,:) = 1; //add ones to the last column (can be any column), i.e. the sum all p(i) must equal 1
b = zeros(m,1); //create b-vector with zeros
b(m)=1; //add a 1 to the same row as where you added 1:s to the column of A
c = aa\b; //solve the linear equation system
stationary_solution_vector = c' //transpose the solution vector back to a row vector
e_raised_to_A_times_1000 = expm(A*1000)
eigenvalues_of_A = eig(A)'
I found out that by replacing the line [t,x] = ode45(#markovprocessfunc,[0,tend],x0); with something like
t = [0 1 2 3]
x = [1 2 3 4]
the script works fine (but obviously I get the wrong result). So how do I convert ode45 to scilab? I think that after I get that done everything will work.

About the crash of mfile2sci() code converter, please do not hesitate to post a bug report # https://bugzilla.scilab.org for your user case. Things can't get better without reporting bugs.
Even without converter's crash, the ode45() instruction is not converted. But it could be (let us put this on our todo list ;-). Indeed, an equivalent of
[t,x] = ode45(#markovprocessfunc,[0,tend],x0);
is
n = 100; // or whatever value you wish
t = linspace(0, tend, n);
x = ode("rkf", x0, t(1), t, markovprocessfunc);

Related

Attempting Tridiagonal Gauss-Jordan Elimination Matlab

As you probably guessed from the title, I'm attempting to do tridiagonal GaussJordan elimination. I'm trying to do it without the default solver. My answers aren't coming out correct and I need some assistance as to where the error is in my code.
I'm getting different values for A/b and x, using the code I have.
n = 4;
#Range for diagonals
ranged = [15 20];
rangesd = [1 5];
#Vectors for tridiagonal matrix
supd = randi(rangesd,[1,n-1]);
d = randi(ranged,[1,n]);
subd = randi(rangesd,[1,n-1]);
#Creates system Ax+b
A = diag(supd,1) + diag(d,0) + diag(subd,-1)
b = randi(10,[1,n])
#Uses default solver
y = A/b
function x = naive_gauss(A,b);
#Forward elimination
for k=1:n-1
for i=k+1:n
xmult = A(i,k)/A(k,k);
for j=k+1:n
A(i,j) = A(i,j)-xmult*A(k,j);
end
b(i) = b(i)-xmult*b(k);
end
end
#Backwards elimination
x(n) = b(n)/A(n,n);
for i=n-1:-1:1
sum = b(i);
for j=i+1:n
sum = sum-A(i,j)*x(j);
end
x(i) = sum/A(i,i)
end
end
x
Your algorithm is correct. The value of y that you compare against is wrong.
you have y=A/b, but the correct syntax to get the solution of the system should be y=A\b.

Finding matrix inverse by Gaussian Elimination With Partial Pivoting

Hello guys I am writing program to compute determinant(this part i already did) and Inverse matrix with GEPP. Here problem arises since i have completely no idea how to inverse Matrix using GEPP, i know how to inverse using Gauss Elimination ([A|I]=>[I|B]). I have searched through internet but still no clue, could you please explain me?
Here is my matlab code (maybe someone will find it useful), as of now it solves AX=b and computes determinant:
function [det1,X ] = gauss_czesciowy( A, b )
%GEPP
perm=0;
n = length(b);
if n~=m
error('vector has wrong size');
end
for j = 1:n
p=j;
% choice of main element
for i = j:n
if abs(A(i,j)) >= abs(A(p,j))
p = i;
end
end
if A(p,j) == 0
error('Matrix A is singular');
end
%rows permutation
t = A(p,:);
A(p,:) = A(j,:);
A(j,:) = t;
t = b(p);
b(p) = b(j);
b(j) = t;
if~(p==i)
perm=perm+1;
end
% reduction
for i = j+1:n
t = (A(i,j)/A(j,j));
A(i,:) = A(i,:)-A(j,:)*t;
b(i) = b(i)-b(j)*t;
end
end
%determinant
mn=1;
for i=1:n
mn=mn*A(i,i);
end
det1=mn*(-1)^perm;
% solution
X = zeros(1,n);
X(n) = b(n)/A(n,n);
if (det1~=0)
for i = 1:n
s = sum( A(i, (i+1):n) .* X((i+1):n) );
X(i) = (b(i) - s) / A(i,i);
end
end
end
Here is the algorithm for Guassian elimination with partial pivoting. Basically you do Gaussian elimination as usual, but at each step you exchange rows to pick the largest-valued pivot available.
To get the inverse, you have to keep track of how you are switching rows and create a permutation matrix P. The permutation matrix is just the identity matrix of the same size as your A-matrix, but with the same row switches performed. Then you have:
[A] --> GEPP --> [B] and [P]
[A]^(-1) = [B]*[P]
I would try this on a couple of matrices just to be sure.
EDIT: Rather than empirically testing this, let's reason it out. Basically what you are doing when you switch rows in A is you are multiplying it by your permutation matrix P. You could just do this before you started GE and end up with the same result, which would be:
[P*A|I] --> GE --> [I|B] or
(P*A)^(-1) = B
Due to the properties of the inverse operation, this can be rewritten:
A^(-1) * P^(-1) = B
And you can multiply both sides by P on the right to get:
A^(-1) * P^(-1)*P = B*P
A^(-1) * I = B*P
A^(-1) = B*P

change filter(B,A, X) in matlab and Out of memoy Error

this post is related to my previous question : image processing in matlab
as I have uploaded my algorithme there.
the think is that I am trying to change the filtering part of the code.
in matlab filter.m function can accpet filter(B, A, my pixels evolutions in Time) and it return me the filtered values.
but at the moment I have to pass the the whole time series together.
but the problem is that now I want to change the code in a way instead of passing the whole timeseries into the filter, I want to pass one value at a time, but I want filter function treat the value like the nth value not the first valu.
I have created a sudo code, as I am injecting one picture into the code, but I dont know how can change the filtering part., any body has any idea??
clear all
j=1;
for i=0:3000
str = num2str(i);
str1 = strcat(str,'.mat');
load(str1);
D{j}=A(20:200,130:230);
j=j+1;
end
N=5;
w = [0.00000002 0.05;0.05 0.1;0.1 0.15;0.15 0.20;
0.20 0.25;0.25 0.30;0.30 0.35;0.35 0.40;
0.40 0.45;0.45 0.50;0.50 0.55;0.55 0.60;
0.60 0.65;0.65 0.70;0.70 0.75;0.75 0.80;
0.80 0.85;0.85 0.90;0.90 0.95;0.95 0.99999999];
for ind=1:20
wn = w(ind,:);
[b,a] = butter(N,wn);
bCoeff(ind,:)=b;
aCoeff(ind,:)=a;
end
ts=[];
sumLastImages=[];
for k=1:10 %number of images
for bands=1:20 %number of bands
for i=1:10 %image h
for j=1:10 %image w
pixelValue = D{k}(i,j);
% reflectivity elimination
% for the current pixel, have the summation of the same position from before
% images and create a mean value base on the temporal values
sumLastImages(i,j)=pixelValue+sumLastImages(i,j);
meanValue = sumLastImages(i,j)/k;
if(meanValue==0)
filteredimages{bands}(i,j)=0;
continue;
else
pixel_calculated_meanvalue = pixelValue/meanValue;
end
% filter part that need to be changed, and because we are adding
% one value then the reutrn of the filter is one too
ts_f = filter(bCoeff(bands,:), aCoeff(bands,:), ...
pixel_calculated_meanvalue);
filteredimages{bands}(i,j)=ts_f;
end
end
finalImagesSummation{bands}(:,:) = ...
(filteredimages{bands}(:,:)^2)+finalImagesSummation{bands}(:,:);
finalImages{bands}(:,:)=finalImagesSummation/k;
end
end
EDIT
I managed to change the code like this, which now I load the fist 200 images, and after that I am able to inject the images one by one into the filter, but now the problem is that I am getting "Out of memory. Type HELP MEMORY for your options." error for big
images.
here is my code any idea to efficent the code :
%%
cd('D:\MatlabTest\06-06-Lentils');
clear all
%%
N=5;
W = [0.0 0.10;0.10 0.20;0.20 0.30;0.30 0.40;
0.40 0.50;0.50 0.60 ;0.60 0.70;0.70 0.80 ;
0.80 0.90;0.90 1.0];
[bCoeff{1},aCoeff{1}] = butter(N,0.1,'Low');
for ind=2:9
wn = W(ind,:);
[b,a] = butter(N,wn);
bCoeff{ind}=b;
aCoeff{ind}=a;
end
[bCoeff{10},aCoeff{10}] = butter(N,0.9,'high');
%%
j=1;
D = zeros(200,380,320);
T = 200;
K = 0:399;
l = T+1;
Yout = cell(1,10);
figure;
for i = 1:length(K)-200
disp(i)
if i == 1
for j = 1:T
str = int2str(K(1)+j-1);
str1 = strcat(str,'.mat');
load(str1);
D(j,1:380,1:320) = A;
end
else
str = int2str(l);
str1 = strcat(str,'.mat');
load(str1);
temp = D(2:200,1:380,1:320) ;
temp(200,1:380,1:320) = A;
D = temp;
clear temp
l = l +1;
end
for p = 1:380
for q = 1:320
x = D(:,p,q) - mean(D(:,p,q));
for k = 1:10
temp = filter(bCoeff{k},aCoeff{k},x);
if i == 1
Yout{k}(p,q) = mean(temp);
else
Yout{k}(p,q) = (Yout{k}(p,q) + mean(temp))/2;
end
end
end
end
for k = 1:10
subplot(5,2,k)
subimage(Yout{k}*1000,[0 255]);
color bar
colormap jet
end
pause(0.01);
end
disp('Done Loading...')
No need to rewrite the filter function, there is a simple solution!
If you want to feed filter with one sample at a time, you need to pass the state parameters as well so that each input sample is processed depending on its predecessor. After filtering, the new state is actually returned as a second parameter, so that most of the work is already done by MATLAB for you. This is good news!
For the sake of readability, allow me to temporarily replace your variable names with simple letters:
a = aCoeff(bands, :);
b = bCoeff(bands, :);
x = pixel_calculated_meanvalue;
ts_f is represented by y.
And so, this:
y = filter(b, a, x);
is actually equivalent to this:
N = numel(x);
y = zeros(N, 1); %# Preallocate memory for output
z = zeros(max(length(a), length(b)) - 1, 1); %# This is the initial filter state
for i = 1:N
[y(i), z] = filter(b, a, x(i), z);
end
You can check for yourself that the result is the same!
For your example, the code would be:
N = numel(pixel_calculated_meanvalue);
ts_f = zeros(N, 1);
z = zeros(max(length(aCoeff(bands, :)), length(bCoeff(bands, :))) - 1, 1);
for i = 1:N
[ts_f(i), z] = filter(bCoeff(bands, :), aCoeff(bands, :), ...
pixel_calculated_meanvalue(i), z);
end
With this method you can process one input sample at a time, just make sure you store the last filter state after every filter call. If you plan on using multiple filters, you'll have to store a state vector per filter!
Overview
If all you want to have is an IIR filter, which you can feed incrementally, i.e. where you do not have to supply the full vector at once, you can simply implement your own function and use either persistent variables.
Simple approach
The code snippet below defines a function myFilter, which makes use of persistent
variables, which you can control with the following commands:
init: set up the IIR coefficients
getA: returns the A coefficients, i.e. the outputweights
getB: returns the B coefficients, i.e. the input weights
getX: returns the stored input data x[0], x[1], ... x[M]
getY: returns the output data y[0], y[1], ... y[N]
getCurrentY: returns the last output data y[N]
Here is the function:
function result = myFilter(varargin)
% myFilter A simple IIR filter which can be fed incrementally.
%
% The filter is controlled with the following commands:
% myFilter('init', B, A)
% Initializes the coefficients B and A. B are the weights for the
% input and A for the output.
% myFilter('reset')
% Resets the input and output buffers to zero.
% A = myFilter('getA')
% B = myFilter('getB')
% Returns the filter coefficients A and B, respectively.
% x = myFilter('getX')
% y = myFilter('getY')
% Returns the buffered input and output vectors.
% y = myFilter('getCurrentY')
% Returns the current output value.
% myFilter(x)
% Adds the new value x as input to the filter and updates the
% output.
persistent Bcoeff
persistent Acoeff
persistent x
persistent y
if ischar(varargin{1})
% This is a command.
switch varargin{1}
case 'init'
Bcoeff = varargin{2};
Acoeff = varargin{3};
Bcoeff = Bcoeff / Acoeff(1);
Acoeff = Acoeff / Acoeff(1);
x = zeros(size(Bcoeff));
y = zeros(1, length(Acoeff) - 1);
return
case 'reset'
x = zeros(size(Bcoeff));
y = zeros(1, length(Acoeff) - 1);
return
case 'getA'
result = Acoeff;
return
case 'getB'
result = Bcoeff;
return
case 'getX'
result = x;
return
case 'getY'
result = y;
return
case 'getCurrentY'
result = y(1);
return
otherwise
error('Unknown command');
end
end
% A new value has to be filtered.
xnew = varargin{1};
x = [xnew, x(1:end-1)];
ynew = sum(x .* Bcoeff) - sum(y .* Acoeff(2:end));
y = [ynew, y(1:end-1)];
end
And a usage example:
% Define the filter coefficients. Bcoeff acts on the input, Acoeff on
% the output.
Bcoeff = [4, 5];
Acoeff = [1, 2, 3];
% Initialize the filter.
myFilter('init', Bcoeff, Acoeff);
% Add a value to be filtered.
myFilter(10)
myFilter('getCurrentY')
ans =
40
% Add another one.
myFilter(20)
myFilter('getCurrentY')
ans =
50
% And a third one.
myFilter(30)
myFilter('getCurrentY')
ans =
0
% Compare with the Matlab filter function.
filter(Bcoeff, Acoeff, [10 20 30])
ans =
40 50 0
The drawback of this approach is that it is only possible to have one active filter
simultaneously. This is problematic e.g. in your question, where you have different
filters which are updated in an alternating fashion.
Advanced approach
In order to operate multiple filters simultatenously, you need some way to identify
the filter. The solution I present here works with handles. A handle is simple an
integer. To be more precise, it is actually an index into a persistent array, which
itself holds the filter state, i.e. the filter coefficients and the buffers for the
input and the output.
The calling syntax is a bit more complicated, because you have to pass a handle. However,
it is possible that multiple filters are active simultaneously.
function result = myFilterH(varargin)
% myFilterH A simple IIR filter which can be fed incrementally.
% Operates on a filter handle.
%
% The filter is controlled with the following commands:
% handle = myFilterH('create')
% Creates a new filter handle.
% myFilterH(handle, 'init', B, A)
% Initializes the coefficients B and A. B are the weights for the
% input and A for the output. handle identifies the filter.
% myFilterH(handle, 'reset')
% Resets the input and output buffers to zero.
% A = myFilterH(handle, 'getA')
% B = myFilterH(handle 'getB')
% Returns the filter coefficients A and B, respectively.
% x = myFilterH(handle, 'getX')
% y = myFilterH(handle, 'getY')
% Returns the buffered input and output vectors.
% y = myFilterH(handle, 'getCurrentY')
% Returns the current output value.
% myFilterH(handle, x)
% Adds the new value x as input to the filter and updates the
% output.
persistent handles
if ischar(varargin{1})
if strcmp(varargin{1}, 'create')
if isempty(handles)
handles = struct('x', [], 'y', [], 'A', [], 'B', []);
result = 1;
else
result = length(handles) + 1;
handles(result).x = [];
end
return
else
error('First argument must be a filter handle or ''create''');
end
end
% The first input should be the handles(hIdx).
hIdx = varargin{1};
if hIdx < 0 || hIdx > length(handles)
error('Invalid filter handle')
end
if ischar(varargin{2})
% This is a command.
switch varargin{2}
case 'init'
handles(hIdx).B = varargin{3};
handles(hIdx).A = varargin{4};
handles(hIdx).B = handles(hIdx).B / handles(hIdx).A(1);
handles(hIdx).A = handles(hIdx).A / handles(hIdx).A(1);
handles(hIdx).x = zeros(size(handles(hIdx).B));
handles(hIdx).y = zeros(1, length(handles(hIdx).A) - 1);
return
case 'reset'
handles(hIdx).x = zeros(size(handles(hIdx).B));
handles(hIdx).y = zeros(1, length(handles(hIdx).A) - 1);
return
case 'getA'
result = handles(hIdx).A;
return
case 'getB'
result = handles(hIdx).B;
return
case 'getX'
result = handles(hIdx).x;
return
case 'getY'
result = handles(hIdx).y;
return
case 'getCurrentY'
result = handles(hIdx).y(1);
return
otherwise
error('Unknown command');
end
end
% A new value has to be filtered.
xnew = varargin{2};
handles(hIdx).x = [xnew, handles(hIdx).x(1:end-1)];
ynew = sum(handles(hIdx).x .* handles(hIdx).B) ...
- sum(handles(hIdx).y .* handles(hIdx).A(2:end));
handles(hIdx).y = [ynew, handles(hIdx).y(1:end-1)];
end
And the example:
% Define the filter coefficients.
Bcoeff = [4, 5];
Acoeff = [1, 2, 3];
% Create new filter handles.
fh1 = myFilterH('create');
fh2 = myFilterH('create');
% Initialize the filter handle. Note that reversing Acoeff and Bcoeff creates
% two totally different filters.
myFilterH(fh1, 'init', Bcoeff, Acoeff);
myFilterH(fh2, 'init', Acoeff, Bcoeff);
% Add a value to be filtered.
myFilterH(fh1, 10);
myFilterH(fh2, 10);
[myFilterH(fh1, 'getCurrentY'), myFilterH(fh2, 'getCurrentY')]
ans =
40.0000 2.5000
% Add another one.
myFilterH(fh1, 20);
myFilterH(fh2, 20);
[myFilterH(fh1, 'getCurrentY'), myFilterH(fh2, 'getCurrentY')]
ans =
50.0000 6.8750
% And a third one.
myFilterH(fh1, 30);
myFilterH(fh2, 30);
[myFilterH(fh1, 'getCurrentY'), myFilterH(fh2, 'getCurrentY')]
ans =
0 16.4063
% Compare with the Matlab filter function.
filter(Bcoeff, Acoeff, [10 20 30])
ans =
40 50 0
filter(Acoeff, Bcoeff, [10 20 30])
ans =
2.5000 6.8750 16.4063
Using it for your example
To use the advanced approach in your example, you could first create an array of filters:
fh = [];
for ind = 1:20
wn = w(ind,:);
[b,a] = butter(N,wn);
fh(ind) = myFilterH('create');
myFilterH(fh(ind), 'init', b, a);
end
Later on in the filter part simply add your value to all of the filters. However, for this
you also need to reverse the loops because right now you would need one filter per
band per pixel. If you loop over pixels first and then over bands, you can reuse the filters:
for height = 1:10
for width = 1:10
for bands = 1:20
myFilterH(fh(bands), 'reset');
for k = 1:10
[...]
ts_f = myFilterH(fh(bands), ...
pixel_calculated_meanvalue);
filteredimages{bands}(i,j) = myFilterH(fh(bands), 'getCurrentY');
end
end
end
end
Hope that helps!
If I understand the question correctly, the crux is "How do I return multiple things from a Matlab function?"
You can return multiple things like this:
function [a, b, np, x, y] = filter(ord, a, b, np, x, y)
%code of function here
%make some changes to a, b, np, x, and y
end
If you want to call the filter from another function and catch its return values, you can do this:
function [] = main()
%do some stuff, presumably generate initial values for ord, a, b, np, x, y
[new_a, new_b, new_np, new_x, new_y] = filter(ord, a, b, np, x, y)
end
In short, if you do function [x, y] = myfunc(a, b), then myfunc returns both x and y.

Looping with two variables from a vector

I have a 30-vector, x where each element of x follows a standardised normal distribution.
So in Matlab,
I have:
for i=1:30;
x(i)=randn;
end;
Now I want to create 30*30=900 elements from vector, x to make a 900-vector, C defined as follows:
I am unable to do the loop for two variables (k and l) properly. I have:
for k=1:30,l=1:30;
C(k,l)=(1/30)*symsum((x(i))*(x(i-abs(k-l))),1,30+abs(k-l));
end
It says '??? Undefined function or method 'symsum' for input arguments of type
'double'.'
I hope to gain from this a 900-vector, C which I will then rewrite as a matrix. The reason I have using two indices k and l instead of one is because I eventually want these indices to denote the (k,l)-entry of such a matrix so it is important that that my 900-vector will be in the form of C = [ row 1 row 2 row 3 ... row 30 ] so I can use the reshape tool i.e.
C'=reshape(C,30,30)
Could anyone help me with the code for the summation and getting such a 900 vector.
Let's try to make this a bit efficient.
n = 30;
x = randn(n,1);
%# preassign C for speed
C = zeros(n);
%# fill only one half of C, since it's symmetric
for k = 2:n
for l = 1:k-1
%# shift the x-vector by |k-l| and sum it up
delta = k-l; %# k is always larger than l
C(k,l) = sum( x(1:end-delta).*x(1+delta:end) );
end
end
%# fill in the other half of C
C = C + C';
%# add the diagonal (where delta is 0, and thus each
%# element of x is multiplied with itself
C(1:n+1:end) = sum(x.^2);
It seems to me that you want a matrix C of 30x30 elements.
Given the formula that you provided I would do
x = randn(1,30)
C = zeros(30,30)
for k=1:30
for l=1:30
v = abs(k-l);
for i =1:30-v
C(k,l) = C(k,l) + x(i)*x(i+v);
end
end
end
if you actually need the vector you can obtain it from the matrix.

Vectorizing sums of different diagonals in a matrix

I want to vectorize the following MATLAB code. I think it must be simple but I'm finding it confusing nevertheless.
r = some constant less than m or n
[m,n] = size(C);
S = zeros(m-r,n-r);
for i=1:m-r+1
for j=1:n-r+1
S(i,j) = sum(diag(C(i:i+r-1,j:j+r-1)));
end
end
The code calculates a table of scores, S, for a dynamic programming algorithm, from another score table, C.
The diagonal summing is to generate scores for individual pieces of the data used to generate C, for all possible pieces (of size r).
Thanks in advance for any answers! Sorry if this one should be obvious...
Note
The built-in conv2 turned out to be faster than convnfft, because my eye(r) is quite small ( 5 <= r <= 20 ). convnfft.m states that r should be > 20 for any benefit to manifest.
If I understand correctly, you're trying to calculate the diagonal sum of every subarray of C, where you have removed the last row and column of C (if you should not remove the row/col, you need to loop to m-r+1, and you need to pass the entire array C to the function in my solution below).
You can do this operation via a convolution, like so:
S = conv2(C(1:end-1,1:end-1),eye(r),'valid');
If C and r are large, you may want to have a look at CONVNFFT from the Matlab File Exchange to speed up calculations.
Based on the idea of JS, and as Jonas pointed out in the comments, this can be done in two lines using IM2COL with some array manipulation:
B = im2col(C, [r r], 'sliding');
S = reshape( sum(B(1:r+1:end,:)), size(C)-r+1 );
Basically B contains the elements of all sliding blocks of size r-by-r over the matrix C. Then we take the elements on the diagonal of each of these blocks B(1:r+1:end,:), compute their sum, and reshape the result to the expected size.
Comparing this to the convolution-based solution by Jonas, this does not perform any matrix multiplication, only indexing...
I would think you might need to rearrange C into a 3D matrix before summing it along one of the dimensions. I'll post with an answer shortly.
EDIT
I didn't manage to find a way to vectorise it cleanly, but I did find the function accumarray, which might be of some help. I'll look at it in more detail when I am home.
EDIT#2
Found a simpler solution by using linear indexing, but this could be memory-intensive.
At C(1,1), the indexes we want to sum are 1+[0, m+1, 2*m+2, 3*m+3, 4*m+4, ... ], or (0:r-1)+(0:m:(r-1)*m)
sum_ind = (0:r-1)+(0:m:(r-1)*m);
create S_offset, an (m-r) by (n-r) by r matrix, such that S_offset(:,:,1) = 0, S_offset(:,:,2) = m+1, S_offset(:,:,3) = 2*m+2, and so on.
S_offset = permute(repmat( sum_ind, [m-r, 1, n-r] ), [1, 3, 2]);
create S_base, a matrix of base array addresses from which the offset will be calculated.
S_base = reshape(1:m*n,[m n]);
S_base = repmat(S_base(1:m-r,1:n-r), [1, 1, r]);
Finally, use S_base+S_offset to address the values of C.
S = sum(C(S_base+S_offset), 3);
You can, of course, use bsxfun and other methods to make it more efficient; here I chose to lay it out for clarity. I have yet to benchmark this to see how it compares with the double-loop method though; I need to head home for dinner first!
Is this what you're looking for? This function adds the diagonals and puts them into a vector similar to how the function 'sum' adds up all of the columns in a matrix and puts them into a vector.
function [diagSum] = diagSumCalc(squareMatrix, LLUR0_ULLR1)
%
% Input: squareMatrix: A square matrix.
% LLUR0_ULLR1: LowerLeft to UpperRight addition = 0
% UpperLeft to LowerRight addition = 1
%
% Output: diagSum: A vector of the sum of the diagnols of the matrix.
%
% Example:
%
% >> squareMatrix = [1 2 3;
% 4 5 6;
% 7 8 9];
%
% >> diagSum = diagSumCalc(squareMatrix, 0);
%
% diagSum =
%
% 1 6 15 14 9
%
% >> diagSum = diagSumCalc(squareMatrix, 1);
%
% diagSum =
%
% 7 12 15 8 3
%
% Written by M. Phillips
% Oct. 16th, 2013
% MIT Open Source Copywrite
% Contact mphillips#hmc.edu fmi.
%
if (nargin < 2)
disp('Error on input. Needs two inputs.');
return;
end
if (LLUR0_ULLR1 ~= 0 && LLUR0_ULLR1~= 1)
disp('Error on input. Only accepts 0 or 1 as input for second condition.');
return;
end
[M, N] = size(squareMatrix);
if (M ~= N)
disp('Error on input. Only accepts a square matrix as input.');
return;
end
diagSum = zeros(1, M+N-1);
if LLUR0_ULLR1 == 1
squareMatrix = rot90(squareMatrix, -1);
end
for i = 1:length(diagSum)
if i <= M
countUp = 1;
countDown = i;
while countDown ~= 0
diagSum(i) = squareMatrix(countUp, countDown) + diagSum(i);
countUp = countUp+1;
countDown = countDown-1;
end
end
if i > M
countUp = i-M+1;
countDown = M;
while countUp ~= M+1
diagSum(i) = squareMatrix(countUp, countDown) + diagSum(i);
countUp = countUp+1;
countDown = countDown-1;
end
end
end
Cheers