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

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

このコミットは、Go言語の任意精度演算ライブラリであるbignumパッケージに対する重要な更新を含んでいます。主な変更点は、パッケージ名のGo言語の慣例に合わせた小文字化と、任意精度整数に対するビット論理演算(AND, OR, XOR)の基本的な実装です。これにより、bignumパッケージの機能が拡張され、より実用的なものとなりました。

コミット

commit 2727abe4fc0e169c5414e5cb0c1cc7d5d33bf69d
Author: Robert Griesemer <gri@golang.org>
Date:   Wed Nov 12 11:00:11 2008 -0800

    - lowercased package name (Bignum -> bignum)
    - implemented some missing functionality (and, or, xor of positive ints)
    
    R=r
    OCL=19087
    CL=19087

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

https://github.com/golang/go/commit/2727abe4fc0e169c5414e5cb0c1cc7d5d33bf69d

元コミット内容

- lowercased package name (Bignum -> bignum)
- implemented some missing functionality (and, or, xor of positive ints)

R=r
OCL=19087
CL=19087

変更の背景

このコミットが行われた2008年11月は、Go言語がまだ一般に公開される前の初期開発段階にありました。この時期は、言語の設計原則や標準ライブラリの構造が固められていく重要なフェーズでした。

変更の背景には、主に以下の2点があります。

  1. Go言語のパッケージ命名規則への準拠: Go言語では、パッケージ名を小文字で記述するのが慣例です。初期のコードベースでは、この慣例が完全に適用されていない部分があり、Bignumのような大文字始まりのパッケージ名が存在していました。このコミットは、Go言語全体のコードベースの一貫性を保つために、命名規則を統一する作業の一環として行われました。
  2. 任意精度演算ライブラリの機能拡充: bignumパッケージは、Go言語で任意精度の整数や浮動小数点数を扱うための基盤を提供するものです。初期段階では、基本的な算術演算が実装されていましたが、ビット論理演算(AND, OR, XOR)のような、数値型にとって不可欠な機能が欠けていました。このコミットは、これらの不足している機能を、特に正の整数に限定して実装することで、パッケージの実用性を高めることを目的としています。負の数に対するビット演算はより複雑な考慮が必要なため、段階的な実装が選択されたと考えられます。

前提知識の解説

1. Go言語のパッケージ命名規則

Go言語では、パッケージ名は通常、そのパッケージが提供する機能を表す短い単一の単語で、すべて小文字で記述されます。例えば、HTTPクライアントを提供するパッケージはnet/http、文字列操作を提供するパッケージはstringsとなります。この慣例は、コードの可読性と一貫性を高めるために非常に重要です。大文字で始まる識別子(関数名、変数名など)はエクスポートされ、パッケージ外からアクセス可能になりますが、パッケージ名自体は小文字が推奨されます。

2. 任意精度演算 (Arbitrary-precision arithmetic)

通常のプログラミング言語で提供される整数型(例: int, long)や浮動小数点型(例: float, double)は、表現できる数値の範囲や精度に限界があります。これに対し、任意精度演算は、メモリが許す限り、任意の大きさの整数や任意の精度の浮動小数点数を扱うことができる計算手法です。科学技術計算、暗号学、金融計算など、非常に大きな数や高い精度が要求される分野で利用されます。Go言語のmath/bigパッケージ(このコミット時点ではbignum)がこれに該当します。

3. ビット演算 (Bitwise operations)

ビット演算は、数値をビット列として扱い、個々のビットに対して論理演算を行うものです。主に以下の3つが基本となります。

  • AND (&): 両方のビットが1の場合にのみ結果が1となる。
  • OR (|): どちらか一方または両方のビットが1の場合に結果が1となる。
  • XOR (^): どちらか一方のビットのみが1の場合に結果が1となる(排他的論理和)。

これらの演算は、フラグの操作、データのマスク、暗号化、ハッシュ計算など、様々な低レベルのプログラミングで利用されます。任意精度整数に対しても、これらのビット演算は重要な機能となります。

技術的詳細

このコミットは、src/lib/bignum.goファイルに対して行われました。

  1. パッケージ名の変更: ファイルの先頭にあるpackage Bignumpackage bignumに変更されました。これは、Go言語のパッケージ命名規則に厳密に準拠するための変更であり、機能的な影響はありませんが、コードベース全体の整合性を高めます。

  2. ビット論理演算の実装: Integer型にAnd, Or, Xorの3つのメソッドが追加されました。これらのメソッドは、任意精度整数に対するビット論理演算を提供します。

    • 正の整数に限定した実装: コミットメッセージにもあるように、これらのメソッドは現時点では「正の整数」に限定して実装されています。コードを見ると、!x.sign && !y.signという条件で、両方のオペランドが非負(signfalseは非負を表す慣例)の場合にのみ実際の演算(x.mant.And(y.mant)など)が行われています。
    • 負の数に対する未実装のハンドリング: オペランドのいずれか、または両方が負の場合(elseブロック)、panic("UNIMPLEMENTED Integer.And() of negative values")のような形で、未実装であることを示すパニックが発生するように記述されています。これは、負の数のビット演算が2の補数表現など、より複雑なロジックを必要とするため、後回しにされたことを示唆しています。初期開発段階では、まず基本的な機能から実装し、徐々に複雑なケースに対応していくアプローチが一般的です。
    • mantフィールドの利用: x.mant.And(y.mant)のように、Integer型の内部表現であるmant(仮数部、符号なしの絶対値部分)に対して実際のビット演算が行われています。これは、任意精度整数の内部が、ビット列として扱えるような構造になっていることを示しています。
  3. Integer.Shrのパニックメッセージの修正: 既存のInteger.Shr(右シフト)メソッドにおいて、負の値に対する未実装のパニックメッセージがpanic("UNIMPLEMENTED")からpanic("UNIMPLEMENTED Integer.Shr() of negative values")へと、より具体的で分かりやすいメッセージに修正されています。これも、開発の初期段階でデバッグや将来の作業を容易にするための改善です。

これらの変更は、bignumパッケージが単なる算術演算だけでなく、ビットレベルでの操作も可能にするための重要な一歩であり、Go言語の標準ライブラリが徐々に成熟していく過程を示しています。

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

変更はsrc/lib/bignum.goファイルに集中しています。

--- a/src/lib/bignum.go
+++ b/src/lib/bignum.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package Bignum
+package bignum
 
 // A package for arbitrary precision arithmethic.
 // It implements the following numeric types:\n
@@ -1076,27 +1076,42 @@ func (x *Integer) Shl(s uint) *Integer {
 func (x *Integer) Shr(s uint) *Integer {
 		z := MakeInt(x.sign, x.mant.Shr(s));
 		if x.IsNeg() {
-			panic("UNIMPLEMENTED");
+			panic("UNIMPLEMENTED Integer.Shr() of negative values");
 		}
 		return z;
 }
 
 
 func (x *Integer) And(y *Integer) *Integer {
-	panic("UNIMPLEMENTED");
-	return nil;
+	var z *Integer;
+	if !x.sign && !y.sign {
+		z = MakeInt(false, x.mant.And(y.mant));
+	} else {
+		panic("UNIMPLEMENTED Integer.And() of negative values");
+	}
+	return z;
 }
 
 
 func (x *Integer) Or(y *Integer) *Integer {
-	panic("UNIMPLEMENTED");
-	return nil;
+	var z *Integer;
+	if !x.sign && !y.sign {
+		z = MakeInt(false, x.mant.Or(y.mant));
+	} else {
+		panic("UNIMPLEMENTED Integer.Or() of negative values");
+	}
+	return z;
 }
 
 
 func (x *Integer) Xor(y *Integer) *Integer {
-	panic("UNIMPLEMENTED");
-	return nil;
+	var z *Integer;
+	if !x.sign && !y.sign {
+		z = MakeInt(false, x.mant.Xor(y.mant));
+	} else {
+		panic("UNIMPLEMENTED Integer.Xor() of negative values");
+	}
+	return z;
 }
 
 

コアとなるコードの解説

1. パッケージ名の変更 (package Bignum -> package bignum)

これは、Go言語の標準的なコーディング規約に準拠するための変更です。Goでは、パッケージ名は通常、すべて小文字で記述されます。この変更により、bignumパッケージはGoエコシステム内の他のパッケージとの一貫性を保ち、よりGoらしいコードベースに統合されます。機能的な影響は一切ありませんが、プロジェクト全体の品質と保守性を向上させます。

2. Integer.And, Integer.Or, Integer.Xor メソッドの追加

これらのメソッドは、Integer型(任意精度整数)に対するビット論理積(AND)、ビット論理和(OR)、ビット排他的論理和(XOR)の操作を実装しています。

  • 実装のロジック: 各メソッドは、まずz *Integer;として結果を格納するInteger型の変数を宣言します。 次に、if !x.sign && !y.signという条件で、xyの両方が非負(signフィールドがfalse)であるかをチェックしています。Goのmath/bigパッケージ(当時のbignum)では、signフィールドがfalseであれば非負、trueであれば負を表すのが一般的です。 この条件が真の場合、つまり両方のオペランドが正の整数である場合にのみ、実際のビット演算が行われます。MakeInt(false, x.mant.And(y.mant))のように、結果のIntegerを生成し、その符号をfalse(非負)に設定し、内部のmant(仮数部、つまり数値の絶対値を表すビット列)に対してビット演算を実行しています。mantは通常、big.Wordのスライスなどで構成されており、その上でビット演算が定義されています。
  • 負の数に対する未実装の扱い: elseブロックでは、オペランドのいずれか、または両方が負の場合にpanicを発生させています。例えば、panic("UNIMPLEMENTED Integer.And() of negative values");というメッセージが出力されます。これは、負の数のビット演算(特に2の補数表現を考慮したビット演算)が正の数よりも複雑であり、このコミット時点ではまだ実装が完了していないことを明確に示しています。開発の初期段階では、最も一般的なケース(正の数)から実装を進め、徐々にエッジケースや複雑なケースに対応していくのが効率的なアプローチです。

3. Integer.Shr のパニックメッセージの修正

Integer.Shr(右シフト)メソッドは以前から存在していましたが、負の数に対する操作が未実装でした。このコミットでは、その未実装を示すパニックメッセージがpanic("UNIMPLEMENTED")からpanic("UNIMPLEMENTED Integer.Shr() of negative values");へと変更されました。この修正は、エラーメッセージをより具体的かつ情報量の多いものにすることで、デバッグの容易性や将来の機能追加の際の指針を改善することを目的としています。

これらの変更は、bignumパッケージがGo言語の標準ライブラリとして成長していく過程で、機能の拡充とコード品質の向上が図られていることを示しています。

関連リンク

参考にした情報源リンク

  • Go言語の公式ドキュメント(パッケージ命名規則など、一般的なGoの慣例に関する情報)
  • 任意精度演算に関する一般的な情報
  • ビット演算に関する一般的な情報
  • Go言語のmath/bigパッケージの現在の実装(当時のbignumパッケージの進化形)