This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Conversion (unsigned int)double incorrect.

I'm calculate sin by table.

Example fragment code bellow

....
#define Tabl_acos 0x80000000
...
...
double tsin (double arg)
{ double argout;
unsigned int *adr;

adr = (unsigned int *)((unsigned int)Tabl_sin + (unsigned int)fabs(arg)*400); argout = *(double *)adr; return (argout);
}

If I'm write
... + (unsigned int)fabs(arg)*400) -> result correct, but (arg) lose fraction right part and argout lose precition.
If I'm write
... + (unsigned int)(fabs(arg)*400)) -> result incorrect! argout = fantastic value!!!

Parents Reply Children
  • And there are better methods of using that table than using a #define - C does have nice typed (!) pointers. And the linker can place arrays and other variables at specific addresses if that is required.

    A very interesting thing with data types here is that:

    #define Tabl_acos 0x80000000  <<== why not a real array or a real pointer? And of correct type?
     ...
     ...
    double tsin (double arg) {
        double argout;
        unsigned int *adr;    <<== pointer to unsigned int
    
        adr = (unsigned int *)((unsigned int)Tabl_sin + (unsigned int)fabs(arg)*400);
        argout = *(double *)adr;  <<== but used to retrieve a double
        return (argout);
    }
    

    Why play with a pointer to unsigned if the table stores doubles?

    And what happens if sizeof(unsigned int) isn't the same as sizeof(double)?

    Type casts are a great way to get broken code to compile without warnings/errors. And so it's a great way to produce broken code since the compiler many times is correct when it complains.

    double table_sin[400];
    ...
    double tsin(double arg) {
        double res;
        unsigned idx;
        idx = suitable_calculation_of_table_idx(arg);
        res = table_sin[idx];
        return res;
    }
    


    or just

    double table_sin[400];
    ...
    double tsin(double arg) {
        return table_sin[suitable_calculation_of_table_idx(arg)];
    }
    

  • And a little footnote here.

    The same lookup table can be used to compute both sin() and cos(), since there is just a difference of phase between sin() and cos().

    And since a horisontal line through a circle shows that the upper and lower halves are mirrors, it's enough with a table of 180 degrees.

    But since a vertical line through a circle shows that the left and right halves are mirrors, the table can be shrunk to only cover 90 degrees.

    And since a diagonal line through the remaining quadrant shows that the two sides of the line are mirrors, the table can be shrunk to only cover 45 degrees. (This is sometimes used by fast circle drawing code to draw 8 dots at a time)

    The calculation of the table index - and any adjustments of the retrieved value (additional sign or 1-lookup) - will obviously have to take into account which 45 degree part of the circle the input parameter related to. And take into account if sin() or cos() is computed.