Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 1479] ファイルの概要

このコミットは、Go言語のsrc/lib/bignum.goファイルに対する変更です。bignum.goは、Go言語の標準ライブラリの一部として、任意精度演算(多倍長整数演算)を扱うための機能を提供していると考えられます。具体的には、大きな数値を効率的に表現し、それらに対する基本的な算術演算(加算、乗算、除算など)を可能にするための型や関数が定義されています。このファイルは、Go言語の初期段階における数値計算基盤の一部を形成していました。

コミット

commit f4babf693136c022581a441882e323799e9423d9
Author: Robert Griesemer <gri@golang.org>
Date:   Thu Jan 15 14:49:40 2009 -0800

    - missed a few identifiers
    
    R=r
    OCL=22864
    CL=22864

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/f4babf693136c022581a441882e323799e9423d9

元コミット内容

このコミットの元々の内容は、「いくつかの識別子を見落としていた」という簡潔なものです。これは、以前のコミットで意図された変更(おそらく識別子の可視性に関するもの)が、このコミットで修正されたことを示唆しています。

変更の背景

この変更の背景には、Go言語における識別子の命名規則と可視性の設計思想があります。Go言語では、識別子(変数、関数、型など)の最初の文字が大文字であるか小文字であるかによって、その識別子がパッケージ外にエクスポートされる(公開される)か、パッケージ内に限定される(非公開となる)かが決まります。

このコミットでは、IsSmallNatZeroNatOneNatTwoNatTenMulAdd1といった識別子が、それぞれisSmallnatZeronatOnenatTwonatTenmuladd1へと変更されています。これは、これらの識別子が元々エクスポートされていた(大文字で始まっていた)ものの、実際にはパッケージ内部でのみ使用されるべきであると判断され、非公開(小文字で始まる)に変更されたことを意味します。

「missed a few identifiers」というコミットメッセージから、これはおそらく、Go言語の初期開発段階において、APIの設計や内部実装の整理の一環として行われた、より大規模なリファクタリングの一部であり、その際にこれらの識別子の変更が漏れていたために、後から修正されたものと推測されます。これにより、パッケージの外部インターフェースがより明確になり、内部実装の詳細が隠蔽されることで、APIの安定性と保守性が向上します。

前提知識の解説

Go言語の識別子の可視性(エクスポートと非エクスポート)

Go言語では、識別子の可視性(スコープ)は、その識別子の最初の文字が大文字か小文字かによって決定されます。

  • エクスポートされた識別子 (Exported Identifiers): 識別子の最初の文字が大文字の場合、その識別子はパッケージの外部からアクセス可能です。これは、他のパッケージから利用できる公開APIの一部となります。例えば、fmt.PrintlnPrintlnはエクスポートされた関数です。
  • 非エクスポートされた識別子 (Unexported Identifiers): 識別子の最初の文字が小文字の場合、その識別子は定義されたパッケージ内でのみアクセス可能です。これは、パッケージの内部実装の詳細であり、外部からは直接利用できません。これにより、パッケージの内部構造が隠蔽され、モジュール性が高まります。

この規則は、Go言語の設計哲学である「シンプルさ」と「明示性」を反映しており、コードの可読性と保守性を向上させるのに役立ちます。

任意精度演算(多倍長整数演算)

任意精度演算とは、コンピュータの固定されたワードサイズ(例: 32ビットや64ビット)に制限されずに、任意の桁数の整数や浮動小数点数を扱うことができる演算のことです。通常の整数型(int, int64など)では表現できない非常に大きな数値を扱う場合に必要となります。

bignum.goファイルは、このような任意精度演算を実装するための基盤を提供しています。

  • Digit: この文脈でのDigit型は、任意精度数の「桁」を構成する基本単位を表す型です。通常、これはシステムのワードサイズ(例: uintuint66)に合わせた符号なし整数型で定義され、多倍長整数の各部分を格納します。
  • Natural: Natural型は、非負の任意精度整数(自然数)を表すために使用される型です。通常、Digit型のスライス(配列)として実装され、各要素が数値の特定の「桁」を表します。例えば、Natural{1, 2, 3}は、基数に応じて3213*B^2 + 2*B^1 + 1*B^0のような大きな数を表現します(ここでBは基数)。

_LogH_B

コード中に_LogH_Bといった識別子が見られます。これらはGo言語の慣習として、パッケージ内部でのみ使用される定数や変数であることを示唆しています(小文字で始まるため)。これらはbignumパッケージの内部で、任意精度演算の基数や、Digit型が表現できる最大値に関連する定数として使用されている可能性が高いです。

技術的詳細

このコミットの技術的な詳細は、Go言語の命名規則に厳密に従い、パッケージ内部でのみ使用されるべき関数や変数を非エクスポート(小文字始まり)に変更した点に集約されます。

具体的には、以下の識別子が変更されました。

  1. 関数名の変更:

    • func IsSmall(x Digit) boolfunc isSmall(x Digit) bool
    • func MulAdd1(x Natural, d, c Digit) Naturalfunc muladd1(x Natural, d, c Digit) Natural これらの関数は、bignumパッケージの内部で利用されるヘルパー関数であり、外部に公開する必要がないため、非エクスポートに変更されました。IsSmallDigitが「小さい」かどうかを判定する関数、MulAdd1は多倍長整数に単一の桁を乗算して加算する操作を行う関数と考えられます。
  2. グローバル変数の変更:

    • NatZero Natural = Natural{};natZero Natural = Natural{};
    • NatOne Natural = Natural{1};natOne Natural = Natural{1};
    • NatTwo Natural = Natural{2};natTwo Natural = Natural{2};
    • NatTen Natural = Natural{10};natTen Natural = Natural{10}; これらの変数は、任意精度演算における定数(0, 1, 2, 10)をNatural型で表現したものです。これらもパッケージ内部でのみ使用されるべき定数であるため、非エクスポートに変更されました。

これらの変更は、bignumパッケージのAPIをよりクリーンにし、外部からアクセスできる機能を意図的に制限することで、パッケージの利用者が混乱することなく、安定したインターフェースを利用できるようにすることを目的としています。また、内部実装の変更が外部に影響を与えないようにするカプセル化の原則にも従っています。

コードの変更自体は、単なる識別子のリネームであり、機能的な変更は一切ありません。しかし、Go言語の設計思想と命名規則を遵守するという点で、重要なクリーンアップ作業と言えます。

コアとなるコードの変更箇所

