Skip to content

Commit

Permalink
<stdfloat> : 残りを書いた #1022
Browse files Browse the repository at this point in the history
  • Loading branch information
faithandbrave committed Feb 22, 2023
1 parent 4818ff7 commit dcbf835
Show file tree
Hide file tree
Showing 7 changed files with 820 additions and 24 deletions.
5 changes: 5 additions & 0 deletions GLOBAL_QUALIFY_LIST.txt
Expand Up @@ -167,6 +167,11 @@
* <stack>[link /reference/stack.md]
* <stacktrace>[link /reference/stacktrace.md]
* <stdexcept>[link /reference/stdexcept.md]
* <stdfloat>[link /reference/stdfloat.md]
* std::bfloat16_t[link /reference/stdfloat/bfloat16_t.md]
* std::float16_t[link /reference/stdfloat/float16_t.md]
* std::float32_t[link /reference/stdfloat/float32_t.md]
* std::float64_t[link /reference/stdfloat/float64_t.md]
* <stop_token>[link /reference/stop_token.md]
* <streambuf>[link /reference/streambuf.md]
* <string>[link /reference/string.md]
Expand Down
8 changes: 4 additions & 4 deletions reference/stdfloat.md
Expand Up @@ -10,10 +10,10 @@
| 名前 | 説明 | 対応バージョン |
|------|------|----------------|
| [`float16_t`](stdfloat/float16_t.md) | 16ビット半精度の浮動小数点数型 | C++23 |
| [`float32_t`](stdfloat/float32_t.md.nolink) | 32ビット単精度の浮動小数点数型 | C++23 |
| [`float64_t`](stdfloat/float64_t.md.nolink) | 64ビット倍精度の浮動小数点数型 | C++23 |
| [`float128_t`](stdfloat/float128_t.md.nolink) | 128ビット四倍精度の浮動小数点数型 | C++23 |
| [`bfloat16_t`](stdfloat/bfloat16_t.md.nolink) | 16ビットのbrain floating point型 | C++23 |
| [`float32_t`](stdfloat/float32_t.md) | 32ビット単精度の浮動小数点数型 | C++23 |
| [`float64_t`](stdfloat/float64_t.md) | 64ビット倍精度の浮動小数点数型 | C++23 |
| [`float128_t`](stdfloat/float128_t.md) | 128ビット四倍精度の浮動小数点数型 | C++23 |
| [`bfloat16_t`](stdfloat/bfloat16_t.md) | 16ビットのbrain floating point型 | C++23 |


## バージョン
Expand Down
187 changes: 187 additions & 0 deletions reference/stdfloat/bfloat16_t.md
@@ -0,0 +1,187 @@
# bfloat16_t
* stdfloat[meta header]
* std[meta namespace]
* type-alias[meta id-type]
* cpp23[meta cpp]

```cpp
namespace std {
#if defined(__STDCPP_BFLOAT16_T__)
using bfloat16_t = implementation-defined;
#endif
}
```
## 概要
16ビットのbrain floating point型。
### 内部表現
この型はISO/IEC/IEEE 60559 (IEEE 754) にはない16ビットの浮動小数点数型である。
Google社のTPUや、NVIDIAのGPUなどで採用されている内部表現をもつ。
| 型 | 符号ビット数 | 指数ビット数 | 仮数ビット数 | 最大指数 |
|--------------|--------------|--------------|--------------|----------|
| `bfloat16_t` | 1 | 8 | 7 | 127 |
| `float16_t` | 1 | 5 | 10 | 15 |
### リテラル
値にサフィックスとして`bf16`もしくは`BF16`を指定することで、`std::bfloat16_t`のリテラルとすることができる。
```cpp
std::bfloat16_t a = 1.0bf16;
std::bfloat16_t b = 2.0BF16;
```


### 事前定義マクロ
- この型は、事前定義マクロ`__STDCPP_BFLOAT16_T__`が定義されない場合、定義されない


### 順位
浮動小数点数の変換で使用される順位 (rank) は、以下のように定義される:

- `long double` > `double` > `float`のように、`long double`が最も高い順位をもつ
- 同じ値集合をもつ2つの拡張浮動小数点数型は、同じ順位をもつ
- 標準浮動小数点数型と同じ値集合をもつ拡張浮動小数点数型は、同じ順位をもつ
- 標準浮動小数点数型より多くの値集合をもつ拡張浮動小数点数型は、`double`と同じ順位をもつ

