Archived

This topic is now archived and is closed to further replies.

Sin/Cos-Tables faster? How..

This topic is 5646 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello! At first, I dont know in wich forum i should post it, so if it is here worng, sorry! What are the advantages of some kind of "tabel" that hold many sin/cos values? How can i make such a thing? Beause I dont know how many values I must use. e.g. namespace XX { class CMath { private: float *sinTable; .. public: void Generate_Table(); inline float sin(float value) { return .... } .. } }

Share this post


Link to post
Share on other sites
sin & cos array tables are so much faster than actully calling sin & cos in the rendering loop infact anything that stays const and used in rendering engine should be put into an array !

The reason its faster is cause memory is just being move to processor and thats it when you call the array but when you call the function many lines of code are excuted which will slow down your engine a hell of alot cause finding sine & cosine is quite a long process.

hope this helps WizHarD

Share this post


Link to post
Share on other sites

      
class TSinTable {
float sine[36000];
public:
TSinTable {
for(int i = 0;i < 36000;i++)
this -> sine[i] = sin(i/100);
}
float GetSin(float inc) {
inc *= 100;
inc %= 360;
if(inc == (int)inc)
return this -> sine[(int)inc];
float diff = inc - (int)inc;
return ((this -> sine[(int)inc] + this -> sine[(int)inc+1])*diff)
}
}
TSinTable SinTable;

EDIT: Normalize to 360... increased storage to 36000 (foolish me)..
will be 100% correct if you value is two or less decimals...
if it's more, it'll interpolate the values...
I'm positive the interpolate stuff isn't right, I don't remember how it's done, sorry!
I don't know anything about speedup, it should be faster though..


[edited by - Coward on June 26, 2002 5:04:59 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
That''s generally how it is done. You seem to have found the draw back though. If you want better precision you have to have a bigger table so you kinda need to know what kind of precision you need before making the table.

Share this post


Link to post
Share on other sites
Alberto''s right. If you think long and hard about it (or just use a Taylor Series), you can make much more accurate (and probably faster) trig functions. In fact, I''ll time-trial my custom sin function against a 3-decimal look-up table function. I''m posting this before I do the test, and I''ll post the unbiased results in a few minutes, regardless of outcome.

Peace,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links

Share this post


Link to post
Share on other sites
To say nothing of the accuracy of lookup tables (okay, it's plain atrocious), lookups are 150% faster than my fastest Taylor Series function. So take your pick: accuracy or speed.

EDIT: or size. You could always make the lookup table 100 times the current size and get 5 decimals of accuracy (or 10000 times larger and it'll be as accurate as mine...)

Later,
ZE.

//email me.//zealouselixir software.//msdn.//n00biez.//
miscellaneous links


[edited by - zealouselixir on June 26, 2002 6:29:22 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Coward
Well, could anyone help me out on the interpolation?

Parametric:
Given that you have an angle value t between angles t0 and t1 for which the sine/cosine values are known (ie, entries in your table).

sin(t) = [(1-t) * sin(t0)] + [t * sin(t1)]

How do we know for sure this works without trying all possible values? Sine and Cosine are continuous functions with lower and upper bounds of -/+ 1 in Cartesian coordinates. The reasoning for the above is that as t grows (ie, approaches t1) there should be less of an influence on the sine of t exerted by t0.

Share this post


Link to post
Share on other sites
quote:

sin(t) = [(1-t) * sin(t0)] + [t * sin(t1)]


Unfortunaetly this doesn''t work! (try it)
Something more like

( sin(t1) - sin(t0) )
sin(t) = sin(t0) + ( (t - t0) * ------------------- )
( t1 - t0 )

should do the trick.

Share this post


Link to post
Share on other sites
All you need is one table from 0° to 90° - all the other quadrants are reflections of each other.

You could even use the same table for both cos & sin, as they are the same wave 90° out-of-phase. (i.e. build a sine table, add 90° to the cosine value, and look it up in the sine table).

Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

[Look for information | GDNet Start Here | GDNet Search Tool | GDNet FAQ | MSDN RTF[L] | SGI STL Docs | STFW | Asking Smart Questions ]

[Free C++ Libraries | Boost | ACE | Loki | MTL | Blitz++ | wxWindows| Spirit(xBNF)]

Share this post


Link to post
Share on other sites
also any sin/cos table should be a power of two so a simple logical and will handle wrapping the angle you use. also arrays getting larger then 2048 or maybe 1024 (i dont have a good rule of thumb for this since i have not done much benchmarking, its very possible 4096 or even 8192 be fine, though a table that is 36000 will definatly be slow especially since mod is being used) will start to degrade performence significently if used as a lookup table. lookup tables should be small otherwise you will screw with the onboard cpu cache and things will slow down more then just calling the sin/cos function. its common misconception that lookup tables make things faster. it only gets faster if you dont trade one bottleneck 9ie calculating sin/cos) for another (ie memory bandwidth/cache thrashing).

it would be beneficial to even just go all out use fixed point math. though only if your using the values and frequently ocnverting to ints (ie perpixel/buffer type stuff, maybe for creating dynamic height maps or something or a plasma).

Share this post


Link to post
Share on other sites