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!!!
And so you decided to immediately do some debugging to understand what happens. So you quickly modified your program to call the function with a number of different arguments, and print out the argument, and the result of doing the type cast on fabs() directly or after having multiplied the result of the multiplication with 400. And also considered printing the result of multiplying with 400 inside the fabs() call.
And what was the result of that test? Did you figure out what did happen, and why? Did you see why parentheses and order of execution matters?
So - exactly where are you stuck? You never tell us what _you_ think should happen when you perform your typecast operation. You don't even tell us what range your arg parameter has, or the size of your tables, or if you think you use radians, degrees or some other unit for your angles. And you don't tell us if your tables are defined for the full circle or a fraction of the circle or if you expect your code to work even if the angle is more than 360 degrees.
In the end it's quite good if you sit down and figure out exactly what assumptions you have made and that you document them. And that you then look at your code and see if it really fulfills your assumptions. Right now, the code most definitely doesn't and that's why you get the wrong results. Learning means that you must make sure that you understand your own code - so make sure that you are able to visualize step-by-step what the processor is actually expected to do when it process your two expressions.
Your source code would be a lot easier to read if you would follow the instructions on how to post source code - they are quite simple and clearly stated, as this picture shows:
www.danlhenry.com/.../keil_code.png
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.