注意として、浮動小数点数型`T1`の値集合が浮動小数点数型`T2`の値集合の部分集合でも上位集合でもない場合、浮動小数点数型`T1``T2`の変換順位は順位通りではない。これは、一方の型が他方より大きな範囲と低い精度の両方を持つ場合に起こり得る。

順位が同じ浮動小数点数型は、サブ順位 (subrank) で順序付けられる。拡張浮動小数点数は、標準浮動小数点数型よりも大きなサブ順位をもつ。


### 昇格と変換
C言語の名残と後方互換性のために、オーバーロード解決での`float`から`double`への変換は昇格と見なされるが、ほかの浮動小数点数型では昇格はない。

2つの浮動小数点型の少なくとも一方が拡張浮動小数点型である場合、変換先の型が変換元の型より大きいか等しい場合にのみ、2つの浮動小数点型間の変換が暗黙的に行われる。いかなる暗黙の変換も損失なく、値を正確に保持する。潜在的に損失のある変換はすべて明示的でなければならない。

小さい精度への変換は、`()``{}`による直接初期化、もしくは明示的なキャストのみ許可される。

```cpp
void f(std::float16_t);
void g() {
std::float16_t a = 1.0; // エラー!小さい精度への暗黙変換はできない
std::float16_t b(2.0); // OK : 直接初期化
std::float16_t c{3.0}; // OK : 直接初期化
a = 4.0; // エラー!小さい精度への暗黙変換はできない
f(5.0); // エラー!小さい精度への暗黙変換はできない
f(static_cast<std::float16_t>(5.0)); // OK : 明示的なキャスト
}
```
### 通常の算術変換
算術演算での型変換は、以下のような規則で行われる。
- どちらかのオペランドが浮動小数点数型である場合、
- 両方のオペランドが同じ型であれば、型変換は行われない
- そうでなく、オペランドの一方が浮動小数点数型でなければ、浮動小数点数型のオペランドの型に変換される
- そうでなく、オペランドの浮動小数点数型の変換順位が等しくない場合、小さい方の順位をもつ浮動小数点数型は、もう一方の浮動小数点数型に変換される
- `float + double`は`double`に、`std::float16_t + float`は`float`に変換される
- そうでなく、変換順位が等しい場合、サブ順位で比較が行われ、より大きいサブ順位をもつ浮動小数点数型に変換される
- `float + std::float32_t`は`std::float32_t`に変換される
- そうでなければ、式は不適格となる
- `std::float16_t + std::bfloat16_t`は不適格
```cpp example
#include <stdfloat>
#include <type_traits>
int main() {
float f32 = 1.0;
std::float16_t f16{2.0};
std::bfloat16_t b16{3.0};
std::float32_t f32b{4.0};
auto r1 = f32 + f16; // OK : f16は`float`に変換され、結果の型は`float`となる
auto r2 = f32 + b16; // OK : b16は`float`に変換され、結果の型は`float`となる
//auto r3 = f16 + b16; // エラー!どちらの型も算術変換でもう一方の型に変換できない
auto r4 = f32 + f32b; // OK : f32はより大きいサブ順位をもつ`std::float32_t`に変換される
static_assert(std::is_same_v<decltype(r4), std::float32_t>);
}
```

### オーバーロード解決
- 浮動小数点数型の変換をともなうオーバーロード解決は、値を維持する変換が優先され、同じ変換順位をもつ他の浮動小数点数型への変換が優先して行われる
- 値を維持する変換が曖昧な場合、プログラムは不適格となる

