On Jan 10, 2008 10:40 AM, Benoît Jacob <
jacob@xxxxxxxxxxxxxxx> wrote:
Hi List
1) Jonas asked me a few questions yesterday which made me realize that
-a) we need to completely split the "actual size at compile time" from the
"allocated size at compile time". This would allow taking a dynamic block in a
fixed-size matrix and still not do any dynamic memory allocation when
evaluating it. One would then be able to get rid of the block()/dynBlock()
pair and have only one block() function in the API.
-b) we need to introduce a separate special size "Generic" alongside the
existing "Dynamic". This would allow writing
someExpression = Eigen::zero();
instead of
someExpression = TypeOfThatExpression::zero();
To Jonas and ollupaC: I'm sorry the current Eigen API is not good enough; give
me a few days to work that out (currently working locally with git).
2) I'm about to switch the compile-time sizes from "static const int"
to "enum". Two reasons to do that; first it feels cleaner than having
these "static const int" values such as "Dynamic"; second I just found this:
http://jpz-log.info/archives/2007/09/09/the-joy-of-c-templates-metaprogramming/#comment-317
and the following comments.
I am not sure I understand all what is said here so I'm asking you for
confirmation:
when a class has a "static const int" member, this member is actually stored
in memory somewhere in the program's memory space, while an "enum" is just
used by the compiler and not stored in the program's memory space. Right?
That's what I understant too, and it makes sense to me that enum wastes no memory:
- static int: Is declaring a variable, so it needs memory to store the value.
- enum: It's declaring a new type. Variables of that type waste memory, the type itself not..
However, I'm not sure if "static -const- int" is not enough for the compiler to optimize it over, have you checked it?
If that's true, that's a good reason to go for enums, again for two reasons.
a) wasted memory. a static const int does not take much memory, but eigen
creates so many types, and many of which are purely formal and might not
generate any code, that the ratio "memory wasted by static const
ints" / "memory used for code" might be non-negligible
b) more importantly (the main reason IMO) being stored in memory sounds very
bad as it means that if the compiler somehow fails to optimize, a memory
access is done when that value is used. While with enums, this is guaranteed
to be optimized i.e. replaced by the literal value.
Can you confirm if so far I got it right?
I got the same so far.
Now, before going for enums, I have a few more questions.
1) when the compiler sees something like
enum MyType { First = 1, Second = 10000};
the compiler may choose as underlying integer type for MyType any type that
can store the given values. In that case it might use "short int"
or "unsigned int" for example. The following example,
enum MyType { First = 1, Second = -10000};
is legal and the compiler is guaranteed to choose for MyType a signed type.
Correct so far?
So I can always, regardless of the compiler, do:
enum Size { Dynamic = -1, Generic = -2 };
right?
2) Should my template parameters then be enums as well? Is this legal? Or
should I leave them as ints?
My concern here is the following. Suppose that at some point during
compilation, the compiler has decided that the underlying integer type
for "enum Size" is "char" (this counts as an integer type, right?)
Suppose then (unlikely but possible) that later the compiler finds in the
source code an instanciation like
Matrix<float, 128, 1> myBigFixedSizeVector;
128 doesn't fit into char so what happens?
- compiler error?
- integer overflow / undefined behavior?
- or is the compiler so clever that it will first go through the whole source
code to see what integer type is really needed?
(Well I ask about the compiler but what I really care about is the C++
standard i.e. I don't want to use non-standard behavior)
Is it a good idea, to work around this issue, to declare enum Size as follows?
enum Size { Dynamic = -1, Generic = -2, Dummy = INT_MAX };
in order to ensure that the underlying type is "int" ?
If you do use Size, then it's not:
Matrix<float , 128, 1> myBigFixedSizeVector;
but:
Matrix<float, Size(128), Size(1)> myBigFixedSizeVector;
which I think it's too verbose. I would use ints as template parameters and enums to store it (If it's really better)
Thanks for your help
Cheers,
Benoit