Using VecInt


amirvahid
08-29-2009, 01:12 PM
Hi Dave,
I want to use VecInt in my code but it seems that the VecInt assumes that initUcell has "2" members not "3" members. Thus the output would look like this:

The definition of initUcell:

#include "C:\...\nr3.h"

VecInt initUcell

NameList -- data
density 0.800000
eventMult 4
initUcell 8 8 ** extra data
intervalRdf 0.250000
intervalSum 5.00000
limitEventCount 1500000
limitRdf 100
rangeRdf 4.00000
sizeHistRdf 200
temperature 1.00000

The correct outputs should look like this:
NameList -- data
density 0.800000
eventMult 4
initUcell 8 8 8
intervalRdf 0.250000
intervalSum 5.00000
limitEventCount 1500000
limitRdf 100
rangeRdf 4.00000
sizeHistRdf 200
temperature 1.00000

so initUcell should have 8 8 8 as members.

I wonder if you could help me on this issue.

Regards,

Amir

davekw7x
08-29-2009, 02:34 PM
...it seems that the VecInt assumes...
Here's the thing: VecInt doesn't assume a blasted, blooming thing!

VecInt is typedef'ed as an NRVector<Int> so it has whatever constructors, operators, and functions that an NRVector<Int> class object has.

So, declaring an VecInt with no arguments will result in an 'empty' object.

Declaring a VecInt with an integer argument will result in an object with that many elements. All of the values are set equal to zero.

Declaring a VecInt with an integer and the name of an integer array as arguments will result in an object with that many elements. The values of the elements are assigned to the values from the array.

Etc.



#include "../code/nr3.h"

void PrintVecInt(const VecInt & v)
{
if (v.size() == 0) {
cout << "In VecInt: vector has no members." << endl;
}
else {
for (Int i = 0; i < v.size(); i++) {
cout << " " << v[i];
}
cout << endl;
}
}

int main()
{
VecInt a; //An "empty" VecInt. Size = 0.
cout << "Vector a: ";
PrintVecInt(a);

VecInt b(3); //A VecInt object with size = 3.
cout << "Vector b: ";
PrintVecInt(b);

int c_array[] = {11, 22, 33};
int c_size = sizeof(c_array)/sizeof(c_array[0]);

VecInt c(c_size, c_array); //Create an object and fill it from the array
cout << "Vector c: ";
PrintVecInt(c);

VecInt d(4, 42); //A VecInt object. Size = 4; all elements = 42
cout << "Vector d: ";
PrintVecInt(d);

a = c; //Assignment resizes the target appropriately
cout << "Vector a after assignment \"a = c\" : ";
PrintVecInt(a);

return 0;
}



Output:

Vector a: In VecInt: vector has no members.
Vector b: 0 0 0
Vector c: 11 22 33
Vector d: 42 42 42 42
Vector a after assignment "a = c" : 11 22 33


Bottom line: Showing us what you got and what you wanted to get from your program without showing any part of the program makes it kind of difficult to recommend specific solutions.

My hope is that the few specific examples that I posted here can help. If not, then maybe you can show us some code.



Regards,

Dave

amirvahid
08-29-2009, 06:08 PM
Thanks Dave,

The problem is exactly in sizeof() and size() function.

I have a macro like this that treats both real numbers and real vectors:

#define NameI(x) {#x, &x, N_I, sizeof (x) / sizeof (Int)}

you will see e.g. in your code the arguments sizeof(c_array)/sizeof(int) and/or sizeof(c_array)/sizeof(c_array[0]) work perfect and return 3.

However, for b, sizeof(b)/sizeof(Int) returns 2!! Therefore you had to use b.size(). In my code, the macro works with both integer and integer vectors. So x can be either Int and/or VecInt. You will see that for Int the argument "sizeof(x)/sizeof(Int)" works properly and returns 1 but for a 3 member VecInt x with the definition of "VecInt x(3)" it returns 2 as the case of "b" in your example. I wonder if you could elaborate on this issue.

Cordially

Amir

davekw7x
08-29-2009, 06:42 PM
...
The problem is exactly in sizeof() and size() function...