```cpp
#include <stdfloat>

void f(std::float32_t) {}
void f(std::float64_t) {}
void f(long long) {}

int main() {
float x;
std::float16_t y;
f(x); // f(std::float32_t)が呼び出される。
// floatとstd::float32_tが同じ変換順位をもつ
//f(y); // エラー!曖昧。変換順位が等しいオーバーロードが見つからない
}
```
## 備考
- この型は、C23で定義されるオプションキーワード`_Float16`の別名として定義されることになるだろう
- この型は、`_Float16`と相互運用できることが望ましい
## 例
```cpp example
#include <iostream>
#include <stdfloat>
#include <cmath>
int main() {
std::bfloat16_t a = 1.0bf16;
auto b = 2.0f32; // bの型はstd::float32_t
// 明示的型変換によって、
// float16_tとの間の変換ができる
auto aa = static_cast<std::float16_t>(a);
// aはより大きい精度の型float32_tに変換される
auto c = a + b; // cの型はstd::float32_t
// 精度を落とす縮小変換は明示的型変換で行う。
// 拡張浮動小数点数型は数学関数にも渡すことができ、
// 標準浮動小数点数型への暗黙変換もできる
double d = std::log(static_cast<std::bfloat16_t>(c));
// 同じ精度の浮動小数点数型との間で、精度を落とさず変換でき、
// coutでも拡張浮動小数点数のまま出力できる
std::cout << static_cast<std::float64_t>(d) << std::endl;
}
```
* std::log[link /reference/cmath/log.md]

### 出力
```
1.10156
```

## バージョン
### 言語
- C++23

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): 13.1
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`std::float16_t`](float16_t.md)
- [`std::float32_t`](float32_t.md)
- [`std::float64_t`](float64_t.md)
- [`std::float128_t`](float128_t.md)


## 参照
- [P1467R9 Extended floating-point types and standard names](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1467r9.html)

179 changes: 179 additions & 0 deletions reference/stdfloat/float128_t.md
@@ -0,0 +1,179 @@
# float128_t
* stdfloat[meta header]
* std[meta namespace]
* type-alias[meta id-type]
* cpp23[meta cpp]

```cpp
namespace std {
#if defined(__STDCPP_FLOAT128_T__)
using float128_t = implementation-defined;
#endif
}
```
## 概要
128ビット四倍精度の浮動小数点数型。
### 内部表現
この型は、ISO/IEC/IEEE 60559 (IEEE 754) 浮動小数点数規格のbinary128フォーマットをもつ。
| 符号ビット数 | 指数ビット数 | 仮数ビット数 | 最大指数 |
|--------------|--------------|--------------|----------|
| 1 | 15 | 112 | 16383 |
### リテラル
値にサフィックスとして`f128`もしくは`F128`を指定することで、`std::float128_t`のリテラルとすることができる。
```cpp
std::float128_t a = 1.0f128;
std::float128_t b = 2.0F128;
```


### 事前定義マクロ
- この型は、事前定義マクロ`__STDCPP_FLOAT128_T__`が定義されない場合、定義されない
- ISO/IEC/IEEE 60559 (IEEE 754) のbinary128フォーマットが実装される環境でこのマクロは定義される


### 順位
浮動小数点数の変換で使用される順位 (rank) は、以下のように定義される:

- `long double` > `double` > `float`のように、`long double`が最も高い順位をもつ
- 同じ値集合をもつ2つの拡張浮動小数点数型は、同じ順位をもつ
- 標準浮動小数点数型と同じ値集合をもつ拡張浮動小数点数型は、同じ順位をもつ
- 標準浮動小数点数型より多くの値集合をもつ拡張浮動小数点数型は、`double`と同じ順位をもつ

注意として、浮動小数点数型`T1`の値集合が浮動小数点数型`T2`の値集合の部分集合でも上位集合でもない場合、浮動小数点数型`T1``T2`の変換順位は順位通りではない。これは、一方の型が他方より大きな範囲と低い精度の両方を持つ場合に起こり得る。

順位が同じ浮動小数点数型は、サブ順位 (subrank) で順序付けられる。拡張浮動小数点数は、標準浮動小数点数型よりも大きなサブ順位をもつ。


### 昇格と変換
C言語の名残と後方互換性のために、オーバーロード解決での`float`から`double`への変換は昇格と見なされるが、ほかの浮動小数点数型では昇格はない。

2つの浮動小数点型の少なくとも一方が拡張浮動小数点型である場合、変換先の型が変換元の型より大きいか等しい場合にのみ、2つの浮動小数点型間の変換が暗黙的に行われる。いかなる暗黙の変換も損失なく、値を正確に保持する。潜在的に損失のある変換はすべて明示的でなければならない。

小さい精度への変換は、`()``{}`による直接初期化、もしくは明示的なキャストのみ許可される。

