Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculation sine and cosine in one shot

I have a scientific code that uses both sine and cosine of the same argument (I basically need the complex exponential of that argument). I was wondering if it were possible to do this faster than calling sine and cosine functions separately.

Also I only need about 0.1% precision. So is there any way I can find the default trig functions and truncate the power series for speed?

One other thing I have in mind is, is there any way to perform the remainder operation such that the result is always positive? In my own algorithm I used x=fmod(x,2*pi); but then I would need to add 2pi if x is negative (smaller domain means I can use a shorter power series)

EDIT: LUT turned out to be the best approach for this, however I am glad I learned about other approximation techniques. I will also advise using an explicit midpoint approximation. This is what I ended up doing:

const int N = 10000;//about 3e-4 error for 1000//3e-5 for 10 000//3e-6 for 100 000
double *cs = new double[N];
double *sn = new double[N];
for(int i  =0;i<N;i++){
    double A= (i+0.5)*2*pi/N;
    cs[i]=cos(A);
    sn[i]=sin(A);
}

The following part approximates (midpoint) sincos(2*pi*(wc2+t[j]*(cotp*t[j]-wc)))

double A=(wc2+t[j]*(cotp*t[j]-wc));
int B =(int)N*(A-floor(A));
re += cs[B]*f[j];
im += sn[B]*f[j];

Another approach could have been using the chebyshev decomposition. You can use the orthogonality property to find the coefficients. Optimized for exponential, it looks like this:

double fastsin(double x){
    x=x-floor(x/2/pi)*2*pi-pi;//this line can be improved, both inside this 
                              //function and before you input it into the function

    double x2 = x*x;
    return (((0.00015025063885163012*x2- 
   0.008034350857376128)*x2+ 0.1659789684145034)*x2-0.9995812174943602)*x;} //7th order chebyshev approx
like image 395
Gappy Hilmore Avatar asked Aug 04 '15 16:08

Gappy Hilmore


People also ask

Can you combine sin and cos?

We can add together a sine and a cosine curve. Their sum can be obtained graphically by adding the y-values of the two curves. It turns out that, if the waves have the same period, this will produce another trigonometric graph with a change in amplitude and a phase shift.

How do you combine sines?

Addition Formula for Sine: sin(a+b)=sina cosb+cosa sinb ⁡ ( a + b ) = sin ⁡ ⁡ ⁡ ⁡

How do you find the sine and cosine of an angle?

Now as per sine, cosine and tangent formulas, we have here: Sine θ = Opposite side/Hypotenuse = BC/AC. Cos θ = Adjacent side/Hypotenuse = AB/AC. Tan θ = Opposite side/Adjacent side = BC/AB.


1 Answers

If you seek fast evaluation with good (but not high) accuracy with powerseries you should use an expansion in Chebyshev polynomials: tabulate the coefficients (you'll need VERY few for 0.1% accuracy) and evaluate the expansion with the recursion relations for these polynomials (it's really very easy).

References:

  1. Tabulated coefficients: http://www.ams.org/mcom/1980-34-149/S0025-5718-1980-0551302-5/S0025-5718-1980-0551302-5.pdf
  2. Evaluation of chebyshev expansion: https://en.wikipedia.org/wiki/Chebyshev_polynomials

You'll need to (a) get the "reduced" argument in the range -pi/2..+pi/2 and consequently then (b) handle the sign in your results when the argument actually should have been in the "other" half of the full elementary interval -pi..+pi. These aspects should not pose a major problem:

  1. determine (and "remember" as an integer 1 or -1) the sign in the original angle and proceed with the absolute value.
  2. use a modulo function to reduce to the interval 0..2PI
  3. Determine (and "remember" as an integer 1 or -1) whether it is in the "second" half and, if so, subtract pi*3/2, otherwise subtract pi/2. Note: this effectively interchanges sine and cosine (apart from signs); take this into account in the final evaluation.

This completes the step to get an angle in -pi/2..+pi/2 After evaluating sine and cosine with the Cheb-expansions, apply the "flags" of steps 1 and 3 above to get the right signs in the values.

like image 128
Bert te Velde Avatar answered Nov 15 '22 12:11

Bert te Velde