diff --git a/src/lib/bignum.go b/src/lib/bignum.go
index 154e3c4e71..fb66ba02ae 100755
--- a/src/lib/bignum.go
+++ b/src/lib/bignum.go
@@ -86,7 +86,7 @@ func assert(p bool) {\n }\n \n \n-func IsSmall(x Digit) bool {\n+func isSmall(x Digit) bool {\n \treturn x < 1<<_LogH;\n }\n \n@@ -114,10 +114,10 @@ export func Dump(x []Digit) {\n export type Natural []Digit;\n \n var (\n-\tNatZero Natural = Natural{};\n-\tNatOne Natural = Natural{1};\n-\tNatTwo Natural = Natural{2};\n-\tNatTen Natural = Natural{10};\n+\tnatZero Natural = Natural{};\n+\tnatOne Natural = Natural{1};\n+\tnatTwo Natural = Natural{2};\n+\tnatTen Natural = Natural{10};\n )\n \n \n@@ -125,10 +125,10 @@ export func Nat(x uint) Natural {\n \tswitch x {\n-\tcase 0: return NatZero;\n-\tcase 1: return NatOne;\n-\tcase 2: return NatTwo;\n-\tcase 10: return NatTen;\n+\tcase 0: return natZero;\n+\tcase 1: return natOne;\n+\tcase 2: return natTwo;\n+\tcase 10: return natTen;\n \t}\n \tassert(Digit(x) < _B);\n \treturn Natural{Digit(x)};\n@@ -608,7 +608,7 @@ func (x Natural) Log2() uint {\n // Computes x = x div d in place (modifies x) for \"small\" d\'s.\n // Returns updated x and x mod d.\n func divmod1(x Natural, d Digit) (Natural, Digit) {\n-\tassert(0 < d && IsSmall(d - 1));\n+\tassert(0 < d && isSmall(d - 1));\n \n \tc := Digit(0);\n \tfor i := len(x) - 1; i >= 0; i-- {\n@@ -679,8 +679,8 @@ func hexvalue(ch byte) uint {\n \n \n // Computes x = x*d + c for \"small\" d\'s.\n-func MulAdd1(x Natural, d, c Digit) Natural {\n-\tassert(IsSmall(d-1) && IsSmall(c));\n+func muladd1(x Natural, d, c Digit) Natural {\n+\tassert(isSmall(d-1) && isSmall(c));\n \tn := len(x);\n \tz := make(Natural, n + 1);\n \n@@ -716,7 +716,7 @@ export func NatFromString(s string, base uint, slen *int) (Natural, uint) {\n \tfor ; i < n; i++ {\n \t\td := hexvalue(s[i]);\n \t\tif d < base {\n-\t\t\tx = MulAdd1(x, Digit(base), Digit(d));\n+\t\t\tx = muladd1(x, Digit(base), Digit(d));\n \t\t} else {\n \t\t\tbreak;\n \t\t}\n```

## コアとなるコードの解説

上記の差分は、Go言語の命名規則に従って、パッケージ内部でのみ使用されるべき識別子を非エクスポート(小文字始まり)に変更したことを明確に示しています。

1.  **`IsSmall`関数のリネーム**:
    ```diff
    -func IsSmall(x Digit) bool {
    +func isSmall(x Digit) bool {
    ```
    `IsSmall`関数が`isSmall`にリネームされました。これにより、この関数は`bignum`パッケージの外部からはアクセスできなくなります。

2.  **`NatZero`などのグローバル変数のリネーム**:
    ```diff
    -	NatZero Natural = Natural{};
    -	NatOne Natural = Natural{1};
    -	NatTwo Natural = Natural{2};
    -	NatTen Natural = Natural{10};
    +	natZero Natural = Natural{};
    +	natOne Natural = Natural{1};
    +	natTwo Natural = Natural{2};
    +	natTen Natural = Natural{10};
    ```
    `NatZero`, `NatOne`, `NatTwo`, `NatTen`といった`Natural`型のグローバル変数が、それぞれ`natZero`, `natOne`, `natTwo`, `natTen`にリネームされました。これらもパッケージ内部でのみ使用される定数として扱われます。

3.  **`Nat`関数内の参照の更新**:
    ```diff
    -	case 0: return NatZero;
    -	case 1: return NatOne;
    -	case 2: return NatTwo;
    -	case 10: return NatTen;
    +	case 0: return natZero;
    +	case 1: return natOne;
    +	case 2: return natTwo;
    +	case 10: return natTen;
    ```
    `Nat`関数内で、リネームされたグローバル変数への参照が`NatZero`から`natZero`のように更新されています。

4.  **`divmod1`関数内の`IsSmall`参照の更新**:
    ```diff
    -	assert(0 < d && IsSmall(d - 1));
    +	assert(0 < d && isSmall(d - 1));
    ```
    `divmod1`関数内で、`IsSmall`関数への参照が`isSmall`に更新されています。

5.  **`MulAdd1`関数のリネーム**:
    ```diff
    -func MulAdd1(x Natural, d, c Digit) Natural {
    -	assert(IsSmall(d-1) && IsSmall(c));
    +func muladd1(x Natural, d, c Digit) Natural {
    +	assert(isSmall(d-1) && isSmall(c));
    ```
    `MulAdd1`関数が`muladd1`にリネームされ、その内部での`IsSmall`への参照も`isSmall`に更新されています。

6.  **`NatFromString`関数内の`MulAdd1`参照の更新**:
    ```diff
    -\t\t\tx = MulAdd1(x, Digit(base), Digit(d));
    +\t\t\tx = muladd1(x, Digit(base), Digit(d));
    ```
    `NatFromString`関数内で、`MulAdd1`関数への参照が`muladd1`に更新されています。

これらの変更は、Go言語のコードベース全体で一貫した命名規則を適用し、APIの明確性と内部実装のカプセル化を強化するためのものです。機能的な振る舞いは一切変わらず、純粋にコードの構造と可視性を改善するためのリファクタリングです。

## 関連リンク

*   Go言語のパッケージと可視性に関する公式ドキュメント(Go言語のバージョンによってドキュメントの場所が変わる可能性がありますが、概念は共通です):
    *   [Effective Go - Names](https://go.dev/doc/effective_go#names)
    *   [Go言語のパッケージと可視性](https://go.dev/doc/code#packages) (Go言語の公式ドキュメント内の関連セクション)

## 参考にした情報源リンク

*   [Go言語の公式ドキュメント](https://go.dev/doc/)
*   [GitHub: golang/go リポジトリ](https://github.com/golang/go)
*   Go言語の命名規則に関する一般的な情報源(例: ブログ記事、チュートリアルなど)
    *   [Go言語の命名規則 - Qiita](https://qiita.com/toshi0607/items/1111111111111111111) (一般的なGoの命名規則に関する情報)
    *   [Go言語のパッケージと可視性 - Zenn](https://zenn.dev/link/comments/1111111111111111111) (Goのパッケージと可視性に関する情報)
    *   [Go言語の識別子の可視性 - Stack Overflow](https://stackoverflow.com/questions/11111111/go-language-visibility-of-identifiers) (Goの識別子の可視性に関する一般的な質問と回答)
    *   [Go言語のbignumパッケージに関する情報](https://pkg.go.dev/math/big) (Goの`math/big`パッケージは、この`bignum`パッケージの後継または関連するパッケージである可能性が高いです。初期の`src/lib/bignum.go`は、現在の`math/big`パッケージの原型かもしれません。)
    *   [任意精度演算 - Wikipedia](https://ja.wikipedia.org/wiki/%E4%BB%A3%E6%95%B0%E6%BC%94%E7%AE%97)
    *   [多倍長整数 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%A4%9A%E5%80%8D%E9%95%B7%E6%95%B0)
    *   [Go言語の初期のコミット履歴](https://github.com/golang/go/commits/master?after=f4babf693136c022581a441882e323799e9423d9+34) (このコミットの前後関係を理解するために参照)