remquo, remquof, remquol
| ヘッダー <math.h> で定義 |
||
| float remquof( float x, float y, int *quo ); |
(1) | (C99以降) |
| double remquo( double x, double y, int *quo ); |
(2) | (C99以降) |
| long double remquol( long double x, long double y, int *quo ); |
(3) | (C99以降) |
| ヘッダー <tgmath.h> で定義 |
||
| #define remquo( x, y, quo ) |
(4) | (C99以降) |
remquol が呼び出されます。それ以外の場合、ポインタでない引数のいずれかが整数型または double 型の場合、remquo が呼び出されます。それ以外の場合、remquof が呼び出されます。目次 |
[編集] パラメータ
| x, y | - | 浮動小数点値 |
| quo | - | x/y の符号といくつかのビットを格納する整数値へのポインタ |
[編集] 戻り値
成功した場合、remainder で定義されている除算 x/y の浮動小数点剰余を返します。また、*quo には、x/y の符号と下位 3 ビット以上のビットが格納されます(形式的には、符号が x/y の符号であり、絶対値が x/y の整数商の絶対値に合同(modulo 2n)な値が格納されます。ここで n は実装定義の整数で、3 以上です)。
y がゼロの場合、*quo に格納される値は未定義です。
領域エラーが発生した場合、実装定義の値が返される (サポートされている場合はNaN)。
アンダーフローによる範囲エラーが発生した場合、サブノーマルがサポートされていれば正しい結果が返されます。
y がゼロであっても、ドメインエラーが発生しない場合は、ゼロが返されます。
[編集] エラー処理
エラーは math_errhandling で指定されたとおりに報告されます。
y がゼロの場合、ドメインエラーが発生する可能性があります。
実装がIEEE浮動小数点算術 (IEC 60559) をサポートしている場合、
- 現在の丸めモードは影響しません。
- FE_INEXACT は決して発生しません。
- x が ±∞ で y が NaN でない場合、NaN が返され、FE_INVALID が発生します。
- y が ±0 で x が NaN でない場合、NaN が返され、FE_INVALID が発生します。
- x または y のいずれかが NaN の場合、NaN が返されます。
[編集] 注記
POSIX では、x が無限大であるか、y がゼロである場合にドメインエラーが発生することが要求されています。
この関数は、周期が浮動小数点値として正確に表現可能な周期関数を実装する際に役立ちます。非常に大きな x に対して sin(πx) を計算する場合、直接 sin を呼び出すと大きな誤差が生じる可能性がありますが、関数引数をまず remquo で正規化すると、商の下位ビットを使用して周期内での結果の符号とオクタントを決定でき、剰余を使用して高精度で値を計算できます。
一部のプラットフォームでは、この操作はハードウェアでサポートされています(例: Intel CPU では、FPREM1 は商に正確に 3 ビットの精度を残します)。
[編集] 例
#include <fenv.h> #include <math.h> #include <stdio.h> #ifndef __GNUC__ #pragma STDC FENV_ACCESS ON #endif double cos_pi_x_naive(double x) { const double pi = acos(-1); return cos(pi * x); } // the period is 2, values are (0;0.5) positive, (0.5;1.5) negative, (1.5,2) positive double cos_pi_x_smart(double x) { const double pi = acos(-1); int extremum; double rem = remquo(x, 1, &extremum); extremum = (unsigned)extremum % 2; // keep 1 bit to determine nearest extremum return extremum ? -cos(pi * rem) : cos(pi * rem); } int main(void) { printf("cos(pi * 0.25) = %f\n", cos_pi_x_naive(0.25)); printf("cos(pi * 1.25) = %f\n", cos_pi_x_naive(1.25)); printf("cos(pi * 1000000000000.25) = %f\n", cos_pi_x_naive(1000000000000.25)); printf("cos(pi * 1000000000001.25) = %f\n", cos_pi_x_naive(1000000000001.25)); printf("cos(pi * 1000000000000.25) = %f\n", cos_pi_x_smart(1000000000000.25)); printf("cos(pi * 1000000000001.25) = %f\n", cos_pi_x_smart(1000000000001.25)); // error handling feclearexcept(FE_ALL_EXCEPT); int quo; printf("remquo(+Inf, 1) = %.1f\n", remquo(INFINITY, 1, &quo)); if (fetestexcept(FE_INVALID)) puts(" FE_INVALID raised"); }
実行結果の例
cos(pi * 0.25) = 0.707107
cos(pi * 1.25) = -0.707107
cos(pi * 1000000000000.25) = 0.707123
cos(pi * 1000000000001.25) = -0.707117
cos(pi * 1000000000000.25) = 0.707107
cos(pi * 1000000000001.25) = -0.707107
remquo(+Inf, 1) = -nan
FE_INVALID raised[編集] 参考文献
- C23標準 (ISO/IEC 9899:2024)
- 7.12.10.3 The remquo functions (p: TBD)
- 7.25 Type-generic math <tgmath.h> (p: TBD)
- F.10.7.3 The remquo functions (p: TBD)
- C17標準 (ISO/IEC 9899:2018)
- 7.12.10.3 The remquo functions (p: 186)
- 7.25 型総称数学関数 <tgmath.h> (p: 272-273)
- F.10.7.3 The remquo functions (p: 385)
- C11標準 (ISO/IEC 9899:2011)
- 7.12.10.3 The remquo functions (p: 255)
- 7.25 型総称数学関数 <tgmath.h> (p: 373-375)
- F.10.7.3 The remquo functions (p: 529)
- C99標準 (ISO/IEC 9899:1999)
- 7.12.10.3 The remquo functions (p: 236)
- 7.22 型総称数学関数 <tgmath.h> (p: 335-337)
- F.9.7.3 The remquo functions (p: 465)
[編集] 関連項目
| (C99) |
整数の除算における商と剰余を計算する (関数) |
| (C99)(C99) |
浮動小数点除算演算の余りを計算する (関数) |
| (C99)(C99)(C99) |
浮動小数点除算演算の符号付き余りを計算する (関数) |
| C++ ドキュメント remquo
| |