Hacker’s Delight
Second Edition
梅木 輝
担当範囲
・第5章
・Applications
ruler function
[GLS1]はnumber of trailing zeros関数の面白い応用を指摘している。
1 1 1
2 4 8
この関数が , , ,…などに分割する目盛りの高さを与えるため”ruler function”と呼ばれる。
R.W.Gosperのループ検出アルゴリズムへの応用がある。
ntz関数の値毎にルーラーの高さが変わる。
loop-detection
定義
𝑋𝑛+1 = 𝑓 𝑋𝑛 によって
配列 𝑋0 , 𝑋1 , 𝑋2 ,… を定義。
「𝑓」の範囲は有限。
配列は必ず周期的。
loop-detection
leader
follow
𝑋0 , 𝑋1 , 𝑋2 , … , 𝑋𝜇−1 , 𝑋𝜇 , 𝑋𝜇+1 , 𝑋𝜇+2 , … , 𝑋𝜇+λ−1
限りなしで繰り返し
𝑋𝜇+λ , 𝑋𝜇+λ+1 , 𝑋𝜇+λ+2 , … , 𝑋𝜇+2λ−1
Loop-detection problem(ループ検出問題)は
・繰り返されるはじめの要素の添字「μ」
・周期「λ」
を見つけること
ループ検出は乱数生成器の検査やリンクリストの循環の
検出に利用できる。
loop-detection
解き方の1つは、すべての要素の値を保存しそれぞれの新しい要素と比較すること
利点
すぐにどこから2週目のサイクルが始まる
かわかる。
欠点
アルゴリズムは、スペースや時間において効
率的でない。
効率的なものは、R.W.Floyd[Kun2,sec.3.1,prob6]によるもの
R.W.Floyd algorithm
𝑋0 に初期化された𝑥, 𝑦を用いて、以下のプロセスをくりかえす。
𝑥=𝑓 𝑥
𝑦 = 𝑓(𝑓(𝑥))
𝑥 ∶ 𝑋0 , 𝑋1 , 𝑋2
生成して比較→一致しない→次を生成して比較
𝑦 ∶ 𝑋0 , 𝑋2 , 𝑋4
R.W.Floyd algorithm
𝑥3
𝑋0 に初期化された𝑥, 𝑦を用いて、以下のプロセスをくりかえす。
𝑥4
𝑥2
𝑥=𝑓 𝑥
𝑦 = 𝑓(𝑓(𝑥))
𝑥5
𝑥1
𝑥 ∶ 𝑋0 , 𝑋1 , 𝑋2 , … , 𝑋𝑛
𝑥7
𝑥6
𝑥0
𝑦 ∶ 𝑋0 , 𝑋2 , 𝑋4 , … , 𝑋2𝑛
これらを比較し、等しければ𝑋𝑛 と𝑋2𝑛 は周期λの整数倍で
隔てられていることがわかる。
つまり2𝑛 − 𝑛 = 𝑛はλの倍数である。
R.W.Floyd algorithm
次に列を最初から再び生成する。
𝑋0 , 𝑋1 , 𝑋2 , 𝑋3 , … , 𝑋𝜇 , … , 𝑋𝑛 , 𝑋𝑛+1 , 𝑋𝑛+2 , 𝑋𝑛+3 , … , 𝑋𝑛+𝜇
R.W.Floyd algorithm
𝑋0 と𝑋𝑛 を比較。 →一致しない
𝑋1 と𝑋𝑛+1 を比較。 →一致しない
𝑋2 と𝑋𝑛+2 を比較。 →一致しない
𝑋0 , 𝑋1 , 𝑋2 , 𝑋3 , … , 𝑋𝜇 , … , 𝑋𝑛 , 𝑋𝑛+1 , 𝑋𝑛+2 , 𝑋𝑛+3 , … , 𝑋𝑛+𝜇
𝑋𝜇 と𝑋𝑛+𝜇 を比較。 → 一致
ここで𝜇を決定できる。
R.W.Floyd algorithm
最後に「λ」であるが要素の再生成を続け
𝑋𝜇 を𝑋𝜇+1 , 𝑋𝜇+2 , 𝑋𝜇+3 , …と比較していくことで決定することができる。
𝑋𝜇 , 𝑋𝜇+1 を比較。→一致しない
𝑋𝜇 , 𝑋𝜇+2 を比較。→一致しない
𝑋𝜇 , 𝑋𝜇+3 を比較。→一致しない。
𝑋𝜇 , 𝑋𝜇+1 , 𝑋𝜇+2 , 𝑋𝜇+3 , … , 𝑋𝜇+𝜆
𝑋𝜇 , 𝑋𝜇+𝜆 を比較。→一致。
ここで𝜆を決定できる。
R.W.Floyd algorithm
𝑥=𝑓 𝑥
𝑦 = 𝑓(𝑓(𝑥))
利点
限られた量のスペースで十分。
欠点
𝑓を何度も評価するので時間がかかる。
Gosper’s algorithm
このアルゴリズムは周期「λ」は見つけるが、1回目の周期の開始点「μ」は計算できない。
𝜇𝑢 − 𝜇𝑙 + 1 ≤ max(𝜆 − 1,1)であるような𝜇の範囲を求めることができる。
特徴
𝑓の再評価を決して行わない。
スペース的にも、時間的にも極めて経済的
関数の最大周期をΛとすると、大きさlog 2 (Λ) + 1のテーブルが必要
これは大きなスペースではなく、先験的にΛ ≤ 232 だとわかっていれば、33ワードあれば十分
Gosper’s algorithm
void ld_Gosper(int (*f)(int), int X0, int *mu_l,
int*mu_u, int *lambda){
int Xn, k, m, kmax, n, lgl;
int T[33];
T[0] = X0;
Xn = X0;
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
L:
// Compute m = max{i | i < n and ntz(i+1) = k}.
m = ((((n >> k) - 1) | 1) << k) - 1;
*lambda = n - m;
lgl = 31 - nlz(*lambda - 1); // Ceil(log2 lambda) - 1.
*mu_u = m;
// Upper bound on mu.
*mu_l = m - max(1, 1 << lgl) + 1;// Lower bound on mu.
}
Gosper’s algorithm
void ld_Gosper(int (*f)(int), int X0, int *mu_l,
int*mu_u, int *lambda){
int Xn, k, m, kmax, n, lgl;
int T[33];
T[0] = X0;
Xn = X0;
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋0
テーブルにX0をいれ、𝑋𝑛 を𝑋0 で初期化
Gosper’s algorithm
void ld_Gosper(int (*f)(int), int X0, int *mu_l,
int*mu_u, int *lambda){
int Xn, k, m, kmax, n, lgl;
int T[33];
T[0] = X0;
Xn = X0;
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋1 ∶ 𝑋0
新しい要素の生成
テーブルの数計算
𝑋𝑛 とテーブル内を比較。
等しいものがあったら→L
ないならテーブル追加、更新を繰り返す。
Gosper’s algorithm
void ld_Gosper(int (*f)(int), int X0, int *mu_l,
int*mu_u, int *lambda){
int Xn, k, m, kmax, n, lgl;
int T[33];
T[0] = X0;
Xn = X0;
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋1 ∶ 𝑋0
𝑋2 ∶ 𝑋0 , 𝑋1
新しい要素の生成
テーブルの数計算
𝑋𝑛 とテーブル内を比較。
等しいものがあったら→L
ないならテーブル追加、更新を繰り返す。
Gosper’s algorithm
void ld_Gosper(int (*f)(int), int X0, int *mu_l,
int*mu_u, int *lambda){
int Xn, k, m, kmax, n, lgl;
int T[33];
T[0] = X0;
Xn = X0;
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋1 ∶ 𝑋0
𝑋2 ∶ 𝑋0 , 𝑋1
𝑋3 ∶ 𝑋2 , 𝑋1
新しい要素の生成
テーブルの数計算
𝑋𝑛 とテーブル内を比較。
等しいものがあったら→L
ないならテーブル追加、更新を繰り返す。
Gosper’s algorithm
void ld_Gosper(int (*f)(int), int X0, int *mu_l,
int*mu_u, int *lambda){
int Xn, k, m, kmax, n, lgl;
int T[33];
T[0] = X0;
Xn = X0;
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋1 ∶ 𝑋0
𝑋2 ∶ 𝑋0 , 𝑋1
𝑋3 ∶ 𝑋2 , 𝑋1
𝑋4 ∶ 𝑋2 , 𝑋1 , 𝑋3
新しい要素の生成
テーブルの数計算
𝑋𝑛 とテーブル内を比較。
等しいものがあったら→L
ないならテーブル追加、更新を繰り返す。
Gosper’s algorithm
void ld_Gosper(int (*f)(int), int X0, int *mu_l,
int*mu_u, int *lambda){
int Xn, k, m, kmax, n, lgl;
int T[33];
T[0] = X0;
Xn = X0;
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋1 ∶ 𝑋0
𝑋2 ∶ 𝑋0 , 𝑋1
𝑋3 ∶ 𝑋2 , 𝑋1
𝑋4 ∶ 𝑋2 , 𝑋1 , 𝑋3
𝑋5 ∶ 𝑋4 , 𝑋1 , 𝑋3
新しい要素の生成
テーブルの数計算
𝑋𝑛 とテーブル内を比較。
等しいものがあったら→L
ないならテーブル追加、更新を繰り返す。
Gosper’s algorithm
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
𝑋7
𝑋8
𝑋9
𝑋10
𝑋11
𝑋12
∶
∶
∶
∶
∶
∶
𝑋6 , 𝑋5 , 𝑋3
𝑋6 , 𝑋5 , 𝑋3 , 𝑋7
𝑋8 , 𝑋5 , 𝑋3 , 𝑋7
𝑋8 , 𝑋9 , 𝑋3 , 𝑋7
𝑋10 , 𝑋9 , 𝑋3 , 𝑋7
𝑋10 , 𝑋9 , 𝑋11 , 𝑋7
𝑋13
𝑋14
𝑋15
𝑋16
𝑋17
𝑋18
∶
∶
∶
∶
∶
∶
𝑋12 , 𝑋9 , 𝑋11 , 𝑋7
𝑋12 , 𝑋13 , 𝑋11 , 𝑋7
𝑋14 , 𝑋13 , 𝑋11 , 𝑋7
𝑋14 , 𝑋13 , 𝑋11 , 𝑋7 , 𝑋15
𝑋16 , 𝑋13 , 𝑋11 , 𝑋7 , 𝑋15
𝑋16 , 𝑋17 , 𝑋11 , 𝑋7 , 𝑋15
Gosper’s algorithm
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
𝑋7
𝑋8
𝑋9
𝑋10
𝑋11
𝑋12
∶
∶
∶
∶
∶
∶
𝑋6 , 𝑋5 , 𝑋3
𝑋6 , 𝑋5 , 𝑋3 , 𝑋7
𝑋8 , 𝑋5 , 𝑋3 , 𝑋7
𝑋8 , 𝑋9 , 𝑋3 , 𝑋7
𝑋10 , 𝑋9 , 𝑋3 , 𝑋7
𝑋10 , 𝑋9 , 𝑋11 , 𝑋7
𝑋13
𝑋14
𝑋15
𝑋16
𝑋17
𝑋18
∶
∶
∶
∶
∶
∶
𝑋12 , 𝑋9 , 𝑋11 , 𝑋7
𝑋12 , 𝑋13 , 𝑋11 , 𝑋7
𝑋14 , 𝑋13 , 𝑋11 , 𝑋7
𝑋14 , 𝑋13 , 𝑋11 , 𝑋7 , 𝑋15
𝑋16 , 𝑋13 , 𝑋11 , 𝑋7 , 𝑋15
𝑋16 , 𝑋17 , 𝑋11 , 𝑋7 , 𝑋15
関数の最大周期をΛとすると、大きさlog 2 (Λ) + 1のテーブルが必要
これは大きなスペースではなく、先験的にΛ ≤ 232 だとわかっていれば、33ワードあれば十分
Gosper’s algorithm
例
𝑋0 𝑋1 𝑋2 𝑋3 𝑋4 𝑋5 𝑋6 𝑋7 𝑋8 𝑋9 𝑋10 𝑋11
1 2 3 4 5 6 4 5 6 4 5 6
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
Gosper’s algorithm
𝑋0 𝑋1 𝑋2 𝑋3 𝑋4 𝑋5 𝑋6 𝑋7 𝑋8 𝑋9 𝑋10 𝑋11
1 2 3 4 5 6 4 5 6 4 5 6
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋1 ∶ 1
比較し値が一致しないため要素を追加
Gosper’s algorithm
𝑋0 𝑋1 𝑋2 𝑋3 𝑋4 𝑋5 𝑋6 𝑋7 𝑋8 𝑋9 𝑋10 𝑋11
1 2 3 4 5 6 4 5 6 4 5 6
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋2 ∶ 1 2
比較し値が一致しないため要素を更新
Gosper’s algorithm
𝑋0 𝑋1 𝑋2 𝑋3 𝑋4 𝑋5 𝑋6 𝑋7 𝑋8 𝑋9 𝑋10 𝑋11
1 2 3 4 5 6 4 5 6 4 5 6
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋3 ∶ 3 2
比較し値が一致しないため要素を追加
Gosper’s algorithm
𝑋0 𝑋1 𝑋2 𝑋3 𝑋4 𝑋5 𝑋6 𝑋7 𝑋8 𝑋9 𝑋10 𝑋11
1 2 3 4 5 6 4 5 6 4 5 6
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋4 ∶ 3 2 4
比較し値が一致しないため要素を更新
Gosper’s algorithm
𝑋0 𝑋1 𝑋2 𝑋3 𝑋4 𝑋5 𝑋6 𝑋7 𝑋8 𝑋9 𝑋10 𝑋11
1 2 3 4 5 6 4 5 6 4 5 6
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋5 ∶ 5 2 4
比較し値が一致しないため要素を更新
Gosper’s algorithm
𝑋0 𝑋1 𝑋2 𝑋3 𝑋4 𝑋5 𝑋6 𝑋7 𝑋8 𝑋9 𝑋10 𝑋11
1 2 3 4 5 6 4 5 6 4 5 6
𝑋1 ∶
𝑋2 ∶
𝑋3 ∶
𝑋4 ∶
𝑋5 ∶
𝑋6 ∶
𝑋0
𝑋0 , 𝑋1
𝑋2 , 𝑋1
𝑋2 , 𝑋1 , 𝑋3
𝑋4 , 𝑋1 , 𝑋3
𝑋4 , 𝑋5 , 𝑋3
for (n = 1; ; n++) {
Xn = f(Xn);
kmax = 31 - nlz(n);
// Floor(log2 n).
for (k = 0; k <= kmax; k++) {
if (Xn == T[k]) goto L;
}
T[ntz(n+1)] = Xn;
// No match.
}
T[0] T[1] T[2] T[3]
𝑋6 ∶ 5 6 4
𝑋6 と𝑇[2]に入っている𝑋3 が一致した
のでLに移動(n=6,k=2)
Gosper’s algorithm
L:
// Compute m = max{i | i < n and ntz(i+1) = k}.
m = ((((n >> k) - 1) | 1) << k) - 1;
*lambda = n - m;
lgl = 31 - nlz(*lambda - 1); // Ceil(log2 lambda) - 1.
*mu_u = m;
// Upper bound on mu.
*mu_l = m - max(1, 1 << lgl) + 1;// Lower bound on mu.
}
𝜆を計算
n=6
(000…0110)
k=2
m=
n >> k = 000…0110>>2 = 000…0001
(n >> k) – 1 = 000…0001-1 = 000…0000
((n >> k) - 1) | 1 = (000…0000|1) = 000…0001
(((n >> k) - 1) | 1) << k = 000…0001<<2 = 000…0100
((((n >> k) - 1) | 1) << k) – 1 = 000…0100-1=000…0011 = 3
m=3
𝜆 = 𝑛 − 𝑚 = 6-3 = 3
Gosper’s algorithm
L:
// Compute m = max{i | i < n and ntz(i+1) = k}.
m = ((((n >> k) - 1) | 1) << k) - 1;
*lambda = n - m;
lgl = 31 - nlz(*lambda - 1); // Ceil(log2 lambda) - 1.
*mu_u = m;
// Upper bound on mu.
*mu_l = m - max(1, 1 << lgl) + 1;// Lower bound on mu.
}
𝜇の範囲を計算
m=3 , 𝜆=3
|g|=31-nlz(*lambda - 1) = 31-30 = 1
|g| = 1
𝜇𝑢 =3
𝜇𝑙 = 3-max(1,1<<1)+1 = 3-2+1 = 2
𝜇𝑙 =2
[Knu2] Knuth, Donald E. The Art of Computer Programming, Volume 2, Third Edition:
Seminumerical Algorithms. Addison-Wesley, 1998.
Gosper’s algorithm
このアルゴリズムは常に2巡目のいずれかのnで停止
つまり、𝑛 < 𝜇 + 2𝜆で停止[Kun2]
ruler function
ruler functionはハノイの塔のパズルの解法を明らかにする。
1.n個の円盤に0からn-1まで番号をつける
2.各移動ステップk(1 ≤ k ≤2𝑛 ‐ 1)でntz(k)番目の円盤を、循環式に見て右にある最も近い移動先に移動
まず、3個の円盤に0から2まで番号を付ける。
ステップ1
ステップ1でntz(1)=0なので0番目の円盤を循環式に見て右にある最も近い移動先に移動
0
1
2
1
2
0
ruler function
ruler functionはハノイの塔のパズルの解法を明らかにする。
1.n個の円盤に0からn-1まで番号をつける
2.各移動ステップk(1 ≤ k ≤2𝑛 ‐ 1)でntz(k)番目の円盤を、循環式に見て右にある最も近い移動先に移動
ステップ2
ステップ2でntz(2)=1なので1番目の円盤を循環式に見て右にある最も近い移動先に移動
0
1
2
2
0
1
ruler function
ruler functionはハノイの塔のパズルの解法を明らかにする。
1.n個の円盤に0からn-1まで番号をつける
2.各移動ステップk(1 ≤ k ≤2𝑛 ‐ 1)でntz(k)番目の円盤を、循環式に見て右にある最も近い移動先に移動
ステップ3
ステップ3でntz(3)=0なので0番目の円盤を循環式に見て右にある最も近い移動先に移動
2
0
1
2
0
1
ruler function
ruler functionはハノイの塔のパズルの解法を明らかにする。
1.n個の円盤に0からn-1まで番号をつける
2.各移動ステップk(1 ≤ k ≤2𝑛 ‐ 1)でntz(k)番目の円盤を、循環式に見て右にある最も近い移動先に移動
ステップ4
ステップ4でntz(4)=2なので2番目の円盤を循環式に見て右にある最も近い移動先に移動
2
0
1
2
0
1
ruler function
ruler functionはハノイの塔のパズルの解法を明らかにする。
1.n個の円盤に0からn-1まで番号をつける
2.各移動ステップk(1 ≤ k ≤2𝑛 ‐ 1)でntz(k)番目の円盤を、循環式に見て右にある最も近い移動先に移動
ステップ5
ステップ5でntz(5)=0なので0番目の円盤を循環式に見て右にある最も近い移動先に移動
2
0
1
0
2
1
ruler function
ruler functionはハノイの塔のパズルの解法を明らかにする。
1.n個の円盤に0からn-1まで番号をつける
2.各移動ステップk(1 ≤ k ≤2𝑛 ‐ 1)でntz(k)番目の円盤を、循環式に見て右にある最も近い移動先に移動
ステップ6
ステップ6でntz(6)=1なので1番目の円盤を循環式に見て右にある最も近い移動先に移動
0
2
1
0
1
2
ruler function
ruler functionはハノイの塔のパズルの解法を明らかにする。
1.n個の円盤に0からn-1まで番号をつける
2.各移動ステップk(1 ≤ k ≤2𝑛 ‐ 1)でntz(k)番目の円盤を、循環式に見て右にある最も近い移動先に移動
ステップ7
ステップ7でntz(7)=0なので0番目の円盤を循環式に見て右にある最も近い移動先に移動
0
1
2
0
1
2
ruler function
ruler functionは反射2進グレイコード(13-1節「グレイコード」を参照)の生成に使うこともできる。
任意の𝑛ビットのワードから始めて、各ステップ𝑘(これは1から2𝑛 − 1まで変化する。)において、
𝑛𝑡𝑧(𝑘)番目のビットを反転すればよい。
int ntz (unsigned int n) {
static unsigned char tab[32] =
{ 0, 1, 2, 24, 3, 19, 6, 25,
22, 4, 20, 10, 16, 7, 12, 26,
31, 23, 18, 5, 21, 9, 15, 11,
1, Code Dubé’s algorithm for the ntz function, expanding the multiplication.
30, 17, 8, 14, 29, 13, 28, 27
};
int ntz(unsigned x) {
unsigned int k;
n = n & (-n); /* isolate lsb */
static char table[32] =
#if defined(SLOW_MUL)
{ 0, 1, 2,24, 3,19, 6,25, 22,
k = (n << 11) - n;
4,20,10,16, 7,12,26,
k = (k << 2) + k;
31,23,18, 5,21, 9,15,11, 30,17,
k = (k << 8) + n;
8,14,29,13,28,27};
k = (k << 5) - k;
#else
if (x == 0) return 32;
k = n * 0x4d7651f;
x = (x & -x)*0x04D7651F;
#endif
return table[x >> 27];
return n ? tab[k>>27] : 32;
}
}
Exercises
Exercises
1, Code Dubé’s algorithm for the ntz function, expanding the multiplication.
0x4d7651f = (2047 * 5 * 256 + 1) * 31 で表せる。
#if defined(SLOW_MUL)
k = (n << 11) - n;
//k=2047
k = (k << 2) + k;
//k=k*5
k = (k << 8) + n;
//k=k*256+1
k = (k << 5) - k;
//k=k*31
Exercises
2, Code the “right justify” function,𝑥 ≫𝑢𝑛𝑡𝑧(𝑥) , x ≠ 0, in three basic RISC instructions.
𝑥 ÷𝑢(𝑥&¬𝑥)
右から見て初めの1だけ残し、それ以外を0にする
𝑛𝑡𝑧(𝑥)
「÷」は「>>」と同じ働きなので(𝑥&¬𝑥)で出てきたビット数だけ右シフトする。
Exercises
3, Are the parallel prefix and suffix (with XOR) operations invertible? If so, how would you compute the
inverse functions?
a b c d
𝑛−1 𝑢
⨁
Parallel prefix
𝑦 ← ⊕ (𝑥 ≫ 𝑖)
a b c d
𝑖
⨁
𝑥 = 𝑎𝑏𝑐𝑑(𝑎𝑏𝑐𝑑はそれぞれ1ビットを表す)
a b c d
⨁
𝑦 = 𝑝𝑝 − 𝑋𝑂𝑅 𝑥 = 𝑎 𝑎⨁𝑏 𝑎⨁𝑏⨁𝑐 𝑎⨁𝑏⨁𝑐⨁𝑑
a b c d
a a a a
𝑢
𝑦 ≫1 = (0)(𝑎)(𝑎⨁𝑏)(𝑎⨁𝑏⨁𝑐)
⨁ ⨁⨁
b b b
𝑢
𝑦⨁ 𝑦 ≫1 = 𝑎 𝑏 𝑐 𝑑 = 𝑥
⨁⨁
c c
⨁
d
Exercises
3, Are the parallel prefix and suffix (with XOR) operations invertible? If so, how would you compute the
inverse functions?
a b c d
𝑛−1 𝑢
⨁
Parallel suffix
𝑦 ← ⊕ (𝑥 ≪ 𝑖)
a b c d
𝑖
⨁
𝑥 = 𝑎𝑏𝑐𝑑(𝑎𝑏𝑐𝑑はそれぞれ1ビットを表す)
a b c d
⨁
𝑦 = 𝑝𝑠 − 𝑋𝑂𝑅 𝑥 = 𝑎⨁𝑏⨁𝑐⨁𝑑 𝑏⨁𝑐⨁𝑑 𝑐⨁𝑑 𝑑
a b c d
a
𝑢
𝑦 ≪1 = (𝑏⨁𝑐⨁𝑑)(𝑐⨁𝑑)(𝑑)(0)
⨁
b b
𝑢
𝑦⨁ 𝑦 ≪1 = 𝑎 𝑏 𝑐 𝑑 = 𝑥
⨁ ⨁
c c c
⨁ ⨁ ⨁
d d d d
© Copyright 2026 Paperzz