Warning messages while using ludcmp( ) & lubksb( )


smp
06-19-2010, 03:14 AM
Hi,

____________(1)______________________

I am using ludcmp( ) and lubksb( ) in my C code.
I am using them to find inverse of a matrix.


After compiling my c code, I get following warning messages.
I have not understood them at all.
What is the meaning of these and why did they pop up and how to remove them?



nrutil.h:11: warning: 'sqrarg' defined but not used
nrutil.h:14: warning: 'dsqrarg' defined but not used
nrutil.h:17: warning: 'dmaxarg1' defined but not used
nrutil.h:17: warning: 'dmaxarg2' defined but not used
nrutil.h:21: warning: 'dminarg1' defined but not used
nrutil.h:21: warning: 'dminarg2' defined but not used
nrutil.h:25: warning: 'maxarg1' defined but not used
nrutil.h:25: warning: 'maxarg2' defined but not used
nrutil.h:29: warning: 'minarg1' defined but not used
nrutil.h:29: warning: 'minarg2' defined but not used
nrutil.h:33: warning: 'lmaxarg1' defined but not used
nrutil.h:33: warning: 'lmaxarg2' defined but not used
nrutil.h:37: warning: 'lminarg1' defined but not used
nrutil.h:37: warning: 'lminarg2' defined but not used
nrutil.h:41: warning: 'imaxarg1' defined but not used
nrutil.h:41: warning: 'imaxarg2' defined but not used
nrutil.h:45: warning: 'iminarg1' defined but not used
nrutil.h:45: warning: 'iminarg2' defined but not used




nrutil.h is a header file which contains #define statements (besides other things) like:


static float sqrarg;
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)

static double dsqrarg;
#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)

_________________________(2)_____________

Also, for the same code, I get these warning messages:

In function `main':
warning: assignment from incompatible pointer type
warning: passing arg 1 of `free_vector' from incompatible pointer type

This is fragment of my code corresponding to these 2 warning messages:


int *indx;
indx =vector(1,100);
....
....
free_vector(indx,1,100);

Any help will be appreciated.

Regards,
smp

davekw7x
06-19-2010, 08:03 AM
...


nrutil.h:11: warning: 'sqrarg' defined but not used
...


nrutil.h is a header file which contains #define statements (besides other things) like:


static float sqrarg;
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)


Replace that by an inline function definition. Something like:

/*static float sqrarg; */
/*#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg) */
inline float SQR(float a) {return (a*a);}


Similarly for the other function macros in nrutil.h:

Each of the items declaring "static xxx" followed by "#define" can be commented out and replaced by an inline function definition. This eliminates the static variables (and their associated warnings) and also makes the code more robust, since the compiler can type-check function arguments when the function is invoked in your source code.

Be sure to test them before replacing them in your copy of nrutil.h:


/*
Test program for inline function replacement for SQR in
nrutil.h from the text.

GNU users: compile with
gcc -Wall -W -pedantic test_utils.c o test_utils

If you compile with the following command line,
you get a compiler warning about unused variable dsqrarg
gcc -Wall -W -pedantic -DUSE_NR_VERSION test_utils.c -o test_utils

davekw7x

*/

#include <stdio.h>

#ifdef USE_NR_VERSION

static float sqrarg;
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
static double dsqrarg;
#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)

#else
inline float SQR(float a) {return (a*a);}
inline double DSQR(double a) {return (a*a);}
#endif

int main()
{
float x;
printf("Enter a number: ");
while (scanf("%f", &x)) {
printf("x = %f: SQR(%e) = %e\n\n", x, x, SQR(x));
printf("Enter another number: ");
}
printf("\nGoodbye for now.\n");
return 0;
}



Enter a number: 3.1415962
x = 3.141596: SQR(3.141596e+00) = 9.869627e+00

Enter another number: -42
x = -42.000000: SQR(-4.200000e+01) = 1.764000e+03

Enter another number: 0
x = 0.000000: SQR(0.000000e+00) = 0.000000e+00

Enter another number: quit

Goodbye for now.



...I get ... warning messages:


int *indx;
indx =vector(1,100);
....
....
free_vector(indx,1,100);


From nrutil.h:

.
.
.
float *vector(long nl, long nh);
int *ivector(long nl, long nh);
.
.
.
void free_vector(float *v, long nl, long nh);
void free_ivector(int *v, long nl, long nh);
.
.
.

So: The vector function is for floats.

