Page 1 of 2

Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 5:05 pm
by rje

I've started looking for easy, portable, fast and imprecise 8-bit trigonometric functions to use in the game I'm writing in C.

I've attached a 320 element binary table, with of course the obligatory initial two null bytes.  Use it like this:

foo = TRIG_TABLE[ x ];  // sin(x).  x is from 0 to 255, representing 0 to 360 degrees.
bar = TRIG_TABLE[ x + 64 ]; // cos(x).  

foo_sign = foo & 128;
foo_val = foo & 127;

bar_sign = bar & 128;
bar_val = bar & 127;

The indexed byte value has two parts: the 8th bit is the sign bit.  The remaining 7 bits represent the value, in hundredths.

Yazwho and Desertfish noted that sin and cos overlap, so only one table is needed, as long as you start COS indexing at an offset of 64 (= 90 degrees). In other words, cos(x) = sin(x+64). Since space isn't THAT critical, the table is 320 bytes long.

* * *

I found this interesting idea over here: https://geometricolor.wordpress.com/2017/01/06/fast-approximations-of-the-sine-and-cosine-functions/


Quote




The length of the table should be a power of 2 plus one for linear approximation. Then we can use bitwise-and (&) to impose periodicity instead of the much slower modulus (%) operation.



 

TRIG


Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 5:22 pm
by x16tial

How do BASICs trig functions work?  Tables of information might already be in ROM.


Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 5:30 pm
by rje


7 minutes ago, x16tial said:




How do BASICs trig functions work?  Tables of information might already be in ROM.



Nicely suggested.  You're right, I should look!

 


Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 5:30 pm
by Yazwho


22 minutes ago, rje said:




My first assumption is that there could be two tables, one for sine, and one for cosine.



cos is just sin offset by 90 degrees, or 64 if you use a 256 byte table. So you can save yourself some ram at the expense of an add.

Depending on what you're trying to do, if it's possible to match the amplitude to what you need (so no multiplication is required) you'll obviously get better performance.


Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 5:32 pm
by rje

Commodore BASIC's SIN routine, after dividing the problem by quadrant, uses floating point math thus:


Quote




...It finally computes SIN(X) using the following polynomial, which approximates SIN(F2*2*π) over [-0.25, +0.25]:




-14.381390672 * F211 + 42.007797122 * F29 - 76.704170257 * F27 + 81.605223686 * F25 - 41.341702104 * F23 + 6.2831853069 * F2



...



SIN calls POLY1, which calls MLTPLY ($BA59), and consequently the multiply bug affects its results.




https://www.c64-wiki.com/wiki/SIN


Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 5:32 pm
by desertfish

Sin and cos overlap after .5 pi you can save a few hundred bytes with that


Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 5:35 pm
by rje

Yaz mentioned that as well.  One overlapping table!

 

 


Use fast trig in C on the X16

Posted: Fri Mar 26, 2021 6:26 pm
by rje


1 hour ago, x16tial said:




How do BASICs trig functions work?  Tables of information might already be in ROM.



Now you've got me wondering what a BETTER but still not perfect sin/cos table would look like.  I mean, it could have 64K entries.

But at that point it's ridiculous, and so not only would it be divided into quadrants (thus shrinking to a 16K table) but I suspect speed would be sacrificed and an assembly routine would be introduced, and the result would land somewhere in between.

There's always https://en.wikipedia.org/wiki/Bhaskara_I's_sine_approximation_formula

image.png.69c2625dc12a438435da9c4720a5fb85.png


Use fast trig in C on the X16

Posted: Sun Mar 28, 2021 1:29 pm
by rje

It also didn't occur to me to find out what kind of trigonometric functions cc65 has, if any (I couldn't find them in cc65's library discussion).

 


Use fast trig in C on the X16

Posted: Sun Mar 28, 2021 2:38 pm
by Michael Parson


58 minutes ago, rje said:




It also didn't occur to me to find out what kind of trigonometric functions cc65 has, if any (I couldn't find them in cc65's library discussion).



Unfortunately, none.  Anything that requires floats and/or math.h hasn't been implemented yet.  It seems to be due to how the 6502 does floating point vs the 'traditional' C implementation using IEEE 754.  There were discussions on the cc65 dev list a few years ago about it, and one guy seemed to be making progress, but nothing seems to have been committed to the master branch as of yet.