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

[インデックス 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?というコメントと共に処理が未実装でした。このコミットでFloat80Kindcaseが完全に削除され、float80型がfloat64として扱われる可能性がなくなりました。
  • printField関数: この関数は、リフレクションで取得したフィールドの型に基づいて値をフォーマットします。変更前はreflect.Float64Kindreflect.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というコメントと共に、Float80ValueStructGetSetメソッドの実装がコメントアウトされていました。これは、float80に対するコード生成が困難であったことを明確に示しており、今回の削除の主要な理由の一つと考えられます。
  • creatorマップ: creatorマップからFloat80Kindに対応するfloat80Creatorの登録が削除されました。このマップは、特定のKindに対応するValueインスタンスを作成するために使用されます。

これらの変更は、Go言語のランタイムと標準ライブラリからfloat80型を完全に排除し、float32float64のみに浮動小数点型のサポートを限定するという明確な方針を示しています。これにより、Go言語の設計目標であるシンプルさ、移植性、そして予測可能性が強化されました。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴: https://github.com/golang/go/commits/master
  • IEEE 754に関する一般的な情報源
  • Go言語の設計に関する議論(初期のメーリングリストやデザインドキュメントなど、公開されているものがあれば)