|
-
November 20th, 2009, 01:45 PM
#1
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?
Last edited by bsaucer; November 20th, 2009 at 01:47 PM.
Reason: duplicate word
-
November 20th, 2009, 02:18 PM
#2
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.
-
November 20th, 2009, 02:18 PM
#3
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.
-
November 20th, 2009, 02:38 PM
#4
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.
-
November 20th, 2009, 03:13 PM
#5
Re: initializing static array
Let me clarify what I mean by "static". I mean that the array is a static member of the class.
Last edited by bsaucer; November 20th, 2009 at 03:25 PM.
Reason: spelling
-
November 20th, 2009, 03:15 PM
#6
Re: initializing static array
 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).
-
November 20th, 2009, 03:22 PM
#7
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.
-
November 20th, 2009, 03:25 PM
#8
Re: initializing static array
 Originally Posted by bsaucer
Can they be calculated at compile time?
Depends -- lets see the formula.
Regards,
Paul McKenzie
-
November 23rd, 2009, 11:37 AM
#9
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);
}
}
-
November 23rd, 2009, 02:48 PM
#10
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
Last edited by Paul McKenzie; November 23rd, 2009 at 03:27 PM.
-
November 24th, 2009, 09:53 AM
#11
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.
-
November 24th, 2009, 09:59 AM
#12
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.
-
November 24th, 2009, 10:31 AM
#13
Re: initializing static array
 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) };
-
November 24th, 2009, 10:55 AM
#14
Re: initializing static array
 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.
So either I store 1024 sines and cosines in memory in advance,
That is what is shown above.
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
-
November 24th, 2009, 03:15 PM
#15
Re: initializing static array
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.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|