If you want a vector of ints, use ivector.


Regards,

Dave

smp
06-21-2010, 03:54 AM
I changed from vector( ) to ivector( ) and warning disappeared. Thanks.

But I have many doubts. I want to discuss them step by step.
Sorry, I am not expert in C.

1) I have not understood what your test program does exactly.
Especially this part:
#include <stdio.h>

#ifdef USE_NR_VERSION

static float sqrarg;
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
static double dsqrarg;
#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)

#else
inline float SQR(float a) {return (a*a);}
inline double DSQR(double a) {return (a*a);}
#endif



2)
What is difference between these two statements, as both do the same job of squaring a float number?
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
and
inline float SQR(float a) {return (a*a);}

Regards,
smp

davekw7x
06-21-2010, 10:46 AM
...
What is difference between these two statements, as both do the same job of squaring a float number?
One difference is that the declaration statement (the first in each of the pairs of statements) causes memory to be allocated.

static float sqrarg;
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
static double dsqrarg;
#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)


If a lot of these kinds statements are in a header file that you include (as they are in nrutil.h) and you don't actually use all of them in your program, then you get compiler warnings about variables being "defined but not used", which was the basis of your original question.

I showed possible replacements for the first two pairs; you can also replace the others with very simple inline functions

Now, regardless of compiler warnings, as a matter of style, here's the drill:

In general, defining a macro for a function like this causes the preprocessor to expand the text in such a way that the compiler can not check for correct data types for its arguments, and can lead to execution-time errors that are difficult to track down. If you aren't careful with the macros, calling them with arguments that have side-effects can also create problems that are hard to spot. (The NR macros appear to be as "safe" as you can make them, but for most of us, it may be "safer" to use real functions instead of defining our own macros.)

Maybe there's not much chance of trouble for these simple functions, but in general, gratuitous and unnecessary use of macro functions is frowned upon by many (most?) experienced programmers. It doesn't mention it in the textbook, but actual Numerical Recipes code (on their CD) has inline functions instead of the macros.

Maybe I gave too much information in my example program, but if you define USE_NR_VERSION when compiling my example with the command line that I showed, you get the compiler warnings. When you compile it without defining USE_NR_VERSION you don't get the warnings. The two results are functionally the same. The reason that I put the USE_NR_VERSION stuff in the program was so that I could easily compile with and without that being defined and then compare the results. It's not necessary to put the USE_NR_VERSION stuff in your modified copy of nrutil.h After testing the inline functions in separate programs, as I showed in my example, just comment out each of the define/declare statements in your nrutil.h and put each corresponding inline function there.

Anyhow...

Just replace all of the pairs of declare/define statements in your copy or nrutil.h with inline function definitions, and you won't get the warnings.

Note that the warnings do not interfere with creation of the executable file or with proper functioning of the program, so you don't have to do anything about them, but I really prefer to start with an absolutely clean compile if possible. I perceive that you do also, since that's what you asked about.


Regards,

Dave

smp
06-22-2010, 12:53 AM
(1) Now I understood your test program and its purpose.

You used -D option in compilation command:

gcc -Wall -W -pedantic -DUSE_NR_VERSION test_utils.c -o test_utils

When I saw 'man' page for gcc, it said:
-Dname: Predefine name as a macro with definition 1.

From where did 1 come?

(2)

I am not including nrutil.h file in my C code. But warning message statements included the word nrutil.h as shown in my original (first) post.
How my C code is linked to nrutil.h file?

I am including only nrutil.c file in my C code, since I am using vector( ), ivector( ) & matrix( ) functions.

Also, ran1.c , ludcmp.c, lubksb.c (I used these NR routines in my C code) files are present in the directory in which my C code is present. And in the same directory, nrutil.h & nrutil.c are present.

Is nrutil.c is linked to nrutil.h ?


Regards,
smp

davekw7x
06-22-2010, 08:29 AM
...
-Dname: Predefine name as a macro with definition 1.

From where did 1 come?

Suppose you have a file named foo.c and you compile with the following command line:


gcc -DXXX foo.c -o foo

The GNU compiler man page is telling you that this has the same effect as if you had the following preprocessor directive at the beginning of your program. (But: See Footnote.)

#define XXX 1


Try the following. Follow the suggested command-line switches for compiling three different ways and run the program each way.

/*
foo.c

Compile with
gcc foo.c -o foo

Compile again with
gcc -DXXX foo.c -o foo

Compile again with
gcc -DXXX=1234 foo.c -o foo


davekw7x
*/

