简体   繁体   English

旋转双曲 CORDIC (Z -> 0) 来计算 sinh 和 cosh?

[英]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.在使用循环实现的sincos的情况下,结果是准确的。 In case of sinh and cosh which is the hyperbolic algorithm, they are not.对于双曲线算法sinhcosh ,它们不是。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM