Fast Sine calculation
Posted: Sat May 08, 2021 12:50 pm
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.
Next, here's the plot code and drawing the center line.
First Test with the Z88dk version of sine
Now test with the fast sine routine.
Finally, our main
Enjoy
Andy
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;
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);
}
}
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);
}
}
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);
}
}
Code: Select all
void main()
{
__asm
ei
__endasm
zx_cls(PAPER_WHITE | INK_BLUE);
z88dk_sine ();//sine routine
//sine_Smile();//fast sine routine
}
Andy