Sie können Logarithmen verwenden, um die Division zu entfernen. Für ( x , y) im ersten Quadranten:
z= log2( y) - log2( x )atan2 ( y, x ) = atan ( y/ x)=atan( 2z)
Abbildung 1. Diagramm von atan ( 2z)
Sie müssten sich einem ( 2 z ) im Bereich von - 30 < z < 30 atan ( 2z) , um die erforderliche Genauigkeit von 1E-9 zu erhalten. Sie können die Symmetrie atan ( 2 - z ) = π ausnutzen- 30 < z< 30atan ( 2- z) = π2- atan ( 2z)oder stellen Sie alternativ sicher, dass( x , y)in einem bekannten Oktanten ist. Log2( A )approximieren:
b = Boden ( log2( a ) )c = a2bLog2( a ) = b + log2( c )
b kann berechnet werden, indem der Ort des höchstwertigen Nicht-Null-Bits ermittelt wird. c kann durch eine Bitverschiebung berechnet werden. Sie müsstenLog2( c ) im Bereich1 ≤ c < 2 approximieren.
Abbildung 2. Diagramm von Log2( c )
Für Ihre Genauigkeitsanforderungen, lineare Interpolation und gleichmäßige Abtastung, 214+1=16385 Abtastungen von log2(c) und 30×212+1=122881 Abtastungen vonatan(2z) für0<z<30 ausreichen. Der letztere Tisch ist ziemlich groß. Der Fehler durch Interpolation hängt dabei stark vonz :
Abbildung 3. Größter absoluter Fehler bei einer ( 2 z ) atan(2z) für verschiedene Bereiche von z (horizontale Achse) für verschiedene Anzahlen von Stichproben (32 bis 8192) pro Einheitsintervall von z . Der größte absolute Fehler für 0≤z<1 (weggelassen) ist geringfügig kleiner als für floor(log2(z))=0 .
Die atan ( 2z) -Tabelle kann in mehrere Untertabellen aufgeteilt werden, die 0 ≤ z< 1 und in verschiedene Boden ( log2( z) ) mit z≥ 1 , was einfach zu berechnen ist. Die Tabellenlängen können gemäß Abb. 3 gewählt werden. Der Index innerhalb der Untertabelle kann durch einfache Manipulation von Bitfolgen berechnet werden. Für Ihre Genauigkeitsanforderungen haben die atan ( 2z) -Untertabellen insgesamt 29217 Samples, wenn Sie den Bereich von z bis 0 ≤ z< 32 zur Vereinfachung.
Zum späteren Nachschlagen hier das klobige Python-Skript, mit dem ich die Approximationsfehler berechnet habe:
from numpy import *
from math import *
N = 10
M = 20
x = array(range(N + 1))/double(N) + 1
y = empty(N + 1, double)
for i in range(N + 1):
y[i] = log(x[i], 2)
maxErr = 0
for i in range(N):
for j in range(M):
a = y[i] + (y[i + 1] - y[i])*j/M
if N*M < 1000:
print str((i*M + j)/double(N*M) + 1) + ' ' + str(a)
b = log((i*M + j)/double(N*M) + 1, 2)
err = abs(a - b)
if err > maxErr:
maxErr = err
print maxErr
y2 = empty(N + 1, double)
for i in range(1, N):
y2[i] = -1.0/16.0*y[i-1] + 9.0/8.0*y[i] - 1.0/16.0*y[i+1]
y2[0] = -1.0/16.0*log(-1.0/N + 1, 2) + 9.0/8.0*y[0] - 1.0/16.0*y[1]
y2[N] = -1.0/16.0*y[N-1] + 9.0/8.0*y[N] - 1.0/16.0*log((N+1.0)/N + 1, 2)
maxErr = 0
for i in range(N):
for j in range(M):
a = y2[i] + (y2[i + 1] - y2[i])*j/M
b = log((i*M + j)/double(N*M) + 1, 2)
if N*M < 1000:
print a
err = abs(a - b)
if err > maxErr:
maxErr = err
print maxErr
y2[0] = 15.0/16.0*y[0] + 1.0/8.0*y[1] - 1.0/16.0*y[2]
y2[N] = -1.0/16.0*y[N - 2] + 1.0/8.0*y[N - 1] + 15.0/16.0*y[N]
maxErr = 0
for i in range(N):
for j in range(M):
a = y2[i] + (y2[i + 1] - y2[i])*j/M
b = log((i*M + j)/double(N*M) + 1, 2)
if N*M < 1000:
print str(a) + ' ' + str(b)
err = abs(a - b)
if err > maxErr:
maxErr = err
print maxErr
P = 32
NN = 13
M = 8
for k in range(NN):
N = 2**k
x = array(range(N*P + 1))/double(N)
y = empty((N*P + 1, NN), double)
maxErr = zeros(P)
for i in range(N*P + 1):
y[i] = atan(2**x[i])
for i in range(N*P):
for j in range(M):
a = y[i] + (y[i + 1] - y[i])*j/M
b = atan(2**((i*M + j)/double(N*M)))
err = abs(a - b)
if (i*M + j > 0 and err > maxErr[int(i/N)]):
maxErr[int(i/N)] = err
print N
for i in range(P):
print str(i) + " " + str(maxErr[i])
Der lokale Maximalfehler von Approximieren einer Funktion f( x ) durch lineare Interpolation ff^( x ) aus Proben vonf( x ) , mit Abtastintervall durch gleichförmige Abtastung gemachtΔ x kann durch analytisches angenähert werden:
fˆ( x ) - f( X ) ≈ ( Δ x )2limΔx→0f(x)+f(x+Δx)2−f(x+Δx2)(Δx)2= (Δx)2f′′(x)8,
wo f''( x ) die zweite Ableitung vonf( x ) undx ist ein lokales Maximum des absoluten Fehlers. Mit dem obigen erhalten wir die Annäherungen:
eine Loheˆ( 2z) - atan ( 2z)≈(Δz)22z(1−4z)ln(2)28(4z+1)2,log2ˆ(a)−log2(a)≈−(Δa)28a2ln(2).
Da die Funktionen konkav sind und die Abtastwerte mit der Funktion übereinstimmen, liegt der Fehler immer in einer Richtung. Der lokale maximale absolute Fehler könnte halbiert werden, wenn das Vorzeichen des Fehlers einmal in jedem Abtastintervall hin und her wechselt. Mit linearer Interpolation können nahezu optimale Ergebnisse erzielt werden, indem jede Tabelle vorgefiltert wird durch:
y[k]=⎧⎩⎨⎪⎪b2x[k−2]c1x[k−1]+b1x[k−1]b0x[k]+c0x[k]+b0x[k]+b1x[k+1]+c1x[k+1]+b2x[k+2]if k=0,if 0<k<N,if k=N,
Dabei sind x und y die ursprüngliche und die gefilterte Tabelle, die beide 0≤k≤Nc0=98,c1=−116,b0=1516,b1=18,b2=−116c0,c1N
(Δx)NlimΔx→0(c1f(x−Δx)+c0f(x)+c1f(x+Δx))(1−a)+(c1f(x)+c0f(x+Δx)+c1f(x+2Δx))a−f(x+aΔx)(Δx)N=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(c0+2c1−1)f(x)01+a−a2−c02(Δx)2f′′(x)if N=0,∣∣∣c1=1−c02if N=1,if N=2,∣∣∣c0=98
0≤a<1f(x)f(x)=exb0,b1,b2
(Δx)NlimΔx→0(b0f(x)+b1f(x+Δx)+b2f(x+2Δx))(1−a)+(c1f(x)+c0f(x+Δx)+c1f(x+2Δx))a−f(x+aΔx)(Δx)N=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪(b0+b1+b2−1+a(1−b0−b1−b2))f(x)(a−1)(2b0+b1−2)Δxf′(x)(−12a2+(2316−b0)a+b0−1)(Δx)2f′′(x)if N=0,∣∣∣b2=1−b0−b1if N=1,∣∣∣b1=2−2b0if N=2,∣∣∣b0=1516
for 0≤a<1. Use of the prefilter about halves the approximation error and is easier to do than full optimization of the tables.
Figure 4. Approximation error of log2(a) from 11 samples, with and without prefilter and with and without end conditioning. Without end conditioning the prefilter has access to values of the function just outside of the table.
This article probably presents a very similar algorithm: R. Gutierrez, V. Torres, and J. Valls, “FPGA-implementation of atan(Y/X) based on logarithmic transformation and LUT-based techniques,” Journal of Systems Architecture, vol. 56, 2010. The abstract says their implementation beats previous CORDIC-based algorithms in speed and LUT-based algorithms in footprint size.