Hello, I am using sin() and cos() built in functions in my C++ code. However after profiling it I realized that the 2 functions consume a lot of time. So I decided to eliminate sin() and cos() functions and replace it with an equivalent code that generates the same values for me, using either trigonometric identities or something else (Please suggest!). I tried an approach, which is shown below, but I am not getting the required results due to errors in it (The problem I assume is because of the large number of loops it goes through -- 35000*35000 which marginally moves it away from the desired result). Can somebody help me with this or another approach which might be more precise and correct. I have not shown the entire code because its big and unwanted. I just want a replacement for sin() and cos(). Code: // This is the code that works correctly but consumes a lot of time main() float phase=0.0, rate=2.5e6, raw[35000],multcos[35000],multsin[35000]; { //some statements here for(int i=0;i<35000;i++) { //some statements here for(int j=0;j<35000;j++) { arg=(2*3.14*fc*j)/rate + phase; multcos[j]=raw[j]*cos(arg); //I want to replace this cos() multsin[j]=raw[j]*sin(arg); //I want to replace this sin() //raw[j] has some predefined values Sum1[H[j]]=Sum1[H[j]] + multcos[j]; Sum2[H[j]]=Sum2[H[j]] + multsin[j]; //H[j] has some predefined values; //Sum1[] has been initilized to 0; } //some statements here } //some statements here }//end of main Below is the replacement/equivalent code I wrote to replace sin and cos functions. Code: //This is the equivalent code that does not work correctly float G_cb, G_b=1.57071406, G_a=0.0; float G_snm2, G_snm1, G_cnm2, G_cnm1; float G_s,G_c; for(i=0;i<35000;i++) { G_cb = 2* cos(G_b * PI/180); G_snm2 = sin(G_a + G_b); G_snm1 = sin(G_a + 2*G_b); G_cnm2 = cos(G_a + G_b); G_cnm1 = cos(G_a + 2*G_b); for(int j=0;j<35000;j++) { G_s = (G_cb * G_snm1) - G_snm2 ; G_c = (G_cb * G_cnm1) - G_cnm2 ; G_snm2 = G_snm1; G_cnm2 = G_cnm1; G_snm1 = G_s; G_cnm1 = G_c; multcos[j]= raw[j] * G_c; multsin[j]= raw[j] * G_s; Sum1[H[j]]=Sum1[H[j]] + multcos[j]; Sum2[H[j]]=Sum2[H[j]] + multsin[j]; //H[j] has some predefined values; //Sum1[] has been initilized to 0; } } Please help me. Thanks, prads
One approach is to determine the maximum error you're prepared to live with, then replace the sin() function with a series of straight line segments; specify fixed values at fixed points then for intermediate points use linear interpolation. You can eliminate three quarters of the data you would otherwise need for a full sinewave by using symmetry; define values for 0-90 degrees then e.g. sin(180+x)=-sin(x); sin(-x)=-sin(x) etc. e.g.1: a simple straight line from (0,0) to (90,1). sin(45)=0.7071, but our approximation is 0.5, which is a huge error of .2071. But this will be really fast and could in certain circumstances be acceptable (for example if we're generating a 10kHz sound wave and will be chucking the output through a 20kHz low pass filter such as a human ear). e.g.2: two straight lines from (0,0) to (.5,.7071) to (90,1). sin(22.5)=0.3827 but our approximation is 0.3536 (off by .0291). This is considerably better for a lookup table of only 2 values (because we can include the endpoints in the code) e.g.3: three straight lines from (0,0) to (30,.5) to (60,.8660) to (90,1). sin(15)=0.2588 and our approximation is 0.25 (off by 0.0088 which is less than 5%). You can use the same lookup table for cos because cos(x)=sin(x+90). The symmetry of cos around x=0 (cos(-x)=cos(x)) might make it better to define the values for cos then sin(x)=cos(x-90). Also you can avoid compounding errors by leaving the calculation until as late as possible. If you have, say, a 20-step calculation where sin() is called at step 1 and each step adds a possible x% error, then the error present in the sin replacement is compounded by (20^(1+)x)% (I think, anyway, it's x% compounded 20 times; use same calculation as compound interest). However if the sin function can be left until later, say until step 10, then the error is only compounded (10^(1+)x)%.