计算资源受限:指数log、对数exp 的实现
Shift-and-add algorithms计算对数为了计算logbx, x>1\log_bx,\, x>1logbx,x>1,我们可以预计算表格 (写在硬件上):Ak=logb(1+12k), k=0,1,⋯ ,n−1A_k = \log_b(1+\dfrac{1}{2^k}),\, k=0,1,\cdots,n-1Ak=logb(1+2k1),k=0,1,⋯,
Shift-and-add algorithms
计算对数
为了计算
log
b
x
,
x
>
1
\log_bx,\, x>1
logbx,x>1,我们可以预计算表格 (写在硬件上):
A
k
=
log
b
(
1
+
1
2
k
)
,
k
=
0
,
1
,
⋯
,
n
−
1
A_k = \log_b(1+\dfrac{1}{2^k}),\, k=0,1,\cdots,n-1
Ak=logb(1+2k1),k=0,1,⋯,n−1
然后可以做分解:
log
b
x
≈
log
b
∏
k
=
0
n
−
1
(
1
+
1
2
k
)
a
k
=
∑
k
=
0
n
−
1
a
k
A
k
\log_b x \approx \log_b \prod_{k=0}^{n-1} (1+\dfrac{1}{2^k})^{a_k} = \sum_{k=0}^{n-1} a_kA_k
logbx≈logbk=0∏n−1(1+2k1)ak=k=0∑n−1akAk
设置 x 0 = 1 x_0=1 x0=1,依次计算 x i = x i − 1 ( 1 + 1 2 k ) x_{i} = x_{i-1}(1+\dfrac{1}{2^k}) xi=xi−1(1+2k1)数次,保证 x i ≤ x x_i \le x xi≤x,以确定 a k a_k ak的大小。直到 n n n长的预计算表格用完。
绝对误差为: O ( log b ( 1 + 1 2 n ) ) O(\log_b(1+\dfrac{1}{2^n})) O(logb(1+2n1))
一、预计算表格
void make_shiftadd_ltab(double b)
{
double l1b = 1.0 / log(b);
double s = 1.0;
for (ulong k=0; k<ltab_n; ++k)
{
shiftadd_ltab[k] = log(1.0+s) * l1b; // == log_b(1+1/2^k)
s *= 0.5;
}
}
二、计算对数 log b x \log_b x logbx
double shiftadd_log(double x, ulong n)
{
if ( n>=ltab_n ) n = ltab_n;
double t = 0.0;
double e = 1.0;
double v = 1.0;
for (ulong k=1; k<n; ++k)
{
v *= 0.5; // v == (1>>k)
double u;
bool d;
while ( 1 )
{
u = e + e * v; // u=e; u+=(e>>k);
d = ( u<=x );
if ( d==false ) break;
t += shiftadd_ltab[k];
e = u;
}
}
return t;
}
计算指数
为了计算
b
x
,
b
>
1
b^x,\, b>1
bx,b>1,我们同样预计算表格 (写在硬件上):
A
k
=
log
b
(
1
+
1
2
k
)
,
k
=
0
,
1
,
⋯
,
n
−
1
A_k = \log_b(1+\dfrac{1}{2^k}),\, k=0,1,\cdots,n-1
Ak=logb(1+2k1),k=0,1,⋯,n−1
然后可以做分解:
b
x
≈
∏
i
=
0
n
−
1
(
1
+
1
2
k
)
a
k
=
b
∑
i
=
0
n
−
1
a
k
A
k
b^x \approx \prod_{i=0}^{n-1}(1+\dfrac{1}{2^k})^{a_k} = b^{\sum_{i=0}^{n-1}a_kA_k}
bx≈i=0∏n−1(1+2k1)ak=b∑i=0n−1akAk
设置 x 0 = 0 x_0=0 x0=0,依次计算 x i = x i − 1 + ( 1 + 1 2 k ) x_{i} = x_{i-1} + (1+\dfrac{1}{2^k}) xi=xi−1+(1+2k1)数次,保证 x i ≤ x x_i \le x xi≤x,以确定 a k a_k ak的大小。直到 n n n长的预计算表格用完。
相对误差为: O ( 1 + 1 2 n ) O(1+\dfrac{1}{2^n}) O(1+2n1)
一、预计算表格
void make_shiftadd_ltab(double b)
{
double l1b = 1.0 / log(b);
double s = 1.0;
for (ulong k=0; k<ltab_n; ++k)
{
shiftadd_ltab[k] = log(1.0+s) * l1b; // == log_b(1+1/2^k)
s *= 0.5;
}
}
二、计算指数 b x b^x bx
double shiftadd_exp(double x, ulong n)
{
if ( n>=ltab_n ) n = ltab_n;
double t = 0.0;
double e = 1.0;
double v = 1.0;
for (ulong k=1; k<n; ++k)
{
v *= 0.5; // v == (1>>k)
double u;
bool d;
while ( 1 )
{
u = t + shiftadd_ltab[k];
d = ( u<=x );
if ( d==false ) break;
t = u;
e += e * v; // e+=(e>>k);
}
}
return e;
}
更多推荐
所有评论(0)