This function looks a Heath Robinson but it did do the job. I've not gotten around to a pretty-up rewrite so you'll have to take it or leave it :) It uses formulae to emulate the arc sine function rather than a look-up table (so it is probably a fair bit slower, but will use a bit less memory).
long arc_sine( long v_sine )
{
// supply the sine in 4096ths (i.e. 4096 = one)
// This version only finds angles for positive sines.
// Jon P
long result;
#if DIAGNOSTICS_REQUIRED
if ( v_sine < 0 ) err_dis( 476 );
#endif
if ( v_sine >= 4092 )
{
// angle range from 999 to 1024...
switch( v_sine )
{
case 4092:
return 996;
case 4093:
return 999;
case 4094:
return 1004;
case 4095:
return 1010;
case 4096:
return 1024;
#if DIAGNOSTICS_REQUIRED
default:
err_dis( 475 );
return 1024;
#endif
}
}
else
{
result = 1370000 / ( 5129 - v_sine );
//... 1324 for v_sine=4095. 1324 for v_sine=4096. 267 for v_sine=0
result += 29300 / ( 4141 - v_sine );
//.... 636 for v_sine=4095. 651 for v_sine=4096. 7 for v_sine=0
// totals: 1960 for v_sine=4095 1975 for v_sine=4096 274 for v_sine=0
if ( v_sine > 4057 )
{
// fix angle range from 934 to 993 approx (sine range 4057 to 4091)...
result -= 1625;
result += ( -5324 * ( v_sine - 4057 )) >> 12;
result += 3737;
return result >> 2;
}
else
{
if ( v_sine > 3910 )
{ // ### this range needs more work... it is +-3 out
// fix angle range from 827 to 934 approx...
result -= 1251;
result += ( 1821 * ( v_sine - 3911 )) >> 12;
result += 3309 + 4;
return result >> 2;
}
else
{
if ( v_sine >= 3117 )
{
// fix angle range from 563 to 827 approx...
result -= 708;
result += ( 2624 * ( v_sine - 3117 )) >> 12; //(4428-1804)
result += 2255;
return result >> 2;
}
else
{
//apply the normal ramp
result -= 274;
// offset: 1686 for v_sine=4095 1701 for v_sine=4096 0 for v_sine=0
result += ( 9571 * v_sine ) >> 14; //2393
result >>= 2;
if ( v_sine >= 744 && v_sine <= 2987 )
{
// fix angle range from 119 to 532 approx...
result-= 2;
}
return result;
}
}
}
}
#if DIAGNOSTICS_REQUIRED
err_dis( 477 );
#endif
}