Shop OBEX P1 Docs P2 Docs Learn Events
Newbie C++ Syntax Question — Parallax Forums

Newbie C++ Syntax Question

Prophead100Prophead100 Posts: 192
edited 2012-07-25 23:21 in Propeller 1
OK... ...I was porting over some c++ code and ran into a problem. Perhaps, I don't understand the syntax because this creates an error code --> "double u = atan(0.99664719 * tan(lat_rad));" and this does not --> "double u = atan(0.99664719 );" What am I missing? The complete method is below:



void sun_right_ascension_parallax_and_topocentric_dec(double latitude, double elevation,
double xi, double h, double delta, double *delta_alpha, double *delta_prime)
{
double delta_alpha_rad;
double lat_rad = deg2rad(latitude);
double xi_rad = deg2rad(xi);
double h_rad = deg2rad(h);
double delta_rad = deg2rad(delta);
double u = atan(0.99664719 * tan(lat_rad));
double y = 0.99664719 * sin(u) + elevation*sin(lat_rad)/6378140.0;
double x = cos(u) + elevation*cos(lat_rad)/6378140.0;

delta_alpha_rad = atan2( - x*sin(xi_rad) *sin(h_rad),
cos(delta_rad) - x*sin(xi_rad) *cos(h_rad));

*delta_prime = rad2deg(atan2((sin(delta_rad) - y*sin(xi_rad))*cos(delta_alpha_rad),
cos(delta_rad) - x*sin(xi_rad) *cos(h_rad)));

*delta_alpha = rad2deg(delta_alpha_rad);
«13

Comments

  • Heater.Heater. Posts: 21,230
    edited 2012-06-30 21:12
    No compiler here to play along with but what is the error message you are getting?
  • Prophead100Prophead100 Posts: 192
    edited 2012-06-30 21:42
    The Builder Window shows:

    propeller-elf-c++ -o a.out -Os -mxmmc -I . -m32bit-doubles -fno-exceptions -fno-rtti spa_tester.c -lm
    /tmp/cc3LdvPB.o: In function `
    sun_right_ascension_parallax_and_topocentric_dec(double, double, double, double, double, double*, double*)':
    (.text+0x190c): undefined reference to `_atan'
    collect2: ld returned 1 exit status
    Done. Build Failed!

    Check source for bad function call or global variable name `_atan'
  • Heater.Heater. Posts: 21,230
    edited 2012-06-30 21:59
    Hmmm..
    Do you have #include <math.h> at the top of that file.

    Looks like the is no atan function in the maths library which I find a bit odd.

    Your example of taking atan of a constant works because the compiler can calculate it at compile time and optimize away the function call.
  • Heater.Heater. Posts: 21,230
    edited 2012-06-30 22:07
    What happens if you change all your "double" to "float" and use the float versions of the trig functions, cosf, tanf, atanf etc.
  • Prophead100Prophead100 Posts: 192
    edited 2012-06-30 22:49
    I haven't tried changing the double to float yet. ( Still learning the basics...) It seems to work when I drop out that specific function within a function as noted.

    The program has three files. Spa_test (topfile) includes the other two (Spa.c & Spa.h).

    Spa_test has #include <stdio.h>
    #include "spa.h" //include the SPA header file
    #include "spa.c" //include the SPA header file

    Spa.c has: #include <math.h>
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-06-30 23:58
    Any chance you could bundle up all those files and post as a .zip? Then we can all have a go testing things.

    Thinking big picture, the superb effort here getting C++ working on the prop (and I say C++ specifically and with all credit to C89 using Catalina which has been around for some time) is that this opens a vast library of code. Much of that code may have been written for PCs where memory is not such an issue, so we may have to be selective finding the *best* library, ie the one that does what you want, and doesn't have megabytes of unused code either. Not that megabytes are a big problem any more, but programs do take a long time to download.

    For trig functions, float would probably be better than double. On the other hand... recently I have been using some Spin code that I think falls somewhere between float and double with a fixed decimal point at 4 decimal points, and numbers packed into 32 bits. Such a compromise fits well with the propeller as the prop is natively 32 bits. I don't know if such a library exists in C++?
  • Heater.Heater. Posts: 21,230
    edited 2012-07-01 00:59
    As that code is compiled with -m32bit-doubles then float and double should both be the same.

    The might be some interesting libraries in the Arduino world which is C++ based. I have never taken a serious look.
  • Heater.Heater. Posts: 21,230
    edited 2012-07-01 01:09
    Dr A,
    Have a google for "c++ fixed point class" or such.
    Seems there are many.
    If there is one that is smaller/faster than float that might be very usefull.
    The nice thing about C++ here is that you can overload the operators to make use of your new type. So none of that writing function calls in your source to multiply etc.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-07-01 01:49
    Hi heater,

    Yes I'm on the steep part of the learning curve too.

    Ok, google search finds this http://www.codeproject.com/Articles/37636/Fixed-Point-Class

    Sign up, email confirm, download to a directory, search in the /include directory, grab the file fixed_point.h and copy it.

    Where to put it?

    Try C:\propgcc\lib\gcc\propeller-elf\4.6.1\include

    Add this line to a hello world program
    #include <fixed_point.h>
    

    and try compiling

    error message
    c:\propgcc\bin\../lib/gcc/propeller-elf/4.6.1/include/fixed_point.h:44:28: fatal error: boost/assert.hpp: No such file or directory
    

    try changing the filename "fixed_point.h" to something different eg "afixed_point.h" . Now a different error
    DrAFile.c:3:25: fatal error: fixed_point.h: No such file or directory
    

    so I think it is finding the file, but is not including it somehow.

    In general terms, it would be useful to brainstorm how to include external libraries. Is this the correct directory to put #include files?
  • Heater.Heater. Posts: 21,230
    edited 2012-07-01 02:00
    That fixed point code you found has a dependency on the boost library (boost/assert.h).
    I'd try another.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-07-01 04:39
    Yes, that might explain things.

    I found another one, and that one said it had all the code, but it still had an include that wasn't in the package.

    So maybe try a third?

    Hmm - that is one really nice thing about spin, the way the spin tool creates "readme.txt" which has a treeview of every include, and every include in those includes. I'm still finding my way around .h libraries.
  • Heater.Heater. Posts: 21,230
    edited 2012-07-01 05:17
    Now I have no idea really but it may be possible that the boost library exists as mostly or all header files providing templates and such for use in your application. In which case you could find it,download it and put the headers somewhere your project can find it.
    Perhaps that fixed point thing only uses assert.h.
    If you were lucky there maybe a #define that disables the use of assertion checking.
  • jazzedjazzed Posts: 11,803
    edited 2012-07-01 13:01
    OK... ...I was porting over some c++ code and ran into a problem. Perhaps, I don't understand the syntax because this creates an error code --> "double u = atan(0.99664719 * tan(lat_rad));" and this does not --> "double u = atan(0.99664719 );" What am I missing? The complete method is below: ....
    Can you please make a .zip of your project with any linked source files and post it here for evaluation?

    Thanks,
    --Steve
  • Prophead100Prophead100 Posts: 192
    edited 2012-07-01 13:08
    These are source files I am trying to convert, in case you have any insights.

    Its a high accuracy (+/- 0.0003 degree) solar tracking algorithm with recent formula reviews and C code from NREL (see attached). I did a similar lower accuracy (+/- 1 degree) Solar Object (on the OBEX) which was compact and plenty accurate for basic solar panels (+/- <1 degree) and heliostats but fit nicely within the SPIN memory model. This code used with the larger GCC memory model would allow the propeller to step up to controlling high ratio solar concentrators such as parabolic mirrors and Fresnel lenses where accuracy needs to be +/- 0.06 degrees.
  • jazzedjazzed Posts: 11,803
    edited 2012-07-01 13:49
    Interesting. WIthout 32-bit doubles the program builds without errors with C or C++.
    This appears to be a library issue, but looking at the build I can't see how.

    One consideration beyond the 32-bit double build error:
    The constants are suggesting a precision that needs 64-bit double math.

    Here's the contents of my .side file:

    spa_tester.c
    >compiler=C++
    >memtype=xmmc
    >optimize=-Os
    >-fno-exceptions
    >-fno-rtti
    >-lm
    >BOARD::C3F

    Build Status:

    Project Directory: C:/gccdev/propside/MyProjects/solar_spa/
    propeller-elf-c++ -o a.out -Os -mxmmc -I . -fno-exceptions -fno-rtti spa_tester.c -lm
    propeller-elf-objdump -h a.out
    Done. Build Succeeded!
  • ersmithersmith Posts: 6,096
    edited 2012-07-01 16:28
    jazzed wrote: »
    Interesting. WIthout 32-bit doubles the program builds without errors with C or C++.
    This appears to be a library issue, but looking at the build I can't see how.
    Yes, it is indeed a library issue -- we forgot to include an alias linking "atan" to "atanf" for the 32 bit version of the library (for the 64 bit version atan is aliased to atanl, and that is present). I've checked in a fix for this.

    Until new binaries are available, you can use atanf directly in 32 bit builds. Or if you want the same code to be able to build in 32bit and 64 bit, add a define to the start of your files, like:
    #if defined(__PROPELLER_32BIT_DOUBLES__)
    #define atan atanf
    #endif
    
  • Prophead100Prophead100 Posts: 192
    edited 2012-07-01 17:09
    Thanks, that makes sense. I'll try the atanf approach.
  • Prophead100Prophead100 Posts: 192
    edited 2012-07-03 20:46
    That worked for a successful build, however I may be missing something when it comes to sending text to the terminal. (unless my program is lost in a subroutine somewhere). Anything obvious missing here?



    #include <stdio.h>
    #include <propeller.h>
    #include "spa.h" //include the SPA header file
    #include "spa.c" //include the SPA header file
    #include <math.h>


    int main (int argc, char *argv[])
    {
    spa_data spa; //declare the SPA structure
    int result;
    float min, sec;

    //enter required input values into SPA structure

    spa.year = 2003;
    spa.month = 10;
    spa.day = 17;
    spa.hour = 12;
    spa.minute = 30;
    spa.second = 30;
    spa.timezone = -7.0;
    spa.delta_t = 67;
    spa.longitude = -105.1786;
    spa.latitude = 39.742476;
    spa.elevation = 1830.14;
    spa.pressure = 820;
    spa.temperature = 11;
    spa.slope = 30;
    spa.azm_rotation = -10;
    spa.atmos_refract = 0.5667;
    spa.function = SPA_ALL;

    //call the SPA calculate function and pass the SPA structure

    result = spa_calculate(&spa);

    if (result == 0) //check for SPA errors
    {
    //display the results inside the SPA structure

    printf("Julian Day: %.6f\n",spa.jd);
    printf("L: %.6e degrees\n",spa.l);
    printf("B: %.6e degrees\n",spa.b);
    printf("R: %.6f AU\n",spa.r);
    printf("H: %.6f degrees\n",spa.h);
    printf("Delta Psi: %.6e degrees\n",spa.del_psi);
    printf("Delta Epsilon: %.6e degrees\n",spa.del_epsilon);
    printf("Epsilon: %.6f degrees\n",spa.epsilon);
    printf("Zenith: %.6f degrees\n",spa.zenith);
    printf("Azimuth: %.6f degrees\n",spa.azimuth);
    printf("Incidence: %.6f degrees\n",spa.incidence);

    min = 60.0*(spa.sunrise - (int)(spa.sunrise));
    sec = 60.0*(min - (int)min);
    printf("Sunrise: %02d:%02d:%02d Local Time\n", (int)(spa.sunrise), (int)min, (int)sec);

    min = 60.0*(spa.sunset - (int)(spa.sunset));
    sec = 60.0*(min - (int)min);
    printf("Sunset: %02d:%02d:%02d Local Time\n", (int)(spa.sunset), (int)min, (int)sec);

    } else printf("SPA Error Code: %d\n", result);

    return 0;
    }

    /////////////////////////////////////////////
    // The output of this program should be:
    //
    //Julian Day: 2452930.312847
    //L: 2.401826e+01 degrees
    //B: -1.011219e-04 degrees
    //R: 0.996542 AU
    //H: 11.105902 degrees
    //Delta Psi: -3.998404e-03 degrees
    //Delta Epsilon: 1.666568e-03 degrees
    //Epsilon: 23.440465 degrees
    //Zenith: 50.111622 degrees
    //Azimuth: 194.340241 degrees
    //Incidence: 25.187000 degrees
    //Sunrise: 06:12:43 Local Time
    //Sunset: 17:20:19 Local Time
    //
    /////////////////////////////////////////////
  • KyeKye Posts: 2,200
    edited 2012-07-03 21:09
    Try putting a waitcnt statement at the start.
  • Prophead100Prophead100 Posts: 192
    edited 2012-07-03 21:47
    Tried the waitcnt. No luck but thanks
  • ersmithersmith Posts: 6,096
    edited 2012-07-04 05:02
    Is your program printing something unexpected, or is it not printing anything at all? If it's the latter, have you tried putting a printf before the call to spa_calculate? If that prints, and nothing else does, then the code is hanging in that subroutine. Other possibilities:

    (1) A board configuration issue -- can you run a simple "hello, world" program and see the output?
    (2) Stack and/or memory overflow -- are you compiling in XMM or XMMC mode? If not, try one of those.
  • Prophead100Prophead100 Posts: 192
    edited 2012-07-04 11:47
    ersmith wrote: »
    Is your program printing something unexpected, or is it not printing anything at all? If it's the latter, have you tried putting a printf before the call to spa_calculate? If that prints, and nothing else does, then the code is hanging in that subroutine. Other possibilities:

    (1) A board configuration issue -- can you run a simple "hello, world" program and see the output?
    (2) Stack and/or memory overflow -- are you compiling in XMM or XMMC mode? If not, try one of those.

    The program prints nothing. I tried printf before spa_calculate and still no output. The "Hello World" program worked fine though so maybe I'm having the stack and/or memory overflow. I was using XMMC on my PBOE (no memory card) so perhaps I can try the XMM or add a card for more memory.. Is there a print buffer I need to flush?
  • ersmithersmith Posts: 6,096
    edited 2012-07-05 07:47
    The program prints nothing. I tried printf before spa_calculate and still no output. The "Hello World" program worked fine though so maybe I'm having the stack and/or memory overflow. I was using XMMC on my PBOE (no memory card) so perhaps I can try the XMM or add a card for more memory.. Is there a print buffer I need to flush?
    The standard output should be flushed any time a newline (\n) is printed, but you can also explicitly flush it yourself with fflush(stdout);

    If you're using XMMC mode, and if the data section is getting close to 32K, then it's possible that the stack is overflowing and corrupting some library data. You can get a picture of where everything is in memory with the objdump utility (propeller-elf-objdump -h file.elf); I think SIDE has an option to get a memory map as well.
  • Prophead100Prophead100 Posts: 192
    edited 2012-07-05 20:22
    Thanks. It looks like I'll need to do some line by line work. With the addition of a new 4GB microSD card and running in XMMC, it compiles and loads then locks up just before it goes into the first subroutine call. It prints most of a short line placed just before.
  • jazzedjazzed Posts: 11,803
    edited 2012-07-05 21:35
    Is it possible that the data has exceeded available HUB RAM? Up to 24KB of HUB RAM is available with most cache drivers.

    Can you post the map file here? On the project manager main C file right-click and choose Show Map File.

    Thanks,
    --Steve
  • Prophead100Prophead100 Posts: 192
    edited 2012-07-06 21:05
    I attached the map here. Thanks

    SPAMap.doc
  • msrobotsmsrobots Posts: 3,709
    edited 2012-07-07 13:38
    You are missing a {

    here behind the else

    } else printf("SPA Error Code: %d\n", result);

    return 0;
    }

    should look like

    } else {
    printf("SPA Error Code: %d\n", result);

    return 0;
    }

    Enjoy!

    Mike
  • jazzedjazzed Posts: 11,803
    edited 2012-07-09 14:04
    I've been looking at this issue. I wish it was as simple as a mis-placed brace.... There appears to be some stack corruption in the SPA program. I compile the same program with regular PC based GCC and see stack corruption with it too. Would like to see this resolved. Unfortunately I'm very tied up with other stuff.
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-07-09 14:30
    Steve,

    I compiled the code under Cygwin, and it ran fine. I wonder if the problem under PropGCC has to do with how 64-bit values are handled. I recall there was a compiler bug when passing long long variables to printf. Maybe there's a similar issue with floating point. I realize that we're trying to use 32-bit double variables, but maybe there some part of the code that thinks it's 64 bits instead.

    Dave
  • Heater.Heater. Posts: 21,230
    edited 2012-07-09 14:56
    Not sure if I'm on the same page here but I just downloaded spa.c, spa.h and spa_tester.c as per post #15 here.
    It did not compile under Debian on my PC:
    $ gcc -o spa_tester spa.c spa_tester.c -lm
    spa.c:586: error: expected &#8216;)&#8217; before &#8216;*&#8217; token
    spa.c:999: error: expected &#8216;)&#8217; before &#8216;*&#8217; token
    spa.c:1040: error: expected &#8216;)&#8217; before &#8216;*&#8217; token
    spa.c:1113: error: expected &#8216;)&#8217; before &#8216;*&#8217; token
    

    Looks like the includes are messed up. Firstly I put #include "spa.h" at the top of spa.c where it should be.
    Then I remove #include "spa.c" //include the SPA header from spa_tester.c where it should not be.
    Now it compiles and runs fine:
    $ gcc -o spa_tester spa.c spa_tester.c -lm
    michael@debian:~/spa$ ./spa_tester 
    Julian Day:    2452930.312847
    L:             2.401826e+01 degrees
    B:             -1.011219e-04 degrees
    R:             0.996542 AU
    H:             11.105902 degrees
    Delta Psi:     -3.998404e-03 degrees
    Delta Epsilon: 1.666568e-03 degrees
    Epsilon:       23.440465 degrees
    Zenith:        50.111622 degrees
    Azimuth:       194.340241 degrees
    Incidence:     25.187000 degrees
    Sunrise:       06:12:43 Local Time
    Sunset:        17:20:19 Local Time
    

    Edit: Results look correct.
Sign In or Register to comment.