CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

sin() and cos() consume too much of resource

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
janet



Joined: 17 Feb 2004
Posts: 23

View user's profile Send private message

sin() and cos() consume too much of resource
PostPosted: Tue Mar 16, 2004 12:45 am     Reply with quote

sin() and cos() in math.h consume too much of resources.

these function return 32-bit float type. Do we have another alternative to get sin()/cos() value? precision is not of my priority. I am looking for some alternatives which can return 16-bit or 8-bit data-type.

The final result i want to get is an integer by the formula

result = (sin(x) * 40) + 40;

so it will not have negative value and decimal point.

Thanks.
vaneenbergen
Guest







PostPosted: Tue Mar 16, 2004 2:40 am     Reply with quote

why not use a rom table on desgin time not runtime. also very quick

#rom SINE_WAVE =
{
0x????, 0x???, etc
};

create this file using matlab or a custom VB/VC program.
janet



Joined: 17 Feb 2004
Posts: 23

View user's profile Send private message

PostPosted: Tue Mar 16, 2004 2:56 am     Reply with quote

Thanks!
Ttelmah
Guest







PostPosted: Tue Mar 16, 2004 3:14 am     Reply with quote

janet wrote:
Thanks!

Worth perhaps adding, that you can also do things like have a fairly 'small' lookup table, and linear interpolate between the values on this. Though it does not give fabulous accuracy, it is good enough for a lot of used. For instance I did a decoder some time ago, for a digital compass. The resulting 'number', was to be an angle (nominally) as an integer in 1/10th degree steps. The real accuracy was significantly worse than this, because of errors in the chip, and measurement, so I did the conversion using a single table in 1 degree steps, covering 90 degrees, then interpolated to get the extra digit.
The total size for table and interpolation, was only a few hundred bytes of code, and it was also fast.

Best Wishes
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Tue Mar 16, 2004 4:32 am     Reply with quote

Then there is always the cordic....this little algorithm can be extended to any precision and uses nothing more than shift and add instructions.
It gives sine cosine arctan and the sqrt(of x^2 Y^2) just perfect for that space probe or toy robot.
Sine and cosine are derived in separate calls in this example but it is the same routine so they both can be derived in the same call. It is based on on binary angles
with the tan of 45 deg =1 26.56=0.1 binary( 1/2) etc.





Code:

main()
{
signed int16 result;

result= cos(6000);

printf("cosine of 60 is %ld \n\r",result);

result= sin(6000);

printf("sine of 60 is %ld \n\r",result);

result= arctan(10000,6000);

printf("arctan of 0.60 is %ld \n\r",result);

result=sqrt_x2_y2(10000,6000);

printf("sqrt of (6^2+10^2)/0.6073 is %ld \n\r",result);
while(true);

}
////////////        cordic   ///////////////////////////////////
////////////////////////////////////////////////////////////////
///               theory                                   /////
///                                                        /////
///    coords (x,y) are rotated thru angle a to (x',y')    /////
///                                                        /////
///           x'=x.cos(a)-y.sin(a)                         /////
///           y'=y.cos(a)+x.sin(a)                         /////
///                                                        /////
///           x'/cos(a)=x-y.tan(a)                         /////
///           y'/cos(a)=y+x.tan(a)                         /////
///                                                        /////
///           now if we choose tan(a) to be                /////
///            1/2,1/4,1/8......1/2*n                      /////
///                                                        /////
///           we can rotate thru sucessive values          /////
///           ex 30.00 degs = 45-26.57+14.03-7.13+3.58     ////
///                           +17.9,.90,.45                ////
///          where a minus angle is a counter rotation     ////
///          after a rotation of 30 degs                   ////
///          x' is x.cos(30) if we start with y=0          ////
///          y' is x.sin(30)                               ////
///                                                        ////
///          angle is in 1/100th units 4500 is 45 degrees  ////
///          lengths are in aggregate constant units       ////
///                                                        ////
///  aggregate const cos(atan(1)*cos(atan(1/2)*cos(atan(1/4).....)))))
///  or .607252935                                         ////
///  so 10000 is 6073

long int const atan[13]={4500,2656,1404,712,358,179,90,45,
                 22,12,6,3,1};/// atan(1/2n)
////
////
//// to clac sin(A) cos(A) set y=0 a=angle and drive a to zero
//// via iterations
//// x value is the cos(a) providing x=6073
//// y value is the sign(a) providing x=6073
////
//// to calc atan(a) set a=0 and drive y to zero
//// a value is atan(y/x)
//// x value is sqrt(x^2+y^2) providing x=6073

signed long int cos(signed long a)
{
int i;
signed long  x,y,dx,dy,da;;
x=6073;
y=0;
for (i=0;i<13;i++)
 {

if (X>=0) {dx=X >>i;} else { dx=-X >> i;dx=-dx;}
if (Y>=0) {dy=Y >>i;} else { dy=-Y >> i;dy=-dy;}

  da=atan[i];
  if (a>=0)
          {
          a=a-da;
          x=x-dy;
          y=y+dx;
          }
 else     {
          a=a+da;
          x=x+dy;
          y=y-dx;
          }
 }
return (x);
}
signed long int sin(signed long a)
{
int i;
signed long  x,y,dx,dy,da;;
x=6073;
y=0;
for (i=0;i<13;i++)
 {

if (X>=0) {dx=X >>i;} else { dx=-X >> i;dx=-dx;}
if (Y>=0) {dy=Y >>i;} else { dy=-Y >> i;dy=-dy;}

  da=atan[i];
  if (a>=0)
          {
          a=a-da;
          x=x-dy;
          y=y+dx;
          }
 else     {
          a=a+da;
          x=x+dy;
          y=y-dx;
          }
 }
return (y);
}


