lapack - addressing for fully packed rectangular format - lapack

I would like to use the LAPACK routines for factorisation and inversion of matrices using the fully packed rectangular format, as this requires only n(n+1)/2 elements to be stored for a symmetric nxn matrix. So far, I am setting up the matrix in 'packed' format and transform it calling routine DTPTTF. However, this requires a second array. I would like to build my matrix directly in fully packed rectangular format (to save on space) - is there an 'addressing' function which will give me the position of the i,j-th element? or could somebody point me to the relevant formula?

to partly answer my own question: inspecting the source code of DTPTTF and the example given therein, I've worked out the adress for one of the four possible constellations (the only one I need), namely uplo ='L' and trans ='N'. below is my fortran function:
! ==================================== ! returns address for RFP format
integer function ijfprf( ii, jj, n ) ! for row jj and column ii
! ==================================== ! for UPLO = 'L' and TRANSR = 'N' only!
implicit none
integer, intent(in) :: ii, jj, n
integer :: i, j, k, n1, k1
if( ii <= jj ) then
i = ii; j = jj
else
i = jj; j = ii
end if
k = n/2
if( mod(n,2) == 0 ) then ! n even
n1 = n + 1
if( i <= k ) then
ijfprf = 1 + (i - 1) * n1 + j
else
ijfprf = ( j - k - 1 ) * n1 + i - k
end if
else ! n odd
k1 = k + 1
if( i > k1 ) then
ijfprf = ( j - k1 ) * n + i - k1
else
ijfprf = ( i - 1 ) * n + j
end if
end if
return
end function ijfprf

Related

Merge sort in scilab

I implemented merge sort in scilab with the following code:
function x = mergesortre (x)
n = length (x);
if ( n > 1 ) then
m = floor (n/2);
p = n-m;
x1 = mergesortre ( x(1:m) );
x2 = mergesortre ( x(m+1:n) );
x = merge ( x1 , x2 );
end
endfunction
function [x] = merge ( x1 , x2 )
n1 = length (x1);
n2 = length (x2);
n = n1 + n2;
x = [];
i = 1
j = 1
k = 1
while(j<=n1 && k<=n2)
if x1(j)>=x2(k)
x(i)=x2(k);
k=k+1;
i=i+1;
elseif x1(j)<x2(k)
x(i)=x1(j);
j=j+1;
i=i+1;
end
end
if (j > n1) then
x(i+1:n) = x2(k:n2);
else
x(i+1:n) = x1(j:n1);
end
endfunction
a=[5,4,3,2,1];
x=mergesortre(a);
disp x;
However in when i try to see the sorted array using the terminal window its showing only the first element,for example if my array is [5,4,3,2,1] its only giving output as 1. I need help understanding what i did wrong.
Your error is in the merge function. As i is already incremented at the end of the loop you have to concatenate starting at i:
if (j > n1) then
x(i:n) = x2(k:n2);
else
x(i:n) = x1(j:n1);
end
A recursive algorithm needs a termination condition. There is no such condition in your function mergesortre. It's likely because the declaration of your function does not used the input argument x. Try to change it like this:
function [a] = mergesortre ( a )
I guess you wanted to use a as an input and output argument.

Need help in matrix dimension while converting from fortran to matlab