```cpp
void f(std::float16_t);
void g() {
std::float16_t a = 1.0; // エラー!小さい精度への暗黙変換はできない
std::float16_t b(2.0); // OK : 直接初期化
std::float16_t c{3.0}; // OK : 直接初期化
a = 4.0; // エラー!小さい精度への暗黙変換はできない
f(5.0); // エラー!小さい精度への暗黙変換はできない
f(static_cast<std::float16_t>(5.0)); // OK : 明示的なキャスト
}
```
### 通常の算術変換
算術演算での型変換は、以下のような規則で行われる。
- どちらかのオペランドが浮動小数点数型である場合、
- 両方のオペランドが同じ型であれば、型変換は行われない
- そうでなく、オペランドの一方が浮動小数点数型でなければ、浮動小数点数型のオペランドの型に変換される
- そうでなく、オペランドの浮動小数点数型の変換順位が等しくない場合、小さい方の順位をもつ浮動小数点数型は、もう一方の浮動小数点数型に変換される
- `float + double`は`double`に、`std::float16_t + float`は`float`に変換される
- そうでなく、変換順位が等しい場合、サブ順位で比較が行われ、より大きいサブ順位をもつ浮動小数点数型に変換される
- `float + std::float32_t`は`std::float32_t`に変換される
- そうでなければ、式は不適格となる
- `std::float16_t + std::bfloat16_t`は不適格
```cpp example
#include <stdfloat>
#include <type_traits>
int main() {
float f32 = 1.0;
std::float16_t f16{2.0};
std::bfloat16_t b16{3.0};
std::float32_t f32b{4.0};
auto r1 = f32 + f16; // OK : f16は`float`に変換され、結果の型は`float`となる
auto r2 = f32 + b16; // OK : b16は`float`に変換され、結果の型は`float`となる
//auto r3 = f16 + b16; // エラー!どちらの型も算術変換でもう一方の型に変換できない
auto r4 = f32 + f32b; // OK : f32はより大きいサブ順位をもつ`std::float32_t`に変換される
static_assert(std::is_same_v<decltype(r4), std::float32_t>);
}
```

### オーバーロード解決
- 浮動小数点数型の変換をともなうオーバーロード解決は、値を維持する変換が優先され、同じ変換順位をもつ他の浮動小数点数型への変換が優先して行われる
- 値を維持する変換が曖昧な場合、プログラムは不適格となる

```cpp
#include <stdfloat>

void f(std::float32_t) {}
void f(std::float64_t) {}
void f(long long) {}

int main() {
float x;
std::float16_t y;
f(x); // f(std::float32_t)が呼び出される。
// floatとstd::float32_tが同じ変換順位をもつ
//f(y); // エラー!曖昧。変換順位が等しいオーバーロードが見つからない
}
```
## 備考
- この型は、C23で定義されるオプションキーワード`_Float16`の別名として定義されることになるだろう
- この型は、`_Float16`と相互運用できることが望ましい
## 例
```cpp example
#include <iostream>
#include <stdfloat>
#include <cmath>
int main() {
std::float16_t a = 1.0f16;
auto b = 2.0f32; // bの型はstd::float32_t
// aはより大きい精度の型float32_tに変換される
auto c = a + b; // cの型はstd::float32_t
// 精度を落とす縮小変換は明示的型変換で行う。
// 拡張浮動小数点数型は数学関数にも渡すことができ、
// 標準浮動小数点数型への暗黙変換もできる
double d = std::log(static_cast<std::float16_t>(c));
// 同じ精度の浮動小数点数型との間で、精度を落とさず変換でき、
// coutでも拡張浮動小数点数のまま出力できる
std::cout << static_cast<std::float64_t>(d) << std::endl;
}
```
* std::log[link /reference/cmath/log.md]

### 出力
```
1.09863
```

## バージョン
### 言語
- C++23

### 処理系
- [Clang](/implementation.md#clang): ??
- [GCC](/implementation.md#gcc): 13.1
- [Visual C++](/implementation.md#visual_cpp): ??


## 関連項目
- [`std::float16_t`](float16_t.md)
- [`std::float32_t`](float32_t.md)
- [`std::float64_t`](float64_t.md)
- [`std::bfloat16_t`](bfloat16_t.md)


## 参照
- [P1467R9 Extended floating-point types and standard names](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1467r9.html)

0 comments on commit dcbf835

Please sign in to comment.