signed long int arctan(signed long x,signed long y)
{
int i;
signed long  a,dx,dy,da;;

a=0;
for (i=0;i<13;i++)
 {

if (X>=0) {dx=X >>i;} else { dx=-X >> i;dx=-dx;}
if (Y>=0) {dy=Y >>i;} else { dy=-Y >> i;dy=-dy;}

  da=atan[i];
  if (y<0)
          {
          a=a-da;
          x=x-dy;
          y=y+dx;
          }
 else     {
          a=a+da;
          x=x+dy;
          y=y-dx;
          }
 }
return (a);
}

signed long int sqrt_x2_y2(signed long x,signed long y)
{
int i;
signed long  a,dx,dy,da;;

a=0;
for (i=0;i<13;i++)
 {

if (X>=0) {dx=X >>i;} else { dx=-X >> i;dx=-dx;}
if (Y>=0) {dy=Y >>i;} else { dy=-Y >> i;dy=-dy;}

  da=atan[i];
  if (y<0)
          {
          a=a-da;
          x=x-dy;
          y=y+dx;
          }
 else     {
          a=a+da;
          x=x+dy;
          y=y-dx;
          }
 }
return (x);
}
Code:


Last edited by Douglas Kennedy on Wed Aug 10, 2005 5:55 am; edited 1 time in total
janet



Joined: 17 Feb 2004
Posts: 23

View user's profile Send private message

PostPosted: Tue Mar 16, 2004 10:09 am     Reply with quote

Hi, i have tested the routine u gave me ^_^

Code:
signed int16 result;
signed int16 x = 0;

while(1) {
   printf("sine %ld = %ld \r\n", x, sin(x));
   x= x +400;
   getc();
}


sine 0 = 2
sine 400 = 698
sine 800 = 1398
sine 1200 = 2086
sine 1600 = 2760
sine 2000 = 3423
sine 2400 = 4062
sine 2800 = 4693
sine 3200 = 5292
sine 3600 = 5872
sine 4000 = 6429
sine 4400 = 6945
sine 4800 = 7434
sine 5200 = 7881
sine 5600 = 8292
sine 6000 = 8663
sine 6400 = 8988
sine 6800 = 9274
sine 7200 = 9514
sine 7600 = 9704
sine 8000 = 9846
sine 8400 = 9945
sine 8800 = 9994
sine 9200 = 9993
sine 9600 = 9947
sine 10000 = 9857
sine 10400 = 9857
sine 10800 = 9857
sine 11200 = 9857

the result shows:
1. the parameter is in 1/100th unit
2. the result is int 1/10000th unit
3. the result become constant 9857 after 10000 (??)
4. how bout the negative result?

How to use this function properly? Thanks.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Tue Mar 16, 2004 8:42 pm     Reply with quote

Janet
the routine rotates thru binary angles it is valid in the 0... 90 deg quadrant
so the integer range is 0 to 9000 in 1/100th of a degree increments.
There is always a small precision error so it will not get sin(0) correct
but you all ready know it is zero and sin(90) willl also have a small error.
but you know the result is 1. You'll have to do some adjustments to go to the next quadrant ex sin 100 deg is sin(180-100)
This is 16 bit arithmetic so 4 and a half significant digits is the best possible in decimal
The iteration table is 13 entries 2^13 binary or 3 and a half significant digits. In otherwords this particular example will give the sin cos arctan and sqrt(x^2+y^2) to 3 decimal places( 1 in a 1000 error)
The routine keeps things simple no use of radians ...angles are in int16
0 to 9000 where 9000 is 90.00 degrees no complexity just shifts and adds.
Again this uses binary angles so when we translate back to the decimal system there is a mathematically inherent difference introduced.
This comes up a lot on the forum but 0.1 decimal can't be represented in binary without loss of precision. It's just mathematics not an error.
We have an 8 bit processor so the next precision would be 24 bits
but there is no support in CCS so 32 bit would be next.
At 32 bits 9000000 would be 90 degrees and the decimal to binary angle table would need to be adjusted but the result would be 7 significant digits decimal.
RKnapp



Joined: 23 Feb 2004
Posts: 51

View user's profile Send private message

PostPosted: Sun Mar 21, 2004 4:58 pm     Reply with quote

Sine / Cosine: How about using a Taylor / Maclaurin (?) series truncated at a few terms? Sorry, I don't have the equations in front of me but Google around a bit and I'm sure you'll find the sequence which you then just chop at the 2nd or 3rd power.

Or, a lookup table on one quadrant with some logic on the argument to sort out which part of the wave you're in -- that's the fastest but does chew up some ROM.

Just a suggestion.

Smile Robert
dam



Joined: 10 May 2005
Posts: 4

View user's profile Send private message

PostPosted: Thu Aug 11, 2005 3:39 am     Reply with quote

This algorithm is really brilliant Cool Have you found it by yourself ? Or does it have a name ?
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Thu Aug 11, 2005 6:55 am     Reply with quote

No its the known CORDIC algorithm ...without it would not have had a moon landing. At that time the biggest MCU was the intel 8004 or maybe the 8008 ....anyway landing involves rotations and distance calcs based on triangulation sqrt(x^2+y^2) so the CORDIC was essential.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group