Anda dapat menggunakan logaritma untuk menyingkirkan divisi. Untuk (x,y) di kuadran pertama:
z=log2(y)−log2(x)atan2(y,x)=atan(y/x)=atan(2z)
Gambar 1. Plot atan(2z)
atan(2z)−30<z<30atan(2−z)=π2−atan(2z)(x,y)log2(a)
b=floor(log2(a))c=a2blog2(a)=b+log2(c)
bclog2(c)1≤c<2
log2(c)
214+1=16385log2(c)30×212+1=122881atan(2z)0<z<30z
atan(2z)zz0≤z<1floor(log2(z))=0
atan(2z)0≤z<1floor(log2(z))z≥1atan(2z)z0≤z<32
Untuk referensi nanti, berikut ini adalah skrip Python kikuk yang saya gunakan untuk menghitung kesalahan aproksimasi:
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])
f(x)f^(x)f(x)Δx
fˆ(x)−f(x)≈(Δx)2limΔx→0f(x)+f(x+Δx)2−f(x+Δx2)(Δx)2=(Δx)2f′′(x)8,
di mana adalah turunan kedua dari dan adalah maksimum lokal dari kesalahan absolut. Dengan yang di atas kita mendapatkan perkiraan:f′′(x)f(x)x
atanˆ(2z)−atan(2z)≈(Δz)22z(1−4z)ln(2)28(4z+1)2,log2ˆ(a)−log2(a)≈−(Δa)28a2ln(2).
Karena fungsinya cekung dan sampel cocok dengan fungsinya, kesalahan selalu ke satu arah. Kesalahan absolut maksimum lokal dapat dikurangi setengahnya jika tanda kesalahan dibuat bergantian bolak-balik setiap interval pengambilan sampel. Dengan interpolasi linier, hasil yang mendekati optimal dapat dicapai dengan memfilter setiap tabel dengan:
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,
di mana dan adalah asli dan tabel yang difilter mencakup rentang dan bobotnya adalah . Pengkondisian akhir (baris pertama dan terakhir dalam persamaan di atas) mengurangi kesalahan pada ujung tabel dibandingkan dengan menggunakan sampel fungsi di luar tabel, karena sampel pertama dan terakhir tidak perlu disesuaikan untuk mengurangi kesalahan dari interpolasi antara itu dan sampel di luar tabel. Subtabel dengan interval pengambilan sampel yang berbeda harus difilter secara terpisah. Nilai bobot ditemukan dengan meminimalkan secara berurutan untuk meningkatkan eksponenxy0≤k≤Nc0=98,c1=−116,b0=1516,b1=18,b2=−116c0,c1N nilai absolut maksimum kesalahan perkiraan:
(Δ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
untuk posisi interpolasi antar sampel , dengan fungsi cekung atau cembung (misalnya ). Dengan bobot tersebut diselesaikan, nilai bobot akhir pengkondisian ditemukan dengan meminimalkan nilai absolut maksimum: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
untuk . Penggunaan prefilter tentang separuh kesalahan aproksimasi dan lebih mudah dilakukan daripada optimasi penuh tabel.0≤a<1
Gambar 4. Kesalahan perkiraan dari 11 sampel, dengan dan tanpa prefilter dan dengan dan tanpa pengkondisian akhir. Tanpa akhir pengkondisian prefilter memiliki akses ke nilai-nilai fungsi tepat di luar tabel.log2(a)
Artikel ini mungkin menyajikan algoritma yang sangat mirip: R. Gutierrez, V. Torres, dan J. Valls, " FPGA-implementasi atan (Y / X) berdasarkan transformasi logaritmik dan teknik berbasis LUT, " Journal of Systems Architecture , vol . 56, 2010. Abstrak mengatakan implementasi mereka mengalahkan algoritma berbasis CORDIC sebelumnya dalam kecepatan dan algoritma berbasis LUT dalam ukuran jejak.