名前空間
変種
操作

std::remquo, std::remquof, std::remquol

From cppreference.com
< cpp‎ | numeric‎ | math
 
 
 
 
ヘッダー <cmath> で定義
(1)
float       remquo ( float x, float y, int* quo );

double      remquo ( double x, double y, int* quo );

long double remquo ( long double x, long double y, int* quo );
(C++11以降)
(C++23まで)
constexpr /* floating-point-type */

            remquo ( /* 浮動小数点型 */ x,

                     /* 浮動小数点型 */ y, int* quo );
(C++23から)
float       remquof( float x, float y, int* quo );
(2) (C++11以降)
(C++23 以降 constexpr)
long double remquol( long double x, long double y, int* quo );
(3) (C++11以降)
(C++23 以降 constexpr)
ヘッダー <cmath> で定義
template< class Arithmetic1, class Arithmetic2 >

/* 共通浮動小数点型 */

    remquo( Arithmetic1 x, Arithmetic2 y, int* quo );
(A) (C++11以降)
(C++23 以降 constexpr)
1-3) x / y の除算の浮動小数点剰余を、std::remainder() 関数と同じように計算します。さらに、x / y の符号と下位 3 ビット以上のビットが quo に格納されます。これは、結果のオクターントを周期内で決定するのに十分な情報です。ライブラリは、パラメータ x および y の型として、すべての cv 修飾されていない浮動小数点型に対する std::remquo のオーバーロードを提供します。(since C++23)
A) その他の算術型の組み合わせすべてに対して、追加のオーバーロードが提供されます。

目次

[edit] パラメータ

x, y - 浮動小数点または整数値
quo - x / y の符号と下位ビットを格納するための、int へのポインタ

[edit] 戻り値

成功した場合、x / y の除算の浮動小数点剰余を std::remainder で定義されている通りに返します。また、*quo には、x / y の符号と下位 3 ビット以上のビットを格納します(正式には、符号が x / y の符号であり、絶対値が x / y の整数商の絶対値に、n ≥ 3 である実装定義の整数 n を法として合同な値を格納します)。

y がゼロの場合、*quo に格納される値は未定義です。

領域エラーが発生した場合、実装定義の値が返される (サポートされている場合はNaN)。

アンダーフローによる範囲エラーが発生した場合、サブノーマルがサポートされていれば正しい結果が返されます。

y がゼロでも、定義域エラーが発生しない場合、ゼロが返されます。

[edit] エラー処理

エラーは 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 が返されます。

[edit] 注記

POSIX ではx が無限大であるか y がゼロである場合に定義域エラーが発生することが要求されています。

この関数は、周期が浮動小数点値として正確に表現できる周期関数を実装する際に役立ちます。非常に大きな x に対して sin(πx) を計算する場合、std::sin を直接呼び出すと大きな誤差が生じる可能性がありますが、関数引数をまず std::remquo で正規化すると、商の下位ビットを使用して周期内での結果の符号とオクターントを決定でき、剰余を使用して高精度で値を計算できます。

一部のプラットフォームでは、この操作はハードウェアでサポートされています(例:Intel CPU では、FPREM1 は完了時に商に正確に 3 ビットの精度を残します)。

追加のオーバーロードは (A) とまったく同じように提供される必要はない。それらは、最初の引数 num1 と2番目の引数 num2 に対して以下を保証するのに十分である必要がある。

  • num1 または num2 の型が long double である場合、std::remquo(num1, num2, quo)std::remquo(static_cast<long double>(num1),
                static_cast<long double>(num2), quo)
    と同じ効果があります。
  • それ以外の場合、num1 および/または num2 の型が double または整数型である場合、std::remquo(num1, num2, quo)std::remquo(static_cast<double>(num1),
                static_cast<double>(num2), quo)
    と同じ効果があります。
  • それ以外の場合、num1 または num2 の型が float である場合、std::remquo(num1, num2, quo)std::remquo(static_cast<float>(num1),
                static_cast<float>(num2), quo)
    と同じ効果があります。
