## Fast Sine calculation

Other misc things
andydansby
Member
Posts: 32
Joined: Fri May 27, 2016 8:58 pm

### Fast Sine calculation

While playing around with the Z88dk Sine function, I started to try to search for a faster algorithm. I found on a defunt message board (through archive.org) a pretty faster alternative Sine function that operates nearly twice the speed of the Z88dk version. So, I wanted to post this to share. Enjoy.

Code: Select all

``````//      zcc +zx -vn -SO3 -m -lm -clib=new main.c -o 1sine -startup=9 -create-app
//https://web.archive.org/web/20130927121234/http://devmaster.net/posts/9648/fast-and-accurate-sine-cosine

//#pragma printf %f %ld %d

#include <arch/zx.h>
#include <math.h>
#include <float.h>
#include <stdio.h>
#include <input.h>
#define ABS(N) ((N<0)?(-N):(N))
const float PI = 3.141592;

float freq = 2;
unsigned char yHeight = 191;//height of the display
unsigned char xWidth = 255;//width of the display
int halfHeight = yHeight / 2;
float sinCalc;
int x, y;
float yy;
``````
Next, here's the plot code and drawing the center line.

Code: Select all

``````void plot (unsigned char x, unsigned char y)
{
//
if (x > 255)	return;
if (y > 192)	return;

*zx_pxy2saddr (x,y) |= zx_px2bitmask(x);
}

void drawCenterLine (void)
{
//draw straight  dashed line
for (x=0; x<= xWidth; x+=2)
{
plot(x, halfHeight);
}
}
``````
First Test with the Z88dk version of sine

Code: Select all

``````float sine_caller ()//standard SIN calculation
{
sinCalc = sin( x * freq * PI / xWidth );
yy= ( ( sinCalc + 1.0) * (yHeight - 1) / 2.0);
y = (int)  yy;
return y;
}

void z88dk_sine (void)
{
for (x=0; x <= xWidth; ++ x)
{
sine_caller();
plot(x, y);
}
}
``````
Now test with the fast sine routine.

Code: Select all

``````float _sine_Smile(float xx)
{
//http://devmaster.net/posts/9648/fast-and-accurate-sine-cosine
//this routine was found by user Smile, don't know where
//the algorithm comes from

//const float P = 0.225;//now not used with A and B being precalculated
const float A = 7.5888;//A = 16 * sqrt(P);
const float B = 1.634;//B = (1 - P) / sqrt(P);

yy = xx / DOUBLEPI;

yy = yy - floor(yy + 0.5);

yy = A * yy * (0.5 - ABS(yy));

return yy * (B + ABS(yy));
}

void sine_Smile (void)
{
// this routine IS compatible with frequency yet
//freq = 2.0;// 2.0

for (x=0; x <= xWidth; ++ x)
{
sinCalc = _sine_Smile(x * freq * PI / xWidth);
YY = ( ( sinCalc + 1.0) * (halfHeight));
y = (int)YY;
plot(x, y);
}
}
``````
Finally, our main

Code: Select all

``````void main()
{
__asm
ei
__endasm

zx_cls(PAPER_WHITE | INK_BLUE);
z88dk_sine ();//sine routine
//sine_Smile();//fast sine routine
}``````
Enjoy
Andy
dom
Well known member
Posts: 1407
Joined: Sun Jul 15, 2007 10:01 pm

### Re: Fast Sine calculation

That's interesting - it looks like an approximation that works if the input value is constrained in someway?

There's math16 available which might be of interest to you - it implements a 16 bit IEEE-754 data type which should be significantly faster than any of the other maths libraries for this sort of example. The trig functions use 3 (I think) rounds of the Horner method. It's exposed as a native __Float16 type in sccz80 but in sdcc you have to use the utility functions. There's info and a versus genmath screenshot comparison here: https://github.com/z88dk/z88dk/wiki/Cla ... 80z180z80n
stefano
Well known member
Posts: 1678
Joined: Mon Jul 16, 2007 7:39 pm

### Re: Fast Sine calculation

There's also an integer simplification in lib3d, if you're interested in speed. Some of the examples use it.
stefano
Well known member
Posts: 1678
Joined: Mon Jul 16, 2007 7:39 pm