1
votes

I'm trying to warp adapted functions of the solar position algorithm(aka "spa") made by the United States Naval Observatory to my code in a class so I can easily just call on one method to compute the solar positions.

This code belows is from the source code by the USNO. I am trying to initialize the lists L_TERMS, B_TERMS and R_TERMS

#define L_COUNT 6
#define B_COUNT 2
#define R_COUNT 5
#define Y_COUNT 63

#define L_MAX_SUBCOUNT 64
#define B_MAX_SUBCOUNT 5
#define R_MAX_SUBCOUNT 40

enum {TERM_A, TERM_B, TERM_C, TERM_COUNT};
enum {TERM_X0, TERM_X1, TERM_X2, TERM_X3, TERM_X4, TERM_X_COUNT};
enum {TERM_PSI_A, TERM_PSI_B, TERM_EPS_C, TERM_EPS_D, TERM_PE_COUNT};
enum {JD_MINUS, JD_ZERO, JD_PLUS, JD_COUNT};
enum {SUN_TRANSIT, SUN_RISE, SUN_SET, SUN_COUNT};

#define TERM_Y_COUNT TERM_X_COUNT

const int l_subcount[L_COUNT] = {64,34,20,7,3,1};
const int b_subcount[B_COUNT] = {5,2};
const int r_subcount[R_COUNT] = {40,10,6,2,1};

const double L_TERMS[L_COUNT][L_MAX_SUBCOUNT][TERM_COUNT]=
 { ... }; // contains 3*(64+34+20+7+3+1) = 387 doubles
const double B_TERMS[B_COUNT][B_MAX_SUBCOUNT][TERM_COUNT]=
 { ... }; // contains 3*(5+2) = 21 doubles
const double R_TERMS[R_COUNT][R_MAX_SUBCOUNT][TERM_COUNT]=
 { ... }; // contains 3*(40+10+6+2+1) = 177 doubles

I'm having trouble however initializing the arrays with the constructor. I tried using an initialization list but it doesn't seem to work. If I initialize the arrays in the constructor, all is well but won't be on the scope of the other methods since I can't declare them in the header. I can't initialize them either like a const int array.

Is there a better way to initialize multidimensional const double array that I am not aware of?

Note: the source code written by the USNO was done in C but I'm trying to use it in C++. Should I just include their file and call on the computing function?

2
Tip: Don't use arrays, use std::vector.tadman
Tip: Use existing matrix libraries.user2100815
@tadman why should one use a vector instead of an array of known size????Swordfish
Try using a std::array instead.NathanOliver
@tadman: std::vector is bad for this purpose. std::array is better.geza

2 Answers

1
votes

You absolutely can use an initializer list. What I like to do when doing this kind of thing is start much smaller though. Start with just much smaller arrays so it's easier to manage.

int main()
{
    const double d[2][3][4] =
    {
        {
            { 0.1, 0.2, 0.3, 0.4 },
            { 0.5, 0.6, 0.7, 0.8 },
            { 0.9, 1.0, 1.1, 1.2 }
        },
        {
            { 0.1, 0.2, 0.3, 0.4 },
            { 0.5, 0.6, 0.7, 0.8 },
            { 0.9, 1.0, 1.1, 1.2 }
        },
    };
}

Here we declare d to be 2 x 3 x 4. So we can use d[0] and d[1], and d[0][2] and d[1][2][3] is the last element.

Here's what various things print, noting I've been lazy and just declared the outer arrays with the same elements:

std::cout << d[0][0][0] << ", " << d[1][0][0] << "\n"; // prints 0.1, 0.1
std::cout << d[0][2][3] << ", " << d[1][2][3] << "\n"; // prints 1.2, 1.2
std::cout << d[0][1][2] << ", " << d[1][1][2] << "\n"; // prints 0.7, 0.7

Hopefully this makes it clearer. Note there's no reason to leave lines like I have, I just find it is easier to read.

0
votes

So it turns out in the initialization list, you can either use () or {}, not ({}). So for example initializing an array should be done with the following line:

class Foo::Foo() : L_TERMS{{{ ... }}}, // rest of initialization

Rather than

class Foo::Foo() : L_TERMS( {{{ ... }}} ) // rest of initialization