[英]Hyperbolic CORDIC in rotation (Z -> 0) to calculate sinh and cosh?
I implemented both circular and hyperbolic CORDIC algorithm in rotation mode: Z -> 0
我在旋转模式下实现了圆形和双曲线 CORDIC 算法:
Z -> 0
In case of sin
and cos
which using circular implementation, the results are accurate.在使用循环实现的
sin
和cos
的情况下,结果是准确的。 In case of sinh
and cosh
which is the hyperbolic algorithm, they are not.对于双曲线算法
sinh
和cosh
,它们不是。
The output of the code below ( *_calc
is the CORDIC version, *_good
is the math.* version) is the following:下面代码的 output(
*_calc
是 CORDIC 版本, *_good
_good 是数学。* 版本)如下:
sin_good(20): 0.3420201433256687
sin_calc(20): 0.34202014332566866
sinh_good(20): 242582597.70489514
sinh_calc(20): 0.3555015499407712
cos_good(20): 0.9396926207859084
cos_calc(20): 0.9396926207859082
cosh_good(20): 242582597.70489514
cosh_calc(20): 1.0594692478629741
What am I doing wrong?我究竟做错了什么?
def lookup_circular(iteration):
return math.degrees(math.atan(2 ** -iteration))
def lookup_linear(iteration):
return 2 ** -iteration
def lookup_hyperbolic(iteration):
return math.degrees(math.atanh(2 ** -iteration))
def sin(angle):
x, y, z = cordic_circular_rotation_zto0(
x=1 / circular_scaling_factor(),
y=0,
z=float(angle)
)
return y
def cos(angle):
x, y, z = cordic_circular_rotation_zto0(
x=1 / circular_scaling_factor(),
y=0,
z=float(angle)
)
return x
def sinh(angle):
x, y, z = cordic_hyperbolic_rotation_zto0(
x=1 / hyperbolic_scaling_factor(),
y=0,
z=angle
)
return y
def cosh(angle):
x, y, z = cordic_hyperbolic_rotation_zto0(
x=1 / hyperbolic_scaling_factor(),
y=0,
z=angle
)
return x
def cordic_circular_rotation_zto0(x, y, z, n=64):
i = 0
while i <= n:
if z < 0:
newx = x + (y * 2.0 ** (-i))
newy = y - (x * 2.0 ** (-i))
z = z + lookup_circular(i)
else:
newx = x - (y * 2.0 ** (-i))
newy = y + (x * 2.0 ** (-i))
z = z - lookup_circular(i)
x = newx
y = newy
i += 1
return x, y, z
def cordic_hyperbolic_rotation_zto0(x, y, z, n=64):
i = 1
repeat = 4
while i <= n:
if z < 0:
newx = x - (y * 2.0 ** (-i))
newy = y - (x * 2.0 ** (-i))
z = z + lookup_hyperbolic(i)
else:
newx = x + (y * 2.0 ** (-i))
newy = y + (x * 2.0 ** (-i))
z = z - lookup_hyperbolic(i)
x = newx
y = newy
if i == repeat:
repeat = (i * 3) + 1
else:
i += 1
return x, y, z
def circular_scaling_factor(n=64):
e = 1
for i in range(0, n):
e = e * math.sqrt(1 + 2 ** (-2 * i))
return e
def hyperbolic_scaling_factor(n=64):
e = 1
for i in range(1, n):
e = e * math.sqrt(1 - 2 ** (-2 * i))
return e
if __name__ == '__main__':
angle = 20
sin_res = sin(angle)
print("sin_good({}): {}".format(angle, math.sin(math.radians(angle))))
print("sin_calc({}): {}".format(angle, sin_res))
print()
sinh_res = sinh(angle)
print("sinh_good({}): {}".format(angle, math.sinh(angle)))
print("sinh_calc({}): {}".format(angle, sinh_res))
print()
cos_res = cos(angle)
print("cos_good({}): {}".format(angle, math.cos(math.radians(angle))))
print("cos_calc({}): {}".format(angle, cos_res))
print()
cosh_res = cosh(angle)
print("cosh_good({}): {}".format(angle, math.cosh(angle)))
print("cosh_calc({}): {}".format(angle, cosh_res))
By removing the math.degrees
of the inverse hyperbolic tan of lookup_hyperbolic, I find the following result for cosh:通过删除
math.degrees
的反双曲 tan 的 math.degrees,我发现 cosh 的结果如下:
both functions match until x~1.1, and then the cordic function stays constant.两个函数匹配直到 x~1.1,然后 cordic function 保持不变。
Which is what can be found in Digital Arithmetic - Ercegovac/Lang 2003 chapter 11在数字算术 - Ercegovac/Lang 2003第 11 章中可以找到哪些内容
max angle = 1.11817
最大角度 = 1.11817
Same for sinh: sinh 也一样:
There is an extended cordic alogrithm that you could try to implement:您可以尝试实现一个扩展的 cordic 算法:
Expanding the Range of Convergence of the CORDIC Algorithm X. Hu, R. Harber, S. Bass Published 1991 Computer Science IEEE Trans.
扩大 CORDIC 算法的收敛范围 X. Hu, R. Harber, S. Bass 1991 年出版计算机科学 IEEE Trans。 Computers
电脑
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.