[インデックス 1790] ファイルの概要
このコミットは、Go言語の標準ライブラリからfloat80
型(80ビット浮動小数点数)のサポートを削除するものです。具体的には、src/lib/fmt
パッケージとsrc/lib/reflect
パッケージ内のfloat80
に関連するコードが削除されています。
コミット
Go言語の標準ライブラリからfloat80
型を削除するコミット。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/1fe42e2d4d8f7898ba60af2986bf0d0db7a80d19
元コミット内容
commit 1fe42e2d4d8f7898ba60af2986bf0d0db7a80d19
Author: Rob Pike <r@golang.org>
Date: Mon Mar 9 18:00:41 2009 -0700
delete float80 from libraries
R=rsc
DELTA=40 (0 added, 38 deleted, 2 changed)
OCL=25969
CL=25969
---
src/lib/fmt/print.go | 4 +---\n src/lib/reflect/all_test.go | 1 -\n src/lib/reflect/tostring.go | 4 +---\n src/lib/reflect/type.go | 4 ----\n src/lib/reflect/value.go | 29 -----------------------------\n 5 files changed, 2 insertions(+), 40 deletions(-)
diff --git a/src/lib/fmt/print.go b/src/lib/fmt/print.go
index b5b1fed452..ca5bec9341 100644
--- a/src/lib/fmt/print.go
+++ b/src/lib/fmt/print.go
@@ -315,8 +315,6 @@ func getFloat64(v reflect.Value) (val float64, ok bool) {
}
case reflect.Float64Kind:
return float64(v.(reflect.Float64Value).Get()), true;
- case reflect.Float80Kind:
- break; // TODO: what to do here?
}
return 0.0, false;
}
@@ -388,7 +386,7 @@ func (p *pp) printField(field reflect.Value) (was_string bool) {
case reflect.Float32Kind:
v, ok := getFloat32(field);
s = p.fmt.Fmt_g32(v).Str();
- case reflect.Float64Kind, reflect.Float80Kind:
+ case reflect.Float64Kind:
v, ok := getFloat64(field);
s = p.fmt.Fmt_g64(v).Str();
case reflect.FloatKind:
diff --git a/src/lib/reflect/all_test.go b/src/lib/reflect/all_test.go
index 7636f09501..2ce669721d 100644
--- a/src/lib/reflect/all_test.go
+++ b/src/lib/reflect/all_test.go
@@ -108,7 +108,6 @@ func TestAll(tt *testing.T) { // TODO(r): wrap up better
typedump("float", "float");
typedump("float32", "float32");
typedump("float64", "float64");
- typedump("float80", "float80");
typedump("int8", "int8");
typedump("whoknows.whatsthis", "$missing$");
typedump("**int8", "**int8");
diff --git a/src/lib/reflect/tostring.go b/src/lib/reflect/tostring.go
index 202d0ecbc3..bb673fc224 100644
--- a/src/lib/reflect/tostring.go
+++ b/src/lib/reflect/tostring.go
@@ -78,7 +78,7 @@ func typeToString(typ Type, expand bool) string {
return "$missing$";
case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind,
UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind,
-\t FloatKind, Float32Kind, Float64Kind, Float80Kind,
+\t FloatKind, Float32Kind, Float64Kind,
StringKind,
DotDotDotKind:
return typ.Name();
@@ -170,8 +170,6 @@ func valueToString(val Value) string {
return strconv.Ftoa32(val.(Float32Value).Get(), 'g', -1);
case Float64Kind:
return strconv.Ftoa64(val.(Float64Value).Get(), 'g', -1);
- case Float80Kind:
- return "float80";
case StringKind:
return val.(StringValue).Get();
case BoolKind:
diff --git a/src/lib/reflect/type.go b/src/lib/reflect/type.go
index fcc33e442d..9b3bd35d4d 100644
--- a/src/lib/reflect/type.go
+++ b/src/lib/reflect/type.go
@@ -33,7 +33,6 @@ const (
FloatKind;
Float32Kind;
Float64Kind;
- Float80Kind;
FuncKind;
IntKind;
Int16Kind;
@@ -140,7 +139,6 @@ var (\
Float = newBasicType("float", FloatKind, unsafe.Sizeof(float(0)));
Float32 = newBasicType("float32", Float32Kind, 4);
Float64 = newBasicType("float64", Float64Kind, 8);
- Float80 = newBasicType("float80", Float80Kind, 10); // TODO: strange size?
String = newBasicType("string", StringKind, unsafe.Sizeof(""));
)
@@ -467,7 +465,6 @@ func init() {
types["float"] = Float;
types["float32"] = Float32;
types["float64"] = Float64;
- types["float80"] = Float80;
types["string"] = String;
types["bool"] = Bool;
@@ -490,7 +487,6 @@ func init() {
basicstub["float"] = newStubType("float", Float);
basicstub["float32"] = newStubType("float32", Float32);
basicstub["float64"] = newStubType("float64", Float64);
- basicstub["float80"] = newStubType("float80", Float80);
basicstub["string"] = newStubType("string", String);
basicstub["bool"] = newStubType("bool", Bool);
diff --git a/src/lib/reflect/value.go b/src/lib/reflect/value.go
index f4e63407ad..7bd6f3b153 100644
--- a/src/lib/reflect/value.go
+++ b/src/lib/reflect/value.go
@@ -438,34 +438,6 @@ func (v *float64ValueStruct) Set(f float64) {
*(*float64)(v.addr) = f
}
-// -- Float80
-
-// Float80Value represents a float80 value.
-type Float80Value interface {
- Value;
- Get() float80; // Get the underlying float80.
- Set(float80); // Get the underlying float80.
-}
-
-type float80ValueStruct struct {
- commonValue
-}
-
-func float80Creator(typ Type, addr Addr) Value {
- return &float80ValueStruct{ commonValue{Float80Kind, typ, addr} }
-}
-
-/*
-BUG: can't gen code for float80s
-func (v *Float80ValueStruct) Get() float80 {
- return *(*float80)(v.addr)
-}
-
-func (v *Float80ValueStruct) Set(f float80) {
- *(*float80)(v.addr) = f
-}
-*/
-
// -- String
// StringValue represents a string value.
@@ -819,7 +791,6 @@ var creator = map[int] creatorFn {
FloatKind : floatCreator,\n \tFloat32Kind : float32Creator,\n \tFloat64Kind : float64Creator,\n-\tFloat80Kind : float80Creator,\n \tStringKind : stringCreator,\n \tBoolKind : boolCreator,\n \tPtrKind : ptrCreator,\n```
## 変更の背景
このコミットは、Go言語の初期開発段階において、`float80`型(80ビット浮動小数点数)のサポートを標準ライブラリから削除するものです。`float80`は、主にIntel x86アーキテクチャのFPU(浮動小数点演算ユニット)で内部的に使用される拡張精度浮動小数点形式であり、IEEE 754標準で定義されている`binary64`(倍精度、64ビット)や`binary32`(単精度、32ビット)とは異なる特性を持ちます。
Go言語は、設計当初からシンプルさと移植性を重視しており、特定のハードウェアアーキテクチャに強く依存するデータ型や機能は避ける傾向にあります。`float80`は、その性質上、x86以外のアーキテクチャではネイティブにサポートされていないことが多く、ソフトウェアエミュレーションが必要になる場合があります。これはパフォーマンスの低下や、異なるプラットフォーム間での浮動小数点演算の非一貫性につながる可能性があります。
コミットメッセージ内のコメント「`BUG: can't gen code for float80s`」は、`float80`型に対するコード生成が困難であったことを示唆しています。これは、コンパイラやランタイムが`float80`を効率的かつ正確に扱うための実装上の課題に直面していたことを意味します。Go言語の設計哲学として、言語仕様や標準ライブラリは、堅牢で予測可能であり、かつ複数のアーキテクチャで一貫した動作を提供することが求められます。`float80`のサポートは、これらの目標と矛盾する可能性があったため、Go言語のコアライブラリから削除されることになりました。
結果として、Go言語はIEEE 754で広くサポートされている`float32`(単精度)と`float64`(倍精度)のみを標準の浮動小数点型として提供することになり、これにより言語の移植性と予測可能性が向上しました。
## 前提知識の解説
### 浮動小数点数 (Floating-Point Numbers)
浮動小数点数は、実数を近似的に表現するためのコンピュータの数値表現形式です。非常に大きな数や非常に小さな数を、固定されたビット数で効率的に表現できます。一般的に、符号部、指数部、仮数部で構成されます。
### IEEE 754
IEEE 754は、浮動小数点演算の標準規格です。この標準は、浮動小数点数の表現形式(ビットの割り当て)、特殊な値(無限大、非数NaN)、丸め規則、および基本的な演算(加算、減算、乗算、除算、平方根)の動作を定義しています。Go言語の`float32`と`float64`は、それぞれIEEE 754の単精度(binary32)と倍精度(binary64)に準拠しています。
### 80ビット拡張精度浮動小数点数 (Float80 / Extended Precision)
`float80`は、IEEE 754で定義されている「拡張精度」形式の一つで、主にIntel x86アーキテクチャのFPUで内部的に使用される80ビットの浮動小数点形式です。これは、`float32`や`float64`よりも高い精度と広い範囲を提供しますが、その実装はハードウェアに強く依存し、他のアーキテクチャではサポートされていないことが多いです。そのため、移植性や互換性の問題が生じやすいという特徴があります。
### Go言語の `reflect` パッケージ
`reflect`パッケージは、Goプログラムの実行時に型情報(`Type`)と値情報(`Value`)を検査・操作するための機能を提供します。これにより、Goの型システムを動的に扱うことが可能になります。例えば、構造体のフィールド名を取得したり、関数の引数を動的に渡したりすることができます。
* **`reflect.Type`**: Goの型のメタデータを表します。例えば、`int`、`string`、`struct{}`などの型情報です。
* **`reflect.Value`**: Goの変数の実行時の値を表します。
`reflect`パッケージは、Goの標準ライブラリやフレームワーク、特にシリアライゼーション/デシリアライゼーション、データベースドライバ、RPCシステムなどで広く利用されています。
### Go言語の `fmt` パッケージ
`fmt`パッケージは、Go言語におけるフォーマットI/O(入力/出力)機能を提供します。C言語の`printf`や`scanf`に似た機能を提供し、様々な型の値を文字列に変換して出力したり、文字列から値を解析したりすることができます。`fmt.Printf`や`fmt.Println`などがこのパッケージに含まれます。
## 技術的詳細
このコミットは、Go言語の標準ライブラリから`float80`型を完全に削除するための変更を含んでいます。これは、Go言語が特定のハードウェアアーキテクチャに依存しない、よりポータブルで一貫性のある浮動小数点演算を提供するための重要なステップです。
### `reflect`パッケージへの影響
`reflect`パッケージは、Goの型システムを動的に扱うための基盤です。`float80`の削除は、このパッケージの以下の側面に影響を与えます。
1. **`reflect.Kind`の削除**: `reflect.Kind`は、Goの組み込み型の種類を識別するための定数です。`Float80Kind`が削除されることで、Goの型システムが`float80`を認識しなくなります。
2. **`reflect.Type`の生成と管理の変更**: `newBasicType`関数は、基本的な型(`int`, `float64`など)の`reflect.Type`インスタンスを作成するために使用されます。`Float80`の削除に伴い、`Float80`型の`reflect.Type`インスタンスの生成コードが削除されます。
3. **`reflect.Value`の操作の変更**: `reflect.Value`は実行時の値を表します。`Float80Value`インターフェースとその実装(`float80ValueStruct`)が削除されることで、`reflect`パッケージは`float80`型の値を動的に取得したり設定したりする機能を失います。
4. **`creator`マップからの削除**: `creator`マップは、特定の`Kind`に対応する`Value`インスタンスを作成するための関数を保持しています。`Float80Kind`に対応する`float80Creator`が削除されます。
5. **`typeToString`および`valueToString`からの削除**: `reflect`パッケージ内の型や値を文字列に変換する関数から`Float80Kind`の処理が削除されます。これにより、`float80`型がリフレクションによって文字列として表現されることがなくなります。
6. **テストコードの削除**: `reflect`パッケージのテストコードから`float80`に関連するテストケースが削除されます。
### `fmt`パッケージへの影響
`fmt`パッケージは、Goの値を文字列にフォーマットするための機能を提供します。`float80`の削除は、このパッケージの以下の側面に影響を与えます。
1. **`getFloat64`関数の変更**: `getFloat64`関数は、`reflect.Value`から`float64`値を取得しようとします。以前は`reflect.Float80Kind`の場合の処理がコメントアウトされていましたが、このコミットでそのケース自体が削除されます。
2. **`printField`関数の変更**: `printField`関数は、`reflect.Value`の型に基づいて値をフォーマットします。以前は`reflect.Float64Kind`と`reflect.Float80Kind`の両方を`Fmt_g64`で処理していましたが、`float80`の削除により`reflect.Float64Kind`のみを処理するように変更されます。
これらの変更により、Go言語のランタイムと標準ライブラリは`float80`型を完全に認識しなくなり、`float32`と`float64`のみが公式にサポートされる浮動小数点型となります。これにより、Goプログラムの動作がより予測可能になり、異なるプラットフォーム間での互換性が向上します。
## コアとなるコードの変更箇所
### `src/lib/fmt/print.go`
```diff
--- a/src/lib/fmt/print.go
+++ b/src/lib/fmt/print.go
@@ -315,8 +315,6 @@ func getFloat64(v reflect.Value) (val float64, ok bool) {
}
case reflect.Float64Kind:
return float64(v.(reflect.Float64Value).Get()), true;
- case reflect.Float80Kind:
- break; // TODO: what to do here?
}
return 0.0, false;
}
@@ -388,7 +386,7 @@ func (p *pp) printField(field reflect.Value) (was_string bool) {
case reflect.Float32Kind:
v, ok := getFloat32(field);
s = p.fmt.Fmt_g32(v).Str();
- case reflect.Float64Kind, reflect.Float80Kind:
+ case reflect.Float64Kind:
v, ok := getFloat64(field);
s = p.fmt.Fmt_g64(v).Str();
case reflect.FloatKind:
src/lib/reflect/all_test.go
--- a/src/lib/reflect/all_test.go
+++ b/src/lib/reflect/all_test.go
@@ -108,7 +108,6 @@ func TestAll(tt *testing.T) { // TODO(r): wrap up better
typedump("float", "float");
typedump("float32", "float32");
typedump("float64", "float64");
- typedump("float80", "float80");
typedump("int8", "int8");
typedump("whoknows.whatsthis", "$missing$");
typedump("**int8", "**int8");
src/lib/reflect/tostring.go
--- a/src/lib/reflect/tostring.go
+++ b/src/lib/reflect/tostring.go
@@ -78,7 +78,7 @@ func typeToString(typ Type, expand bool) string {
return "$missing$";
case IntKind, Int8Kind, Int16Kind, Int32Kind, Int64Kind,
UintKind, Uint8Kind, Uint16Kind, Uint32Kind, Uint64Kind,
-\t FloatKind, Float32Kind, Float64Kind, Float80Kind,
+\t FloatKind, Float32Kind, Float64Kind,
StringKind,
DotDotDotKind:
return typ.Name();
@@ -170,8 +170,6 @@ func valueToString(val Value) string {
return strconv.Ftoa32(val.(Float32Value).Get(), 'g', -1);
case Float64Kind:
return strconv.Ftoa64(val.(Float64Value).Get(), 'g', -1);
- case Float80Kind:
- return "float80";
case StringKind:
return val.(StringValue).Get();
case BoolKind:
src/lib/reflect/type.go
--- a/src/lib/reflect/type.go
+++ b/src/lib/reflect/type.go
@@ -33,7 +33,6 @@ const (
FloatKind;
Float32Kind;
Float64Kind;
- Float80Kind;
FuncKind;
IntKind;
Int16Kind;
@@ -140,7 +139,6 @@ var (\
Float = newBasicType("float", FloatKind, unsafe.Sizeof(float(0)));
Float32 = newBasicType("float32", Float32Kind, 4);
Float64 = newBasicType("float64", Float64Kind, 8);
- Float80 = newBasicType("float80", Float80Kind, 10); // TODO: strange size?
String = newBasicType("string", StringKind, unsafe.Sizeof(""));
)
@@ -467,7 +465,6 @@ func init() {
types["float"] = Float;
types["float32"] = Float32;
types["float64"] = Float64;
- types["float80"] = Float80;
types["string"] = String;
types["bool"] = Bool;
@@ -490,7 +487,6 @@ func init() {
basicstub["float"] = newStubType("float", Float);
basicstub["float32"] = newStubType("float32", Float32);
basicstub["float64"] = newStubType("float64", Float64);
- basicstub["float80"] = newStubType("float80", Float80);
basicstub["string"] = newStubType("string", String);
basicstub["bool"] = Bool;
src/lib/reflect/value.go
--- a/src/lib/reflect/value.go
+++ b/src/lib/reflect/value.go
@@ -438,34 +438,6 @@ func (v *float64ValueStruct) Set(f float64) {
*(*float64)(v.addr) = f
}
-// -- Float80
-
-// Float80Value represents a float80 value.
-type Float80Value interface {
- Value;
- Get() float80; // Get the underlying float80.
- Set(float80); // Get the underlying float80.
-}
-
-type float80ValueStruct struct {
- commonValue
-}
-
-func float80Creator(typ Type, addr Addr) Value {
- return &float80ValueStruct{ commonValue{Float80Kind, typ, addr} }
-}
-
-/*
-BUG: can't gen code for float80s
-func (v *Float80ValueStruct) Get() float80 {
- return *(*float80)(v.addr)
-}
-
-func (v *Float80ValueStruct) Set(f float80) {
- *(*float80)(v.addr) = f
-}
-*/
-
// -- String
// StringValue represents a string value.
@@ -819,7 +791,6 @@ var creator = map[int] creatorFn {
FloatKind : floatCreator,\n \tFloat32Kind : float32Creator,\n \tFloat64Kind : float64Creator,\n-\tFloat80Kind : float80Creator,\n \tStringKind : stringCreator,\n \tBoolKind : boolCreator,\n \tPtrKind : ptrCreator,\
コアとなるコードの解説
src/lib/fmt/print.go
getFloat64
関数: この関数はreflect.Value
からfloat64
値を取得しようとします。変更前はreflect.Float80Kind
の場合のcase
文がありましたが、TODO: what to do here?
というコメントと共に処理が未実装でした。このコミットでFloat80Kind
のcase
が完全に削除され、float80
型がfloat64
として扱われる可能性がなくなりました。printField
関数: この関数は、リフレクションで取得したフィールドの型に基づいて値をフォーマットします。変更前はreflect.Float64Kind
とreflect.Float80Kind
の両方をまとめてFmt_g64
で処理しようとしていました。float80
の削除により、reflect.Float64Kind
のみがFmt_g64
で処理されるようになり、float80
のフォーマット処理が削除されました。
src/lib/reflect/all_test.go
TestAll
関数: リフレクションの型ダンプテストからtypedump("float80", "float80")
の行が削除されました。これは、float80
型がGoの型システムから削除されたため、その型をテストする必要がなくなったことを意味します。
src/lib/reflect/tostring.go
typeToString
関数: この関数はreflect.Type
を文字列に変換します。変更前はFloat80Kind
が他の浮動小数点型と共にリストされていましたが、このコミットでFloat80Kind
が削除されました。これにより、float80
型がリフレクションによって型名として認識されなくなります。valueToString
関数: この関数はreflect.Value
を文字列に変換します。変更前はFloat80Kind
の場合に"float80"
という文字列を返すcase
文がありましたが、このコミットでそのcase
が削除されました。これにより、float80
型の値がリフレクションによって文字列として表現されることがなくなります。
src/lib/reflect/type.go
const
ブロック:reflect.Kind
の定数定義からFloat80Kind
が削除されました。これは、Goの型システムがfloat80
を認識しなくなったことを意味します。var
ブロック:Float80
型のreflect.Type
インスタンスを生成するnewBasicType
の呼び出しが削除されました。また、コメントで「TODO: strange size?
」とあったように、float80
のサイズ(10バイト)が他の基本型と異なり、扱いが困難であったことが示唆されています。init
関数:types
マップとbasicstub
マップから"float80"
キーとその対応するreflect.Type
インスタンスの登録が削除されました。これらのマップは、文字列名からreflect.Type
を取得するために使用されます。
src/lib/reflect/value.go
Float80Value
インターフェースとfloat80ValueStruct
構造体:float80
型の値をリフレクションで扱うためのインターフェースと、その具体的な実装構造体が完全に削除されました。これには、Get()
とSet()
メソッドの定義も含まれます。float80Creator
関数:Float80Value
インスタンスを作成するためのファクトリ関数が削除されました。- コメントアウトされたコード:
BUG: can't gen code for float80s
というコメントと共に、Float80ValueStruct
のGet
とSet
メソッドの実装がコメントアウトされていました。これは、float80
に対するコード生成が困難であったことを明確に示しており、今回の削除の主要な理由の一つと考えられます。 creator
マップ:creator
マップからFloat80Kind
に対応するfloat80Creator
の登録が削除されました。このマップは、特定のKind
に対応するValue
インスタンスを作成するために使用されます。
これらの変更は、Go言語のランタイムと標準ライブラリからfloat80
型を完全に排除し、float32
とfloat64
のみに浮動小数点型のサポートを限定するという明確な方針を示しています。これにより、Go言語の設計目標であるシンプルさ、移植性、そして予測可能性が強化されました。
関連リンク
- Go言語の公式ドキュメント(
reflect
パッケージ): https://pkg.go.dev/reflect - Go言語の公式ドキュメント(
fmt
パッケージ): https://pkg.go.dev/fmt - IEEE 754標準に関する情報(Wikipedia): https://ja.wikipedia.org/wiki/IEEE_754
参考にした情報源リンク
- Go言語のコミット履歴: https://github.com/golang/go/commits/master
- IEEE 754に関する一般的な情報源
- Go言語の設計に関する議論(初期のメーリングリストやデザインドキュメントなど、公開されているものがあれば)