No, the problem is exactly in your expectations of what sizeof() returns for a class object. The value of sizeof() for a class object has nothing to do with the number of elements in the object, and, in fact, different compilers may give different values from the same code. In other words, use of sizeof() with a class object gives a value that is absolutely, positively, exactly useless (except, maybe for winning ---or losing--- bar bets). I mean, macros are (almost?) never necessary in well-formed C++ code, and are, in fact, frowned upon by many C programmers and C++ programmers who have to review, debug, and/or maintain OPC (Other People's Code). See Footnote.

In particular, as some of us have just now learned: Use of macros like yours leads to problems that are sometimes very difficult to track down. No type checking and no way of type checking of arguments.

[/begin editorial]
Bottom line: I respectfully suggest that you lose the macro and use standard code constructs that always lead to defined and determinate and useful values. Trying to hide details with clever, sneaky macros like this doesn't really help clueless programmers and drives semi-experienced programmers crazy. More experienced programmers just shake their heads and wonder---why?
[/end editorial]


Regards,

Dave

Footnote: The usage sizeof(c_array)/sizeof(c_array[0]) is an idiom that I use to make it easy to change array initializers without having to change anything else in the code. If at some time I decide to change the array to an array of shorts or an array of unsigned chars, I just change the array declaration and I don't have to remember to chante the sizeof() expression as I would if I had used sizeof(c_array)/sizeof(int). Notice also that that the value of that expression is a constant that is evaluated at compile time and does not carry any run-time penalty in code size or speed.

Really, now, what is the advantage of trying some clever, sneaky, macro to do the same thing? Especially since the macro can not test to see if you are improperly trying to use it with some class object rather than an array? I mean, really?

amirvahid
08-29-2009, 06:52 PM
Thanks Dave,

But, sizeof(b)/sizeof(int) returns "2" in your example. Why? Shouldn't it return "3"? If you define b like this:

int b [3], then "sizeof(b)/sizeof(int)" returns "3". So why VecInt b(3) cannot work as int b [3]?

Hers is the code

#include "C:\Program Files\Numerical Recipes\NR_C302\code\nr3.h"
void PrintVecInt(const VecInt & v)
{
if (v.size() == 0) {
cout << "In VecInt: vector has no members." << endl;
}
else {
for (Int i = 0; i < v.size(); i++) {
cout << " " << v[i];
}
cout << endl;
}
}


int main()
{
VecInt a; //An "empty" VecInt. Size = 0.
cout << "Vector a: ";
PrintVecInt(a);

VecInt b(3); //A VecInt object with size = 3.
cout << "Vector b: ";
PrintVecInt(b);

int c_array[] = {11, 22, 33};
int c_size = sizeof(c_array)/sizeof(c_array[0]);

VecInt c(c_size, c_array); //Create an object and fill it from the array
cout << "Vector c: ";
PrintVecInt(c);

VecInt d(4, 42); //A VecInt object. Size = 4; all elements = 42
cout << "Vector d: ";
PrintVecInt(d);

a = c; //Assignment resizes the target appropriately
cout << "Vector a after assignment \"a = c\" : ";
PrintVecInt(a);
cout << "Return wrong size of b";
cout << endl;
cout << sizeof(b)/sizeof(Int);
cout << endl;
cout << "Return right size of b";
cout << endl;
cout << b.size();
cout << endl;
cout << "Return right size of c_array";
cout << endl;
cout << sizeof(c_array)/sizeof(int);
cout << endl;


return 0;
}

Here is the output:

Vector a: In VecInt: vector has no members.
Vector b: -842150451 -842150451 -842150451
Vector c: 11 22 33
Vector d: 42 42 42 42
Vector a after assignment "a = c" : 11 22 33
Return wrong size of b
2
Return right size of b
3
Return right size of c_array
3
Press any key to continue . . .

davekw7x
08-29-2009, 07:12 PM
?

Because the value of the sizeof() operation on a class object such as a VecInt does not depend on how many ints are in the vector. It yields some implementation-dependent information about some amount of memory associated with the object (perhaps it indicates the size of a couple of pointers, bit I really can't say, and I really, really don't care---really). The value of an expression with sizeof() operations is determined at compile-time. It doesn't change during the course of program execution.

To summarize: An array occupies a fixed contiguous block in memory, and sizeof() indicates the number of bytes occupied by the array.

However...

Data members of an object such as an IntVec are stored "somewhere" in such a way that the code that implements the inner workings of the program can access the data without specific knowledge of the programmer.

Bottom line (and I hate to repeat myself): Use of sizeof() with a class object does not, in general, yield the kind of useful information (how many data items are in the object) that you would like to see. This particular class has a size() member function that tells that. Period. Full Stop.


Regards,

Dave

Footnote: One line of your output points out something that I never noticed, since I wouldn't do such a thing.

Vector b: -842150451 -842150451 -842150451

In particular, the VecInt b was declared to have a size of three, but we used the constructor that did not specify an initial value for the three elements. When I printed the output from my compiler, it told me that the values are all zero. Your compiler shows some meaningless stuff.

As I now look at the definition in nr3.h I see that, indeed the elements were not given values with this constructor, so the values are undefined. Some compilers (helpfully?) initialize all uninitialized variables to zero for you and some do not. The results are undefined. I personally feel that there is no excuse for creating classes whose constructors can leave some data members with undefined values, but that's the way it is here. Of course if you really want to give them particular values other constructors of this class can do the deed, as I show in my example..

The important points here are:

1. You can't prove your program is correct just by running it and getting what you are looking for. Even if you run lots of tests, the possibility of undefined values giving undefined or indeterminate action is always present. If I had written some stuff that depended on values the members of b being zero, it would have tested OK on my system but the code would not work with other compilers such as yours. (Of course if initial values are important, the right thing to do is to use the constructor that assigns values rather than the one that does not.)

2. My assumption that a civilized constructor would not allow an object to be created with undefined values for some data members "probably" wouldn't cause any problems in a "real" program of mine, because I "normally" don't depend on things having known values unless I assign them. But---careless programming practices can lead to grief even with people who have a lot more experience than I do.

Oh, well...

amirvahid
09-17-2009, 12:37 PM
Another problem that arises when using NR vectors is that in the IDE debugger mode, the watch tool, it only shows the "first member" of the vector and/or array, whereas, if you simply use double a[3] instead of VecDoub a(3), the watch shows all members. I wonder if you could elaborate on this issue. Thanks

davekw7x
09-17-2009, 10:58 PM
...I wonder if you could elaborate on this issue...
I will comment, but I don't think I can help very much.

A debugger is a tool. The crafters of your tool have apparently taken some trouble to try to help by keeping track of, and showing contents of, arrays whenever one element is referenced. If you tried it with std::vectors instead of NR VecDoub objects you might even find that it keeps track of std::vectors (and other STL objects) similar to the way that it shows you stuff about arrays. See Footnote.

If it doesn't show the extra stuff about other, non-standard class objects such as NRvectors, well, what can I say??? I mean, create your own class and see how much it tells you about contents of the objects. Then consider what is important to your development.

If it is really, really (really) important for you to see more (at a glance) than the debugger is showing you, then I don't know what to say other than reporting my observation that there are other debugging methods, such as using your eyes and your brain and cout<< statements at strategic places. Maybe that's not as elegant, but it can be done.


Oh, well...


Regards,

Dave


Footnote: If you look at nr3.h, you can see that there is a statement like the following:

#ifdef _USESTDVECTOR_
#define NRvector vector
#else

template <class T>
class NRvector {
.
.//All of the NRvector class definitions
.
};


If it is really, really (really) important for you to see the stuff in the debugger, you can try using #define _USESTDVECTOR_ in your application program file before you #include nr3.h

I haven't tried this, and I have no real interest in doing so, since I try to help people learn to use the nr3 routines "normally" and leave experimentation to them to do on their own.

Note that I am not recommending this (or dis-recommending this). I just mention it as a possibility.

amirvahid
09-18-2009, 10:45 AM
Thanks Dave,
The method that you mentioned is working for vectors. Now, is there any way that we could use a similar approach for matrices? I have used the following in nr3.h

#ifdef _USESTDMATRIX_
#define NRmatrix matrix
#else
template <class T>
class NRmatrix {
.
.//All of the NRmatrix class definitions
.
};

with #define _USESTDMATRIX_ at the first of my code before including nr3.h

But it generates several errors.

Regards

davekw7x
09-18-2009, 01:01 PM
...similar approach for matrices?...

No.

I won't bore you with the details, but actually there is kind of an interesting story about why there is no matrix class in the C++ Standard Template Library. This will, undoubtedly, be changed in the next release of the C++ Standard (maybe before the end of the 21st century, and, then again, maybe not).

If you want to define your own matrix class so that your revised nr3.h will compile without errors, I'm thinking that your IDE debugger still won't show you any more information about the matrix than whatever current element is being addressed. So, from your debugger's point of view, I don't think you can improve on NRmatrix. Note that this has nothing to do with C++, it just has to do with the capabilities of your debugger tool.


Regards,

Dave