root/trunk/0048_FPEnvironment/FPEnvironmentTest.cpp

User picture

Author: Setsu

Revision: 348 («Previous)


File Size: 6.23 KB

(July 19, 2010 19:54 UTC) Almost 2 years ago

Changed for underflow fix for linux.

 
Show/hide line numbers
//
//  FPEnvironmentTest.cpp
//
//  Created by Setsu on 7/19/2010.
//  Copyright 2010 RoundSquare Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//

//----------------------------------------
//	include
//----------------------------------------
#include <Poco/Logger.h>
#include <Poco/PatternFormatter.h>
#include <Poco/FormattingChannel.h>
#include <Poco/ConsoleChannel.h>
#include <Poco/Format.h>
#include <Poco/FPEnvironment.h>

#include <string>

#include "ScopedLogMessage.h"

//----------------------------------------
//	GetBoolString
//----------------------------------------
std::string GetBoolString(bool in)
{
	return std::string(in ? "true":"false");
}

//----------------------------------------
//	Classify
//----------------------------------------
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))));
};

//----------------------------------------
//	TestClassify
//----------------------------------------
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

//----------------------------------------
//	mult
//----------------------------------------
double mult(double a, double b)
{
	return a*b;
}

//----------------------------------------
//	div
//----------------------------------------
double div(double a, double b)
{
	return a/b;
}

//----------------------------------------
//	TestFlags
//----------------------------------------
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

//----------------------------------------
//	TestRound
//----------------------------------------
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
}

//----------------------------------------
//	PrepareConsoleLogger
//----------------------------------------
void PrepareConsoleLogger(const std::string& name, int level=Poco::Message::PRIO_INFORMATION)
{
	Poco::FormattingChannel* pFCConsole = new Poco::FormattingChannel(new Poco::PatternFormatter("%t"));
	pFCConsole->setChannel(new Poco::ConsoleChannel);
	pFCConsole->open();

	Poco::Logger::create(name, pFCConsole, level);
}

//----------------------------------------
//	main
//----------------------------------------
int main(int /*argc*/, char** /*argv*/)
{
	PrepareConsoleLogger(Poco::Logger::ROOT, Poco::Message::PRIO_INFORMATION);

	ScopedLogMessage msg("FPEnvironmentTest ", "start", "end");

	TestClassify(msg);
	TestFlags(msg);
	TestRound(msg);

	return 0;
}