Poco::FPEnvironment を紹介します。
このクラスは Rounding Mode と浮動小数点フラグからなる浮動小数点環境を Save/Restore するのに使えます。また、浮動小数点数のプロパティを問い合わせる幾つかのスタティックメソッドも提供しています。
FPEnvironmentTest.cpp
・TestClassify() で、isNaN() と isInfinite() を float, double について
チェック。
・TestFlags() で isFlag() を呼んで、FP_DIVIDE_BY_ZERO, FP_OVERFLOW, FP_UNDERFLOW について
チェック。
(Linux 環境では、なぜか underflow のフラグが意図した通りに出ないので、while ループで強引に
underflow に持ち込んでいる。なぜそうなるのか分かる方がおられましたら教えてください。)
・TestRound() で、Poco::FPEnvironment のインスタンス化前後で浮動小数点環境が Save/Restore される
かどうかをチェック。
#include <Poco/Format.h> #include <Poco/FPEnvironment.h> #include <string> #include "ScopedLogMessage.h" #include "PrepareConsoleLogger.h" std::string GetBoolString(bool in) { return std::string(in ? "true":"false"); } template<class T> void Classify(ScopedLogMessage& msg) { T a = 0.0; T b = 0.0; T nan = a/b; T inf = static_cast<T>(1.0)/b; msg.Message(Poco::format(" isNaN(0.0/0.0): %s", GetBoolString(Poco::FPE::isNaN(nan)))); msg.Message(Poco::format(" isNaN(0.0): %s", GetBoolString(Poco::FPE::isNaN(a)))); msg.Message(Poco::format(" isInfinite(1.0/0.0): %s", GetBoolString(Poco::FPE::isInfinite(inf)))); msg.Message(Poco::format(" isInfinite(0.0): %s", GetBoolString(Poco::FPE::isInfinite(a)))); }; void TestClassify(ScopedLogMessage& msg) { msg.Message(" --- float ---"); Classify<float>(msg); msg.Message(" --- double ---"); Classify<double>(msg); } #if defined(__HP_aCC) #pragma OPTIMIZE OFF #elif defined(_MSC_VER) #pragma optimize("", off) #endif double mult(double a, double b) { return a*b; } double div(double a, double b) { return a/b; } void TestFlags(ScopedLogMessage& msg) { Poco::FPE::clearFlags(); msg.Message(" --- div(10, 0) ---"); double a = 10; double b = 0; double c = div(a, b); msg.Message(Poco::format(" isFlag(Poco::FPE::FP_DIVIDE_BY_ZERO): %s", GetBoolString(Poco::FPE::isFlag(Poco::FPE::FP_DIVIDE_BY_ZERO)))); msg.Message(Poco::format(" isInfinite: %s", GetBoolString(Poco::FPE::isInfinite(c)))); Poco::FPE::clearFlags(); a = 1.23456789e210; b = 9.87654321e210; c = mult(a, b); msg.Message(Poco::format(" --- mult(%1.8e, %1.8e) ---", a, b)); msg.Message(Poco::format(" isFlag(Poco::FPE::FP_OVERFLOW): %s", GetBoolString(Poco::FPE::isFlag(Poco::FPE::FP_OVERFLOW)))); msg.Message(Poco::format(" isInfinite: %s", GetBoolString(Poco::FPE::isInfinite(c)))); Poco::FPE::clearFlags(); a = 1.23456789e-99; b = 9.87654321e210; c = div(a, b); while( !Poco::FPE::isFlag(Poco::FPE::FP_UNDERFLOW) ) { Poco::FPE::clearFlags(); a *= 0.1; b *= 10.0; c = div(a, b); } msg.Message(Poco::format(" --- div(%1.8e, %1.8e) ---", a, b)); msg.Message(Poco::format(" isFlag(Poco::FPE::FP_UNDERFLOW): %s", GetBoolString(Poco::FPE::isFlag(Poco::FPE::FP_UNDERFLOW)))); msg.Message(Poco::format(" isInfinite: %s", GetBoolString(Poco::FPE::isInfinite(c)))); } #if defined(__HP_aCC) #pragma OPTIMIZE ON #elif defined(_MSC_VER) #pragma optimize("", on) #endif void TestRound(ScopedLogMessage& msg) { #if !defined(__osf__) && !defined(__VMS) msg.Message(" --- RoundingMode ---"); Poco::FPE::setRoundingMode(Poco::FPE::FP_ROUND_TONEAREST); msg.Message(Poco::format(" getRoundingMode() == Poco::FPE::FP_ROUND_TONEAREST: %s", GetBoolString(Poco::FPE::getRoundingMode() == Poco::FPE::FP_ROUND_TONEAREST))); { Poco::FPE env(Poco::FPE::FP_ROUND_TOWARDZERO); msg.Message(Poco::format(" getRoundingMode() == Poco::FPE::FP_ROUND_TOWARDZERO: %s", GetBoolString(Poco::FPE::getRoundingMode() == Poco::FPE::FP_ROUND_TOWARDZERO))); } msg.Message(Poco::format(" getRoundingMode() == Poco::FPE::FP_ROUND_TONEAREST: %s", GetBoolString(Poco::FPE::getRoundingMode() == Poco::FPE::FP_ROUND_TONEAREST))); #endif } int main(int /*argc*/, char** /*argv*/) { PrepareConsoleLogger logger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION); ScopedLogMessage msg("FPEnvironmentTest ", "start", "end"); TestClassify(msg); TestFlags(msg); TestRound(msg); return 0; } |
Results of execution
[0] FPEnvironmentTest start [0] --- float --- [0] isNaN(0.0/0.0): true [0] isNaN(0.0): false [0] isInfinite(1.0/0.0): true [0] isInfinite(0.0): false [0] --- double --- [0] isNaN(0.0/0.0): true [0] isNaN(0.0): false [0] isInfinite(1.0/0.0): true [0] isInfinite(0.0): false [0] --- div(10, 0) --- [0] isFlag(Poco::FPE::FP_DIVIDE_BY_ZERO): true [0] isInfinite: true [0] --- mult(1.23456789e+210, 9.87654321e+210) --- [0] isFlag(Poco::FPE::FP_OVERFLOW): true [0] isInfinite: true [0] --- div(1.23456789e-99, 9.87654321e+210) --- [0] isFlag(Poco::FPE::FP_UNDERFLOW): true [0] isInfinite: false [0] --- RoundingMode --- [0] getRoundingMode() == Poco::FPE::FP_ROUND_TONEAREST: true [0] getRoundingMode() == Poco::FPE::FP_ROUND_TOWARDZERO: true [0] getRoundingMode() == Poco::FPE::FP_ROUND_TONEAREST: true [0] FPEnvironmentTest end |
Downloads
・ここをクリックすると、makefile や VC++ プロジェクトなど一式がダウンロードできます。
(2013.05.31 updated)
・2010年7月23日からのダウンロード数:928
Subversion
・フリーの Subversion ホスティングサービス Assemblaで、ソースコードを管理しています。
![]() |
Copyright © 2010 Round Square Inc. All rights reserved. |
---|
0 Comments.