#include <stdio.h>

int main()
{
#ifdef XXX
printf("XXX is defined.\n");

/* If you use -DXXX the following might not work with some compilers */
printf("XXX = %d\n", XXX);

#else
printf("XXX is not defined.\n");
#endif
return 0;
}


Is nrutil.c is linked to nrutil.h ?Not directly (at least not in my copy of nrutil.c from the NR CD), but lots of other NR files include nrutil.h, so compiling them can show the warnings. In particular, ludcmp.c includes nrutil.h, right?

I mean, really, the compiler compiles and links only what you tell it to compile and link. Period.

How about posting a complete (small) test program that includes everything that you include and that shows the problem? Tell us how you compile it. (Show the command line or the Makefile or whatever...)


Regards,

Dave

Footnote:
This command-line stuff is compiler-specific and is not part of the C (or C++) language standard definition. Other compilers might not give any particular value for something from a command switch line like -DXXX (with no value given).

So: If the command line switch is -DXXX, you can always use #ifdef XXX, but trying to print the value of XXX could be problematic for some (Borland compilers on Windows, for example).

smp
06-24-2010, 12:07 AM
I ran foo.c with 3 ways.

I also ran your test_utils.c : I added in main( ) this part:

#ifdef USE_NR_VERSION
printf("USE_NR_VERSION=%d\n",USE_NR_VERSION);
#endif


Then I ran with following compilation command:

gcc -Wall -W -pedantic -DUSE_NR_VERSION=57 test_utils.c -o test_utils

Then I got following output:

Enter a number: 34
x = 34.000000: SQR(3.400000e+01) = 1.156000e+03

Enter another number: 2
x = 2.000000: SQR(2.000000e+00) = 4.000000e+00

Enter another number: g

Goodbye for now.
USE_NR_VERSION=57



Ok. As you said, here is my test code:
(This is not full code.)

/* test code */

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include"nrutil.c"


#define nodes_x 10


float ran1(long *idum);
void ludcmp(float **a, int n, int *indx, float *d);
void lubksb(float **a, int n, int *indx, float b[]);


int main()
{

int i,k;

float **multi_RM_transpose;
multi_RM_transpose= matrix(1,(nodes_x*nodes_x),1,(nodes_x*nodes_x) );


float **inverse,d,*col;
int *indx;
indx = ivector(1, (nodes_x*nodes_x) );
col = vector(1, (nodes_x*nodes_x) );
inverse = matrix(1, (nodes_x*nodes_x), 1, (nodes_x*nodes_x));

// matrix is LU factorized using ludcmp()
// Then n linear equations Ax=B are solved using lubksb()

ludcmp(multi_RM_transpose,(nodes_x*nodes_x),indx,&d);


for(k=1;k<=(nodes_x*nodes_x);k++)
{
for(i=1;i<=(nodes_x*nodes_x);i++)
{
col[i]=0.0;
}
col[k]=1.0;

lubksb(multi_RM_transpose,(nodes_x*nodes_x),indx,c ol);

for(i=1;i<=(nodes_x*nodes_x);i++)
{
inverse[i][k]=col[i];
}
}

free_matrix(multi_RM_transpose,1,nodes_x*nodes_x,1 ,nodes_x*nodes_x);
free_ivector(indx,1,(nodes_x*nodes_x) );
free_vector(col,1,(nodes_x*nodes_x) );
free_matrix(inverse,1,(nodes_x*nodes_x),1,(nodes_x *nodes_x) );

return 0;
}




Regards,
Swapnil

smp
06-25-2010, 12:01 AM
Hi Dave,

Thanks. I learned new things in this discussion.

In my original full code, I am trying to calculate inverse of a 100 x 100 sparse matrix.

To avoid confusion, I have posted my problem as a new thread.
Thread title is " How to find inverse of a sparse matrix?"

Will you please help me?

Thanks and Regards,
smp

davekw7x
06-25-2010, 10:19 AM
... As you said, here is my test code:

Actually, here is what I said:

How about posting a complete (small) test program that includes everything that you include and that shows the problem? Tell us how you compile it. (Show the command line or the Makefile or whatever...)


Your original post had messages about stuff in nrutil.h That's why I asked to see a complete program that shows the problem. This test program can not generate warnings about nrutil.h unless you have modified nrutil.c so that it includes nrutil.h. You insisted that you didn't have any part of your program that included nrutil.h, and I insist that gcc will not generate messages about nrutil.h unless nrutil.h is included by some file that you compiled. Period. Full stop.