I have been working on a fortran code to convert it into the matlab. I am facing some issues with dimensioning! Following is the code which is giving me error
do 10 p = 1,m
d(p) = 0.d0
d(p) = x - x1(i,p) - x2(i,p) -
& double_sum(i,p,n,m,str,mot)
10 continue
double_sum = 0.d0
do 10 j = 1,m
do 20 k = 1,n
if (k .eq. i) then
else
double_sum = double_sum + mot(k,j,i,p)*str(k,j)
endif
20 continue
10 continue
to which I converted it into matlab as:
for p=1:m
d(p)=0;
double_sum = 0;
for j=1:m
for k=1:n
if k==i
else
double_sum = double_sum + mot(k,j,i,p)*str(k,j);
end
end
end
d(p)=x - x1(i,p) - x2(i,p)-double_sum(i,p,n,m,str,mot);
end
I am getting error of "index exceeding matrix".
The error line is for this part of my code:
d(p)=x - x1(i,p) - x2(i,p)-double_sum(i,p,n,m,str,mot);
So if I ignore double_sum(i,p,n,m,str,mot); this part, code runs perfectly.
I know the double_sum matrix is of 6D which looks suspicious to me, but I would like to have your support to successfully port this piece of fortran code.
Note:Asked the same question on matlab forum. But stackoverflow have more chances of people worked on fortran 77. Hence asking it here.
If the Fortran code in the Question is really everything, it may be a very rough snippet that explains how to calculate array d(:)
do 10 p = 1, m
d( p ) = x - x1( i, p ) - x2( i, p ) - double_sum( i, p, n, m, str, mot )
10 continue
with a function double_sum() defined by
double precision function double_sum( i, p, n, m, str, mot )
implicit none
integer, intent(in) :: i, p, n, m
double precision, intent(in) :: str( n, m ), mot( n, m, ?, ? )
integer j, k
double_sum = 0.d0
do 10 j = 1, m
do 20 k = 1, n
if (k .eq. i) then
else
double_sum = double_sum + mot( k, j, i, p ) * str( k, j )
endif
20 continue
10 continue
end
though it is definitely better to find the original Fortran source to check the context...(including how i and d(:) are used outside this code). Nevertheless, if we use the above interpretation, the corresponding Matlab code may look like this:
for p = 1:m
double_sum = 0;
for j = 1:m
for k = 1:n
if k == i
else
double_sum = double_sum + mot( k, j, i, p ) * str( k, j );
end
end
end
d( p ) = x - x1( i, p ) - x2( i, p ) - double_sum; % <--- no indices for double_sum
end
There is also a possibility that double_sum() is a recursive function, but because we cannot use the function name as the result variable (e.g. this page), it may be OK to exclude that possibility (so the Fortran code has two scopes, as suggested by redundant labels 10).
There is an error in your loops. The fortran code runs one loop over p=1:m, whose end is marked by the continue statement. Then, two nested loops over j and k follow.
Assuming, you know the size of all your arrays beforehand and have initialized them to the correct size (which may not be the case given your error statement) this is more along the lines of the fortran example you posted.
d = zeros(size(d));
for p=1:m
d(p)=x - x1(i,p) - x2(i,p)-double_sum(i,p,n,m,str,mot);
end
% add a statement here to set all entries of double sum to zero
double_sum = zeros(size(double_sum))
for j=1:m
for k=1:n
if k==i
else
double_sum = double_sum + mot(k,j,i,p)*str(k,j);
end
end
end
It is a little hard to give advice without knowledge of more parts of the code. are mot and str and double_sum functions? Arrays? The ambiguous choice of brackets in those two languages are hardly OPs fault, but make it necessary to provide further input.

How to find an arbitrary perpendicular vector of another vector in MATLAB?

