[インデックス 1399] ファイルの概要
このコミットは、Go言語の初期開発段階(2008年12月)において、bignum
(多倍長整数)ライブラリのテストが、その「出力(printing)」に関連する問題で失敗していたことに対する一時的な修正を記録しています。具体的には、src/lib/bignum_test.go
内の TestNatConv
関数の一部が、問題解決までの間、return;//BUG
というコメント付きでスキップされるように変更されました。これは、テストの継続的な実行を可能にしつつ、根本的な問題(多倍長整数の文字列変換やフォーマットに関するバグ)が認識されていることを示すための暫定措置です。
コミット
commit 4991f20b3f9f59d3bb423a33c550a09d079d3856
Author: Ken Thompson <ken@golang.org>
Date: Tue Dec 30 14:03:54 2008 -0800
one bignum test fails
has to do with printing
patched it out
R=r
OCL=21921
CL=21923
---
src/lib/bignum_test.go | 2 ++\n 1 file changed, 2 insertions(+)
diff --git a/src/lib/bignum_test.go b/src/lib/bignum_test.go
index 510096c5ef..f27ec752be 100644
--- a/src/lib/bignum_test.go
+++ b/src/lib/bignum_test.go
@@ -115,6 +115,8 @@ export func TestNatConv(t *testing.T) {
NAT_EQ(base, NatFromString(tmp.ToString(base), base, nil), tmp);\n }\n \n+return;//BUG\n+\n test_msg = "NatConvD";\n x := bignum.Nat(100);\n y, b := bignum.NatFromString(fmt.sprintf("%b", &x), 2, nil);\
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4991f20b3f9f59d3bb423a33c550a09d079d3856
元コミット内容
one bignum test fails
has to do with printing
patched it out
R=r
OCL=21921
CL=21923
変更の背景
このコミットは、Go言語の非常に初期の段階で発生した、bignum
(多倍長整数)ライブラリのテスト失敗に対応するためのものです。コミットメッセージによると、テストの失敗は「printing」(出力、つまり多倍長整数の文字列変換やフォーマット)に関連していました。
当時のGo言語はまだ開発途上にあり、多くのコンポーネントが活発に構築・修正されていました。bignum
のような数値計算ライブラリは、正確性とパフォーマンスが非常に重要であり、そのテストは厳密である必要があります。しかし、多倍長整数の値を様々な基数(例:2進数、10進数、16進数)で文字列に変換する処理は、特にエッジケースや非常に大きな数値において、複雑でバグが発生しやすい領域です。
テストが失敗している状態では、CI/CDパイプライン(もし当時存在していれば)や開発者のローカル環境でのテスト実行が妨げられ、他の開発作業の進行に影響を与える可能性があります。そのため、このコミットは、根本的なバグ修正に時間をかける代わりに、一時的に問題のあるテストセクションをスキップすることで、テストスイート全体がパスする状態を維持し、他の開発者が作業を続けられるようにするための「パッチアウト」(一時的な無効化)措置として行われました。//BUG
というコメントは、このスキップが一時的なものであり、将来的に修正が必要な既知のバグであることを明確に示しています。
前提知識の解説
Go言語の初期開発
このコミットは2008年12月に行われており、Go言語が一般に公開される前の非常に初期の段階です。Go言語は、GoogleのRobert Griesemer、Rob Pike、Ken Thompsonによって設計されました。Ken ThompsonはUnixの共同開発者であり、Go言語の設計と実装において中心的な役割を担っていました。この時期のコードベースは、現在のGo言語とは異なる部分が多く、例えば、export func
のようなキーワードや、fmt.sprintf
のような関数呼び出しの構文にその名残が見られます。
多倍長整数 (bignum)
「多倍長整数」(bignum、またはarbitrary-precision arithmetic)とは、コンピュータの標準的なデータ型(例:64ビット整数)で表現できる範囲を超える、任意の大きさの整数を扱うためのデータ構造とアルゴリズムの集合です。通常の整数型ではオーバーフローが発生するような非常に大きな数値を扱う際に必要となります。暗号化、科学技術計算、金融アプリケーションなどで広く利用されます。
Go言語には、標準ライブラリとして math/big
パッケージがあり、Int
、Rat
、Float
などの型で多倍長整数、有理数、浮動小数点数をサポートしています。このコミットで言及されている bignum
は、math/big
パッケージの前身、またはその初期の実装の一部であったと考えられます。
多倍長整数の実装では、数値を配列やスライスとして表現し、各要素が数値の一部(例:基数10^9の桁)を保持します。加算、減算、乗算、除算などの基本的な算術演算は、これらの配列を操作する形で実装されます。
数値の文字列変換 (Printing/Formatting)
多倍長整数を人間が読める形式(文字列)に変換する処理は、「printing」または「formatting」と呼ばれます。これは、数値を特定の基数(例:10進数、2進数、16進数)で表現し、その桁を文字列として出力するプロセスです。
例えば、fmt.sprintf("%b", &x)
は、Go言語の fmt
パッケージ(C言語の sprintf
に相当)を使用して、変数 x
の値を2進数(%b
)形式の文字列に変換しようとしています。多倍長整数の場合、この変換は特に複雑になります。
- 基数変換: 10進数から2進数、またはその逆の変換は、繰り返し除算や乗算を行うことで実現されます。多倍長整数では、これらの操作も多倍長演算として実装する必要があります。
- 効率: 非常に大きな数値を変換する場合、効率的なアルゴリズムが求められます。
- 正確性: 変換結果が元の数値と完全に一致することが保証されなければなりません。
- フォーマット: 符号、小数点、桁区切り、パディングなど、出力形式に関する様々な要件に対応する必要があります。
このコミットの背景にある問題は、おそらく bignum
の内部表現から文字列への変換ロジックにバグがあったか、または特定の大きな数値や基数での変換が期待通りに機能していなかったことを示唆しています。
技術的詳細
このコミットの技術的詳細は、bignum
ライブラリの TestNatConv
関数におけるテスト失敗と、それに対する一時的な回避策に集約されます。
TestNatConv
関数は、多倍長整数(Nat
型)の文字列変換(ToString
)と、その逆の文字列から多倍長整数への変換(NatFromString
)の正確性を検証するためのテストです。テストコードの関連部分を再掲します。
@@ -115,6 +115,8 @@ export func TestNatConv(t *testing.T) {
NAT_EQ(base, NatFromString(tmp.ToString(base), base, nil), tmp);\n }\n \n+return;//BUG\n+\n test_msg = "NatConvD";\n x := bignum.Nat(100);\n y, b := bignum.NatFromString(fmt.sprintf("%b", &x), 2, nil);\
変更前のコードでは、return;//BUG
の行は存在せず、test_msg = "NatConvD";
から始まる後続のテストロジックが実行されていました。この後続のロジックは、bignum.Nat(100)
という小さな多倍長整数 x
を作成し、それを fmt.sprintf("%b", &x)
を使って2進数文字列に変換し、さらにその文字列を bignum.NatFromString
で元の多倍長整数に戻すという一連の処理を行っています。そして、変換が正しく行われたかを検証する目的があったと推測されます。
コミットメッセージの「has to do with printing」という記述から、この fmt.sprintf("%b", &x)
の部分、または tmp.ToString(base)
の部分で問題が発生していた可能性が高いです。考えられる問題点としては以下が挙げられます。
ToString
メソッドのバグ:bignum.Nat
型のToString(base)
メソッドが、特定の基数や数値に対して誤った文字列を生成していた。NatFromString
メソッドのバグ:NatFromString
が、ToString
によって生成された(あるいは正しく生成されたはずの)文字列を正しくパースしてNat
型に戻せていなかった。fmt.sprintf
とbignum
の連携問題:fmt.sprintf
がbignum.Nat
型を2進数文字列に変換する際に、期待される動作をしなかった、またはbignum
型がfmt
パッケージのフォーマッターインターフェースを正しく実装していなかった。特に、Go言語の初期段階では、型とフォーマッターの連携がまだ成熟していなかった可能性があります。- テストロジックの誤り: テスト自体のロジックに誤りがあり、実際にはバグがないにもかかわらずテストが失敗していた。ただし、コミットメッセージが「one bignum test fails has to do with printing」と明確にバグを示唆しているため、この可能性は低いでしょう。
Ken Thompsonは、この問題の根本原因を特定し修正する代わりに、一時的に return;//BUG
を挿入することで、TestNatConv
関数がその後の問題のあるテストセクションを実行しないようにしました。これにより、テストスイート全体がパスするようになり、他の開発者がテスト失敗に悩まされることなく作業を継続できるようになります。//BUG
コメントは、このコードが一時的な回避策であり、将来的に修正が必要な既知のバグが存在することを示す標準的なプラクティスです。
この種の「パッチアウト」は、大規模なプロジェクトや活発な開発が行われている環境で、クリティカルではないが修正に時間がかかるバグに対してよく用いられる手法です。これにより、開発のフローを止めずに、バグ修正を後回しにすることができます。
コアとなるコードの変更箇所
変更は src/lib/bignum_test.go
ファイルの1箇所のみです。
--- a/src/lib/bignum_test.go
+++ b/src/lib/bignum_test.go
@@ -115,6 +115,8 @@ export func TestNatConv(t *testing.T) {
NAT_EQ(base, NatFromString(tmp.ToString(base), base, nil), tmp);\n }\n \n+return;//BUG\n+\n test_msg = "NatConvD";\n x := bignum.Nat(100);\n y, b := bignum.NatFromString(fmt.sprintf("%b", &x), 2, nil);\
具体的には、TestNatConv
関数内の既存のループ(for _, base := range bases
)の直後に、以下の2行が追加されました。
return;//BUG
コアとなるコードの解説
追加された return;//BUG
という行は、Go言語のテスト関数 TestNatConv
の実行フローを制御します。
return
: このキーワードは、現在の関数(TestNatConv
)の実行を直ちに終了させます。これにより、return
文以降に記述されているすべてのコードは実行されなくなります。//BUG
: これはGo言語の単一行コメントです。BUG
という文字列は、開発者がコードベース内で既知のバグや未解決の問題をマークするためによく使用する慣習的なコメントです。Go言語のツールチェーン(例えばgo vet
やgo doc
)は、BUG
コメントを特別に扱うことがあります。この場合、このコメントは「ここにバグがあり、このreturn
はそのバグを回避するための一時的な措置である」ということを明確に示しています。
したがって、この変更の目的は、TestNatConv
関数内の、多倍長整数の「printing」に関連して失敗していた特定のテストセクションを、一時的に実行しないようにすることです。これにより、テストスイート全体がパスするようになり、CIシステムや開発者のローカル環境でのテスト実行が妨げられなくなります。これは、バグの根本的な修正に時間がかかる場合に、開発の継続性を確保するための一般的な手法です。
関連リンク
- Go言語の初期のコミット履歴は、https://github.com/golang/go/commits/master で確認できます。
- Go言語の
math/big
パッケージのドキュメント(現在のバージョン): https://pkg.go.dev/math/big
参考にした情報源リンク
- Go言語の公式ドキュメント (pkg.go.dev)
- GitHubのGo言語リポジトリ
- 一般的なソフトウェア開発における「パッチアウト」や「一時的な回避策」に関する知識
- 多倍長整数演算に関する一般的な知識
fmt
パッケージのフォーマット動詞に関する知識