TMS320C55X 中的反正切实现
arctangent implementation in TMS320C55X
我正在学习 TMS320C55x 中的反正切实现
这是源代码:
;* AR0 assigned to _x
;* AR1 assigned to _r
;* T0 assigned to _nx
PSH T3
|| BSET FRCT ;fractional mode
SUB #1, T0 ;nx-1
MOV T0, BRC0 ;repeat nx times
MOV #2596 << #16, AC3 ; AC3.Hi = C5
MOV #-9464 << #16, AC1 ; AC1.Hi = C3
MOV #32617 << #16, AC2 ; AC2.Hi = C1
*
* Note: loading T3 on the instruction before a multiply that uses it will
* cause a 1-cycle delay.
*
MPYMR T3=*AR0+, AC3, AC0 ; (Prime the Pump)
|| RPTBLOCAL loop1-1
MACR AC0, T3, AC1, AC0
MPYR T3, AC0
||MOV *AR0+, T1 ; (for next iteration)
MACR AC0, T3, AC2, AC0
MPYR T3, AC0
||MOV T1, T3
MOV HI(AC0), *AR1+ ;save result
||MPYR T1, AC3, AC0 ; (for next iteration)
loop1:
POP T3
|| BCLR FRCT ;return to standard C
MOV #0, T0 ;return OK value (no possible error)
|| RET
其中 _x 是输入向量,_r 是输出向量。 nx 是元素的数量。
问题是关于分配给 AC3、AC1、AC2 的常量。我想这是多项式近似的系数,但我不明白如何计算它们
我不看汇编代码,但我能猜到那些魔法系数是从哪里来的。
代码注释提示C1
、C3
、C5
是多项式逼近的系数,arctan
是奇函数,所以其泰勒展开围绕0
确实只有 x
的奇数次方。比较泰勒展开式y = x - 1/3 x^3 + 1/5 x^5 - 1/7 x^7 + ...
中的C1 = 32617
和1
,在给定计算上下文的情况下,进一步表明计算结果按2^15 = 32768
.[=31=缩放]
事实证明,y = (32617 x - 9464 x^3 + 2596 x^5) / 32768
实际上是区间 [-1, 1]
上 arctan(x)
的一个很好的近似值。如下图(在wolfram alpha中验证)近似的最大绝对误差小于1/1000
,在y = ±π/4
对应的端点x = ±1
处可以忽略不计,这大概是在图形计算中可取。
至于系数的实际推导方式,仅使用 9 个控制点的粗多项式最佳拟合 gives 多项式 y = 32613 x - 9443 x^3 + 2573 x^5
的系数已经接近发布代码中使用的系数。更多控制点 and/or 用于最小化端点错误的附加条件会导致系数略有不同,但很难猜测如何在没有任何关于优化标准的文档或线索的情况下准确匹配代码中的系数在那里使用。
我正在学习 TMS320C55x 中的反正切实现 这是源代码:
;* AR0 assigned to _x
;* AR1 assigned to _r
;* T0 assigned to _nx
PSH T3
|| BSET FRCT ;fractional mode
SUB #1, T0 ;nx-1
MOV T0, BRC0 ;repeat nx times
MOV #2596 << #16, AC3 ; AC3.Hi = C5
MOV #-9464 << #16, AC1 ; AC1.Hi = C3
MOV #32617 << #16, AC2 ; AC2.Hi = C1
*
* Note: loading T3 on the instruction before a multiply that uses it will
* cause a 1-cycle delay.
*
MPYMR T3=*AR0+, AC3, AC0 ; (Prime the Pump)
|| RPTBLOCAL loop1-1
MACR AC0, T3, AC1, AC0
MPYR T3, AC0
||MOV *AR0+, T1 ; (for next iteration)
MACR AC0, T3, AC2, AC0
MPYR T3, AC0
||MOV T1, T3
MOV HI(AC0), *AR1+ ;save result
||MPYR T1, AC3, AC0 ; (for next iteration)
loop1:
POP T3
|| BCLR FRCT ;return to standard C
MOV #0, T0 ;return OK value (no possible error)
|| RET
其中 _x 是输入向量,_r 是输出向量。 nx 是元素的数量。 问题是关于分配给 AC3、AC1、AC2 的常量。我想这是多项式近似的系数,但我不明白如何计算它们
我不看汇编代码,但我能猜到那些魔法系数是从哪里来的。
代码注释提示C1
、C3
、C5
是多项式逼近的系数,arctan
是奇函数,所以其泰勒展开围绕0
确实只有 x
的奇数次方。比较泰勒展开式y = x - 1/3 x^3 + 1/5 x^5 - 1/7 x^7 + ...
中的C1 = 32617
和1
,在给定计算上下文的情况下,进一步表明计算结果按2^15 = 32768
.[=31=缩放]
事实证明,y = (32617 x - 9464 x^3 + 2596 x^5) / 32768
实际上是区间 [-1, 1]
上 arctan(x)
的一个很好的近似值。如下图(在wolfram alpha中验证)近似的最大绝对误差小于1/1000
,在y = ±π/4
对应的端点x = ±1
处可以忽略不计,这大概是在图形计算中可取。
至于系数的实际推导方式,仅使用 9 个控制点的粗多项式最佳拟合 gives 多项式 y = 32613 x - 9443 x^3 + 2573 x^5
的系数已经接近发布代码中使用的系数。更多控制点 and/or 用于最小化端点错误的附加条件会导致系数略有不同,但很难猜测如何在没有任何关于优化标准的文档或线索的情况下准确匹配代码中的系数在那里使用。