I need to create arbitrary perpendicular vector n with components (a, b, c) to another known vector k with components (x,y,z).
The following code creates arbitrary vector n, but I need random numbers for components in the range [-inf, inf] how can I acheive that? (because otherwise vector components created may not exceed some value in given case 10^11 ) Or maybe concept "arbitrary vector" does not require that?
function [a,b,c] = randomOrghogonalVector(x,y,z)
a = 0;
b = 0;
c = 0;
randomDistr = rand * 10^11 * 2 - 10^11; % issue 1
% excluding trivial solution
if x == 0 && y == 0 && z ==0
a = NaN; b = a; c = a;
else
if z ~=0
a = randomDistr;
b = randomDistr;
c = - (x * a + b * y ) / z;
else
if z == 0 && x ~= 0
c = randomDistr;
b = randomDistr;
a = - (z * c + b * y ) / x;
else
if z == 0 && x == 0 && y ~= 0
c = randomDistr;
a = randomDistr;
b = - (z * c + a * x ) / y;
end
end
end
end
The easiest solution I see is to first find a random vector that is orthogonal to your original vector, and then give it a random length. In Matlab, this can be done by defining the following function
function [a, b, c] = orthoVector(x, y, z)
xin = [x;y;z];
e = xin;
while ((e'*xin)==xin'*xin)
e = 2.*rand(3,1)-1;
end
xout = cross(xin, e);
xout = 1.0/(rand()) * xout;
a = xout(1);
b = xout(2);
c = xout(3);
end
Line-by-line, here's what I'm doing:
you asked for this format [a,b,c] = f(x,y,z). I would recommend using function xout = orthoVector(xin), which would make this code even shorter.
Since Matlab handles vectors best as vectors, I'm creating vector xin.
e will be one random vector, different from xin used to compute the orthogonal vector. Since we're dealing with random vectors, we initialize it to be equal to xin.
For this algorithm to work, we need to make sure that e and xin are pointing in different directions. Until this is the case...
...create a new random vector e. Note that rand will give values between 0 and 1. Thus, each component of e will be between -1 and 1.
Ok, if we end, e and xin are pointing in different directions
Our vector xout will be orthogonal to xin and e.
Let's multiply vector xout by a random number between 1 and "very large"
a is first component of xout
b is second component of xout
c is third component of xout
all done.
Optional: if you want to have very large vectors, you could replace line 8 by
xout = exp(1./rand())/(rand()) * xout;
This will give you a very large spread of values.
Hope this helps, cheers!

matlab: convert a string of hex values to a decimal value?

I wrote functions to convert 100,000 hex strings to values, but it takes 10 seconds to perform on the whole array. Does Matlab have a function to do this, so that it is faster, ... ie: less than 1 second for the array?
function x = hexstring2dec(s)
[m n] = size(s);
x = zeros(1, m);
for i = 1 : m
for j = n : -1 : 1
x(i) = x(i) + hexchar2dec(s(i, j)) * 16 ^ (n - j);
end
end
function x = hexchar2dec(c)
if c >= 48 && c <= 57
x = c - 48;
elseif c >= 65 && c <= 70
x = c - 55;
elseif c >= 97 && c <= 102
x = c - 87;
end
Try using hex2dec. It should be faster much faster than looping over each character.
shoelzer's answer is obviously the best.
However, if you want to do the conversion by yourself, then you might find this useful:
Assuming s is a char matrix: all hex numbers are of the same length (zero padded if necessary) and each row has a single number. Then
ds = double( upper(s) ); % convert to double
sel = ds >= double('A'); % select A-F
ds( sel ) = ds( sel ) - double('A') + 10; % convert to 10 - 15
ds(~sel) = ds(~sel) - double('0'); % convert 0-9
% do the sum through vector product
v = 16.^( (size(s,2)-1):-1:0 );
x = s * v(:);

how to optimize nested for loop in matlab

I have a for loop nested thrice in a matlab program. Can any of you help me optimize it.
w=5;
a = rand(m*n,10); b=rand(m,n);
for i = 1 : m
for j = 1 : n
for k = 1 : l
if (i-w >= 1 && i+w <= m)
featureL = a(((i-1)*n)+j,:); featureR = a(((i-1)*n)+j-d,:);
D1(i,j,k) = sqrt( sum( (featureL - featureR) .* (featureL - featureR) ) );
D2(i,j,k) = mean2( b(i-w:i+w, j-w:j+w) );
end
end
end
end
I know the performance could be heavily improved by using meshgrid, but I am not sure how to do it.
Thanks in anticipation.
Can it be done something like this..
[X Y Z] = meshgrid(1:m,1:n,1:l);
D1(something containing X,Y,Z) = sqrt( sum( ( a(something cont. X,Y) - a(something cont. X,Y)).*(a(something cont. X,Y) - a(something cont. X,Y)) ) );
% similarly D2
Thanks a lot!.
I've found that a good way to attack these things is incrementally. Start by examining everything in the innermost loop, and see if it can be done at a higher level. This will reduce repeated computations.
For example, you can perform your if (i-w >= 1 && i+w <= m) two levels higher (since it only depends on i,w, and m), reducing if checks and skipping loop iterations.
Once that is done, your featureL and featureR calculations can be moved up one level; they are performed inside the k loop but only depend on j. Similarly, sqrt( sum( (featureL - featureR) .* (featureL - featureR) ) ) can be computed outside of the k loop, put into a variable, and assigned later.
In fact, as far as I can see you can get rid of the entire k loop since k is never used. Here's your code with some of this applied:
w=5;
a = rand(m*n,10);
b=rand(m,n);
for i = 1 : m
if (i-w >= 1 && i+w <= m)
for j = 1 : n
featureL = a(((i-1)*n)+j,:);
featureR = a(((i-1)*n)+j-d,:);
x = sqrt( sum( (featureL - featureR) .* (featureL - featureR) ) );
y = mean2( b(i-w:i+w, j-w:j+w) )
D1(i,j,:) = x;
D2(i,j,:) = y;
end
end
end