I have tried (really tried) to explain where the compiler warning messages come from and I have suggested a way to get rid of them.
Since nrutil.h is required for many of the NR recipes files, I think it is reasonable to try to get rid of benign warning messages so that messages that indicate real problems won't get lost in a multitude of unimportant warnings in the compiler output. See Footnote.



I'm sorry that my suggestions didn't help.


Regards,

Dave
Footnote: I have no connection with the authors of the code and book or with pubilshers of the code and book. I don't usually recommend that people modify any files from the Numerical Recipes distribution, but you asked about the messages that came from compiling with nrutil.h and I tried to help you understand.

smp
06-28-2010, 12:01 AM
Hi Dave,

In my previous post I said:
To avoid confusion, I have posted my problem as a new thread.

It did not mean, I have not understood what you were trying to explain. My intention behind this statement was this: The discussion about warning messages and discussion about "how to find inverse of a sparse matrix" should not be in the same thread ( so that I may not get confused). I am sorry if any misunderstanding is created by this statement.

Your suggestions really helped me a lot:

Anyhow...

Just replace all of the pairs of declare/define statements in your copy or nrutil.h with inline function definitions, and you won't get the warnings.

I tried this. And I did not get warning messages.

As I told, many new things I learned in this discussion from you.
Thanks once again.

But my real problem (mentioned in my previous post) is to find inverse of sparse matrix of dimensions 100 x 100.

Which routine should I try? :

(1) Band diagonal Matrix is defined in the NR book as :
m1 >=0 non-zero elements immediately to the left of diagonal and m2>=0 non-zero elements immediately to the right of the diagonal.

My 100 x 100 matrix is like this (3rd column values are matrix elements):

row=1 col=1 2.000000
row=1 col=2 -1.000000
row=1 col=11 -1.000000

row=2 col=1 -1.000000
row=2 col=2 3.000000
row=2 col=3 -1.000000
row=2 col=12 -1.000000

row=3 col=2 -1.000000
row=3 col=3 3.000000
row=3 col=4 -1.000000
row=3 col=13 -1.000000

row=4 col=3 -1.000000
row=4 col=4 3.000000
row=4 col=5 -1.000000
row=4 col=14 -1.000000
.....
......
row=10 col=9 -1.000000
row=10 col=10 2.000000
row=10 col=20 -1.000000

row=11 col=1 -1.000000
row=11 col=11 3.000000
row=11 col=12 -1.000000
row=11 col=21 -1.000000

row=12 col=2 -1.000000
row=12 col=11 -1.000000
row=12 col=12 4.000000
row=12 col=13 -1.000000
row=12 col=22 -1.000000
.....
.....
.....
row=25 col=15 -1.000000
row=25 col=24 -1.000000
row=25 col=25 4.000000
row=25 col=26 -1.000000
row=25 col=35 -1.000000

row=26 col=16 -1.000000
row=26 col=25 -1.000000
row=26 col=26 4.000000
row=26 col=27 -1.000000
row=26 col=36 -1.000000
........
........
........
row=49 col=39 -1.000000
row=49 col=48 -1.000000
row=49 col=49 4.000000
row=49 col=50 -1.000000
row=49 col=59 -1.000000

row=50 col=40 -1.000000
row=50 col=49 -1.000000
row=50 col=50 3.000000
row=50 col=60 -1.000000

row=51 col=41 -1.000000
row=51 col=51 3.000000
row=51 col=52 -1.000000
row=51 col=61 -1.000000
......
......
.......
row=98 col=88 -1.000000
row=98 col=97 -1.000000
row=98 col=98 3.000000
row=98 col=99 -1.000000

row=99 col=89 -1.000000
row=99 col=98 -1.000000
row=99 col=99 3.000000
row=99 col=100 -1.000000

row=100 col=90 -1.000000
row=100 col=99 -1.000000
row=100 col=100 2.000000

So , I think this is not band diagonal matrix. Isn't it?

(2) NR book also mentions SVD (and consider it as a powerful technique).
Can SVD be applied to sparse matrix like this?

(3) Another algorithm is : Conjugate Gradient Method (CGM). This looks horrible ! It is meant for sparse systems. But I have not understood how to implement it. Does it compute the inverse of matrix A?

Thanks & Regards,
smp