initializing static array
I am writing a class which will have a static array. I need to initialize the array using a for loop. There will be several instances of the class, each of which will read values from the array. The instances need to treat the array as "constant". The code to initialize the array needs to be executed only once, not once for each instance.
Can I do all of this, and what is the syntax?
Re: initializing static array
Are the values of the array known at compile time? If so, you can use initialiser syntax, and your job becomes very simple.
Re: initializing static array
I suppose that you could write an object which takes the array pointer (and size) as an argument to its constructor, and then fills it there. Then just declare this object statically or globally.
This is more or less the approach taken by the Boost.Assignment library for the list_of syntax.
Re: initializing static array
If values are known at compile-time:
http://www.velocityreviews.com/forum...n-a-class.html
If you need to use the for-loop, or if the values will be calculated on the first call to the class, I think you'll either need a static Init() function, or you could have a static bool in the constructor that indicates whether it's the first object to be constructed, and only populate the array then.
e.g.
Code:
MyClass::MyClass() {
static bool isFirst = true;
if (isFirst) {
isFirst = false;
// initialize the array...
}
}
I'm not sure if there are any thread-safety issues with this approach.
Re: initializing static array
Let me clarify what I mean by "static". I mean that the array is a static member of the class.
Re: initializing static array
Quote:
Originally Posted by bsaucer
Let mne clarify what I mean by "static". I mean that the array is a static member of the class.
Yes, that was clear. A static member array can be initialised with initialiser syntax if its values are known at compile time (though it might be tedious if the array is large).
Re: initializing static array
To answer your questions: The array is large. The values never change, but need to be calculated. Since this is a static member, the values should be available to other classes
without creating any instances of the class.
Can they be calculated at compile time? That would save a lot of execution time at run time. I just don't want to type in a large array of doubles.
Re: initializing static array
Quote:
Originally Posted by
bsaucer
Can they be calculated at compile time?
Depends -- lets see the formula.
Regards,
Paul McKenzie
Re: initializing static array
Code:
static const double m_fCos[1024];
static const double m_fSin[1024];
static void Initialize(void);
Code:
void MyClass::Initialize(void)
{
for (int i = 0; i < 1024; i++)
{
m_fCos[i] = cos(2 * M_PI * i / 1024.0);
m_fSin[i] = sin(2 * M_PI * i / 1024.0);
}
}
Re: initializing static array
Go here:
http://www.oonumerics.org/blitz/examples/fft.cpp
Use the Taylor expansion instead of the function call. You will see template metaprogram version of sin() and cos(). You should use these in place of the arrays m_fCos and m_fSin.
Example:
Code:
#define M_PI 3.14159265358979323846
template<unsigned N, unsigned I>
class Sine {
public:
static inline double sin()
{
return (I*2*M_PI/N)*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/2/3*(1-(I*2*M_PI/N)*
(I*2*M_PI/N)/4/5*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/6/7*(1-(I*2*M_PI/N)*
(I*2*M_PI/N)/8/9*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/10/11*(1-(I*2*M_PI/N)*
(I*2*M_PI/N)/12/13*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/14/15*
(1-(I*2*M_PI/N)*(I*2*M_PI/N)/16/17*
(1-(I*2*M_PI/N)*(I*2*M_PI/N)/18/19*(1-(I*2*M_PI/N)*
(I*2*M_PI/N)/20/21))))))))));
}
};
template<unsigned N, unsigned I>
class Cosine {
public:
static inline double cos()
{
// This is a series expansion for cos(I*2*M_PI/N)
// Since all of these quantities are known at compile time, it gets
// simplified to a single number.
return 1-(I*2*M_PI/N)*(I*2*M_PI/N)/2*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/3/4*
(1-(I*2*M_PI/N)*(I*2*M_PI/N)/5/6*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/7/8*
(1-(I*2*M_PI/N)*(I*2*M_PI/N)/9/10*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/11/12*
(1-(I*2*M_PI/N)*(I*2*M_PI/N)/13/14*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/15/16*
(1-(I*2*M_PI/N)*(I*2*M_PI/N)/17/18*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/19/20*
(1-(I*2*M_PI/N)*(I*2*M_PI/N)/21/22*(1-(I*2*M_PI/N)*(I*2*M_PI/N)/23/24
)))))))))));
}
};
int main()
{
double value = Cosine<1024,2>::cos();
// instead of initializing and then using m_fCos[2];
}
Note that there are no more arrays, but the values are computed at compile time using the template syntax.
Regards,
Paul McKenzie
Re: initializing static array
In your main routine, you are passing literal constants 1024 and 2 to the template. What if I pass integer variables to the template? Does that mean calculations take place at runtime?
My routine will be passing a variable index to the array each time. So either I store 1024 sines and cosines in memory in advance, or I calculate them on the fly. I need to avoid using too many floating point calculations in a time-constrained loop.
Re: initializing static array
The Boost MPL probably contains a way to do it. I'm not familiar enough with it to know exactly, how, though.
Re: initializing static array
Quote:
Originally Posted by
Lindley
The Boost MPL probably contains a way to do it. I'm not familiar enough with it to know exactly, how, though.
if the OP wants to initialize a look up table then MPL is of little help. But there's the boost preprocessor:
something like
Code:
#define COSINE_LOOKUP(z,n,d) Cosine<d,n>::cos(),
float Cosine_[] = { BOOST_PP_REPEAT(1024, COSINE_LOOKUP, 1024) };
Re: initializing static array
Quote:
Originally Posted by
bsaucer
In your main routine, you are passing literal constants 1024 and 2 to the template. What if I pass integer variables to the template? Does that mean calculations take place at runtime?
No, you can't pass variables to the template at runtime.
According to your original requirements, you have two choices, but actually they are the same choice.
Do this in one big initialization:
Code:
double m_fCos[] = {Cosine<1024,0>::cos(),
Cosine<1024,1>::cos(),
Cosine<1024,2>::cos(),
Cosine<1024,3>::cos(),
Cosine<1024,4>::cos(),
Cosine<1024,5>::cos(),
Cosine<1024,6>::cos(),
Cosine<1024,7>::cos(),
Cosine<1024,8>::cos(),
Cosine<1024,9>::cos(),
Cosine<1024,10>::cos(),
Cosine<1024,11>::cos(),
Cosine<1024,12>::cos(),
Cosine<1024,13>::cos(),
Cosine<1024,14>::cos()
// etc..
};
Or use boost, as superbonzo shows in his post. The above and the boost solution is done purely at compile-time.
Quote:
So either I store 1024 sines and cosines in memory in advance,
That is what is shown above.
Quote:
I need to avoid using too many floating point calculations in a time-constrained loop.
Using the template, there are no floating point calculations done at runtime for sin and cos.
Regards,
Paul McKenzie
Re: initializing static array
Quote:
Using the template, there are no floating point calculations done at runtime for sin and cos.
Well, not counting the fact that I'm multiplying the cosines and sines by other things, plus a bunch of other number crunching (addition, multiplying, etc.)
My solution: I wrote a VB.Net program that would generate a large header (.h) file initiallizing the entire arrays each with 1024 douoble values.
Code:
/**********************************************************/
/* MyTable2.h */
/**********************************************************/
#ifndef ADOUBLE
#define ADOUBLE __declspec(align(32)) double
#endif
ADOUBLE aCos[] = {
+1.000000000000000, +0.999981175282601, +0.999924701839145, +0.999830581795823, //aCos[0] to aCos[3]
+0.999698818696204, +0.999529417501093, +0.999322384588350, +0.999077727752645, //aCos[4] to aCos[7]
+0.998795456205172, +0.998475580573295, +0.998118112900149, +0.997723066644192, //aCos[8] to aCos[11]
...
ADOUBLE aSin[] = {
+0.000000000000000, +0.006135884649154, +0.012271538285720, +0.018406729905805, //aSin[0] to aSin[3]
+0.024541228522912, +0.030674803176637, +0.036807222941359, +0.042938256934941, //aSin[4] to aSin[7]
+0.049067674327418, +0.055195244349690, +0.061320736302209, +0.067443919563664, //aSin[8] to aSin[11]
...
Of course I could include other tables, too.
Re: initializing static array
That's a fair enough solution, although probably more trouble than you needed to go to here.
Re: initializing static array
Quote:
Originally Posted by
bsaucer
Well, not counting the fact that I'm multiplying the cosines and sines by other things, plus a bunch of other number crunching (addition, multiplying, etc.)
But the actual calculation of sin() and cos() is not done at runtime. That was the whole point of the templates. I still think you are not aware that the code I showed you is not done at runtime at all. What I've shown you is something called "template metaprogramming", and there are whole books and websites that talk about the use of templates at compile time to do computations.
Quote:
My solution: I wrote a VB.Net program that would generate a large header (.h) file initiallizing the entire arrays each with 1024 douoble values.
Your solution is no different than the one proposed by superbonzo and myself.
Regards,
Paul McKenzie