一键计算正弦和余弦 [英] 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.
我只需要大约0.1%的精度。那么有什么方法可以找到默认的三角函数并截断幂级数以提高速度?
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?
我要记住的另一件事是,有什么方法可以执行余数运算使得结果始终为正?在我自己的算法中,我使用了 x = fmod(x,2 * pi);
,但是如果x为负,则需要添加2pi(较小的域意味着我可以使用较短的幂级数)
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)
编辑:LUT原来是最好的方法,但是我很高兴了解了其他近似技术。我还将建议使用显式的中点近似。这就是我最终要做的事情:
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);
}
以下部分近似(中点)sincos(2 * pi *(wc2 + t [j] *(cotp * t [j] -wc)))
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];
另一种方法可能是使用chebyshev分解。您可以使用正交性属性来找到系数。针对指数进行了优化,如下所示:
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
推荐答案
如果您要通过幂级数寻求具有良好(但不是很高)准确性的快速评估,则应使用Chebyshev多项式的展开式:将系数制成表格(对于0.1%的精度,您将需要很少的数据),并使用这些多项式的递归关系来评估扩展(这非常简单)。
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).
参考文献:
- 制表系数: http://www.ams.org/mcom/1980-34-149/S0025-5718-1980- 0551302-5 / S0025-5718-1980-0551302-5.pdf
- chebyshev扩展的评估: https://en.wikipedia.org/wiki/Chebyshev_polynomials
- Tabulated coefficients: http://www.ams.org/mcom/1980-34-149/S0025-5718-1980-0551302-5/S0025-5718-1980-0551302-5.pdf
- Evaluation of chebyshev expansion: https://en.wikipedia.org/wiki/Chebyshev_polynomials
您需要(a)取得-pi / 2 .. + pi / 2范围内的 reduced自变量然后(b)当参数实际上应位于整个基本间隔-pi .. + pi的另一一半时,处理结果中的符号。这些方面不应该构成主要问题:
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或-1)原始符号
- 使用模函数减少到区间0..2PI
- 确定(并记住为整数1或-1)是否在后一半中,如果是,则减去pi * 3/2,否则减去pi / 2。注意:这有效地交换了正弦和余弦(除符号外);
这完成了获得-pi / 2 .. + pi /角度的步骤。 2
用Cheb展开式评估正弦和余弦后,应用上面的步骤1和3的标志以获取正确的值。
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.
这篇关于一键计算正弦和余弦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!