(C++23まで)

num1num2 が算術型である場合、std::remquo(num1, num2, quo)std::remquo(static_cast</*共通浮動小数点型*/>(num1),
            static_cast</*共通浮動小数点型*/>(num2), quo)
と同じ効果があります。ここで、/*共通浮動小数点型*/ は、num1num2 の型の間で、最も高い 浮動小数点変換ランク と最も高い 浮動小数点変換サブランク を持つ浮動小数点型です。整数型の引数は、double と同じ浮動小数点変換ランクを持つとみなされます。

そのような最高のランクとサブランクセを持つ浮動小数点型が存在しない場合、オーバーロード解決は提供されたオーバーロードから使用可能な候補を導出しません。

(C++23から)

[edit]

#include <cfenv>
#include <cmath>
#include <iostream>
 
#ifndef __GNUC__
#pragma STDC FENV_ACCESS ON
#endif
 
const double pi = std::acos(-1); // or std::numbers::pi since C++20
 
double cos_pi_x_naive(double x)
{
    return std::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)
{
    int quadrant;
    double rem = std::remquo(x, 1, &quadrant);
    quadrant = static_cast<unsigned>(quadrant) % 2; // The period is 2.
    return quadrant == 0 ?  std::cos(pi * rem)
                         : -std::cos(pi * rem);
}
 
int main()
{
    std::cout << std::showpos
              << "naive:\n"
              << "  cos(pi * 0.25) = " << cos_pi_x_naive(0.25) << '\n'
              << "  cos(pi * 1.25) = " << cos_pi_x_naive(1.25) << '\n'
              << "  cos(pi * 2.25) = " << cos_pi_x_naive(2.25) << '\n'
              << "smart:\n"
              << "  cos(pi * 0.25) = " << cos_pi_x_smart(0.25) << '\n'
              << "  cos(pi * 1.25) = " << cos_pi_x_smart(1.25) << '\n'
              << "  cos(pi * 2.25) = " << cos_pi_x_smart(2.25) << '\n'
              << "naive:\n"
              << "  cos(pi * 1000000000000.25) = "
              << cos_pi_x_naive(1000000000000.25) << '\n'
              << "  cos(pi * 1000000000001.25) = "
              << cos_pi_x_naive(1000000000001.25) << '\n'
              << "smart:\n"
              << "  cos(pi * 1000000000000.25) = "
              << cos_pi_x_smart(1000000000000.25) << '\n'
              << "  cos(pi * 1000000000001.25) = "
              << cos_pi_x_smart(1000000000001.25) << '\n';
 
    // error handling
    std::feclearexcept(FE_ALL_EXCEPT);
 
    int quo;
    std::cout << "remquo(+Inf, 1) = " << std::remquo(INFINITY, 1, &quo) << '\n';
    if (fetestexcept(FE_INVALID))
        std::cout << "  FE_INVALID raised\n";
}

実行結果の例

naive:
  cos(pi * 0.25) = +0.707107
  cos(pi * 1.25) = -0.707107
  cos(pi * 2.25) = +0.707107
smart:
  cos(pi * 0.25) = +0.707107
  cos(pi * 1.25) = -0.707107
  cos(pi * 2.25) = +0.707107
naive:
  cos(pi * 1000000000000.25) = +0.707123
  cos(pi * 1000000000001.25) = -0.707117
smart:
  cos(pi * 1000000000000.25) = +0.707107
  cos(pi * 1000000000001.25) = -0.707107
remquo(+Inf, 1) = -nan
  FE_INVALID raised

[edit] 関連項目

整数の除算における商と剰余を計算する
(関数) [編集]
(C++11)(C++11)
浮動小数点数の除算操作における剰余
(関数) [編集]
(C++11)(C++11)(C++11)
除算操作における符号付き剰余
(関数) [編集]
C のドキュメントremquo について)
English 日本語 中文(简体) 中文(繁體)