git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6000 dfc29bdd-3216-0410-991c-e03cc46cb475
		
			
				
	
	
		
			291 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			291 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright (C) 2008-2012 Colin MacDonald
 | 
						|
// No rights reserved: this software is in the public domain.
 | 
						|
 | 
						|
#include "testUtils.h"
 | 
						|
 | 
						|
using namespace irr;
 | 
						|
using namespace core;
 | 
						|
 | 
						|
//! This was an older Irrlicht implementation, tested against for reference.
 | 
						|
static inline u32 old_strtol10(const char* in, const char** out=0)
 | 
						|
{
 | 
						|
	u32 value = 0;
 | 
						|
 | 
						|
	while ( ( *in >= '0') && ( *in <= '9' ))
 | 
						|
	{
 | 
						|
		value = ( value * 10 ) + ( *in - '0' );
 | 
						|
		++in;
 | 
						|
	}
 | 
						|
	if (out)
 | 
						|
		*out = in;
 | 
						|
	return value;
 | 
						|
}
 | 
						|
 | 
						|
//! This was an older Irrlicht implementation, tested against for reference.
 | 
						|
static inline const char* old_fast_atof_move( const char* c, float& out)
 | 
						|
{
 | 
						|
	bool inv = false;
 | 
						|
	const char *t;
 | 
						|
	float f;
 | 
						|
 | 
						|
	if (*c=='-')
 | 
						|
	{
 | 
						|
		++c;
 | 
						|
		inv = true;
 | 
						|
	}
 | 
						|
 | 
						|
	//f = (float)strtol(c, &t, 10);
 | 
						|
	f = (float) old_strtol10 ( c, &c );
 | 
						|
 | 
						|
	if (*c == '.')
 | 
						|
	{
 | 
						|
		++c;
 | 
						|
 | 
						|
		//float pl = (float)strtol(c, &t, 10);
 | 
						|
		float pl = (float) old_strtol10 ( c, &t );
 | 
						|
		pl *= fast_atof_table[t-c];
 | 
						|
 | 
						|
		f += pl;
 | 
						|
 | 
						|
		c = t;
 | 
						|
 | 
						|
		if (*c == 'e')
 | 
						|
		{
 | 
						|
			++c;
 | 
						|
			//float exp = (float)strtol(c, &t, 10);
 | 
						|
			bool einv = (*c=='-');
 | 
						|
			if (einv)
 | 
						|
				++c;
 | 
						|
 | 
						|
			float exp = (float)old_strtol10(c, &c);
 | 
						|
			if (einv)
 | 
						|
				exp *= -1.0f;
 | 
						|
 | 
						|
			f *= (float)pow(10.0f, exp);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (inv)
 | 
						|
		f *= -1.0f;
 | 
						|
 | 
						|
	out = f;
 | 
						|
	return c;
 | 
						|
}
 | 
						|
 | 
						|
//! This was an older Irrlicht implementation, tested against for reference.
 | 
						|
static inline float old_fast_atof(const char* c)
 | 
						|
{
 | 
						|
	float ret;
 | 
						|
	old_fast_atof_move(c, ret);
 | 
						|
	return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static bool testCalculation_atof(const char * valueString)
 | 
						|
{
 | 
						|
	const f32 newFastValue = fast_atof(valueString);
 | 
						|
	const f32 oldFastValue = old_fast_atof(valueString);
 | 
						|
	const f32 atofValue = (f32)atof(valueString);
 | 
						|
 | 
						|
	logTestString("\n String '%s'\n New fast %.40f\n Old fast %.40f\n     atof %.40f\n",
 | 
						|
		valueString, newFastValue, oldFastValue, atofValue);
 | 
						|
 | 
						|
	const f32 diffNew = fabs(newFastValue - atofValue) ;
 | 
						|
	const f32 diffOld = fabs(oldFastValue - atofValue) ;
 | 
						|
	bool accurate = diffNew <= diffOld || equalsByUlp(diffNew, diffOld, 1);
 | 
						|
 | 
						|
	if(!accurate)
 | 
						|
		logTestString("*** ERROR - less accurate than old method ***\n\n");
 | 
						|
 | 
						|
	return accurate;
 | 
						|
}
 | 
						|
 | 
						|
static bool testCalculation_strtol(const char * valueString)
 | 
						|
{
 | 
						|
	const s32 newFastValue = strtol10(valueString);
 | 
						|
	const s32 oldFastValue = old_strtol10(valueString);
 | 
						|
	const s32 strtolValue = (s32)clamp(strtol(valueString, 0, 10), (long int)INT_MIN, (long int)INT_MAX);
 | 
						|
 | 
						|
	logTestString("\n String '%s'\n New fast %d\n Old fast %d\n   strtol %d\n",
 | 
						|
		valueString, newFastValue, oldFastValue, strtolValue);
 | 
						|
 | 
						|
	bool accurate = (newFastValue == strtolValue) || (oldFastValue != strtolValue);
 | 
						|
 | 
						|
	if (!accurate)
 | 
						|
		logTestString("*** ERROR - wrong calculation in new method ***\n\n");
 | 
						|
 | 
						|
	return accurate;
 | 
						|
}
 | 
						|
 | 
						|
//! Test both the accuracy and speed of Irrlicht's fast_atof() implementation.
 | 
						|
bool test_fast_atof(void)
 | 
						|
{
 | 
						|
	bool accurate = true;
 | 
						|
 | 
						|
	accurate &= testCalculation_atof("340282346638528859811704183484516925440.000000");
 | 
						|
	accurate &= testCalculation_atof("3.402823466e+38F");
 | 
						|
	accurate &= testCalculation_atof("3402823466e+29F");
 | 
						|
	accurate &= testCalculation_atof("-340282346638528859811704183484516925440.000000");
 | 
						|
	accurate &= testCalculation_atof("-3.402823466e+38F");
 | 
						|
	accurate &= testCalculation_atof("-3402823466e+29F");
 | 
						|
	accurate &= testCalculation_atof("34028234663852885981170418348451692544.000000");
 | 
						|
	accurate &= testCalculation_atof("3.402823466e+37F");
 | 
						|
	accurate &= testCalculation_atof("3402823466e+28F");
 | 
						|
	accurate &= testCalculation_atof("-34028234663852885981170418348451692544.000000");
 | 
						|
	accurate &= testCalculation_atof("-3.402823466e+37F");
 | 
						|
	accurate &= testCalculation_atof("-3402823466e+28F");
 | 
						|
	accurate &= testCalculation_atof(".00234567");
 | 
						|
	accurate &= testCalculation_atof("-.00234567");
 | 
						|
	accurate &= testCalculation_atof("0.00234567");
 | 
						|
	accurate &= testCalculation_atof("-0.00234567");
 | 
						|
	accurate &= testCalculation_atof("1.175494351e-38F");
 | 
						|
	accurate &= testCalculation_atof("1175494351e-47F");
 | 
						|
	accurate &= testCalculation_atof("1.175494351e-37F");
 | 
						|
	accurate &= testCalculation_atof("1.175494351e-36F");
 | 
						|
	accurate &= testCalculation_atof("-1.175494351e-36F");
 | 
						|
	accurate &= testCalculation_atof("123456.789");
 | 
						|
	accurate &= testCalculation_atof("-123456.789");
 | 
						|
	accurate &= testCalculation_atof("0000123456.789");
 | 
						|
	accurate &= testCalculation_atof("-0000123456.789");
 | 
						|
	accurate &= testCalculation_atof("-0.0690462109446526");
 | 
						|
	accurate &= testCalculation_atof("0.11999999731779099"); // more numbers past dot than in lookup table
 | 
						|
	accurate &= testCalculation_atof("0.119999997317790999");
 | 
						|
 | 
						|
	if (!accurate)
 | 
						|
	{
 | 
						|
		logTestString("Calculation is not accurate, so the speed is irrelevant\n");
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
#ifndef _DEBUG	// it's only faster in release
 | 
						|
	IrrlichtDevice* device = createDevice(video::EDT_NULL);
 | 
						|
	if (!device)
 | 
						|
		return false;
 | 
						|
	ITimer* timer = device->getTimer();
 | 
						|
 | 
						|
	const int ITERATIONS = 100000;
 | 
						|
	int i;
 | 
						|
 | 
						|
	f32 value;
 | 
						|
	u32 then = timer->getRealTime();
 | 
						|
	for(i = 0; i < ITERATIONS; ++i)
 | 
						|
		value = (f32)atof("-340282346638528859811704183484516925440.000000");
 | 
						|
 | 
						|
	const u32 atofTime = timer->getRealTime() - then;
 | 
						|
 | 
						|
	then += atofTime;
 | 
						|
	for(i = 0; i < ITERATIONS; ++i)
 | 
						|
		value = fast_atof("-340282346638528859811704183484516925440.000000");
 | 
						|
	const u32 fastAtofTime = timer->getRealTime() - then;
 | 
						|
 | 
						|
	then += fastAtofTime;
 | 
						|
	for(i = 0; i < ITERATIONS; ++i)
 | 
						|
		value = old_fast_atof("-340282346638528859811704183484516925440.000000");
 | 
						|
	const u32 oldFastAtofTime = timer->getRealTime() - then;
 | 
						|
 | 
						|
	logTestString("Speed test\n         atof time = %d\n    fast_atof Time = %d\nold fast_atof time = %d\n",
 | 
						|
		atofTime, fastAtofTime, oldFastAtofTime);
 | 
						|
 | 
						|
	device->closeDevice();
 | 
						|
	device->run();
 | 
						|
	device->drop();
 | 
						|
 | 
						|
	if(fastAtofTime > (1.2f*atofTime))
 | 
						|
	{
 | 
						|
		logTestString("The fast method is slower than atof()\n");
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
#endif // #ifndef _DEBUG
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
//! Test both the accuracy and speed of Irrlicht's strtol10() implementation.
 | 
						|
bool test_strtol(void)
 | 
						|
{
 | 
						|
	bool accurate = true;
 | 
						|
 | 
						|
	accurate &= testCalculation_strtol("340282346638528859811704183484516925440");
 | 
						|
	accurate &= testCalculation_strtol("3402823466");
 | 
						|
	accurate &= testCalculation_strtol("3402823466e+29F");
 | 
						|
	accurate &= testCalculation_strtol("-340282346638528859811704183484516925440");
 | 
						|
	accurate &= testCalculation_strtol("-3402823466");
 | 
						|
	accurate &= testCalculation_strtol("-3402823466e+29F");
 | 
						|
	accurate &= testCalculation_strtol("402823466385288598117");
 | 
						|
	accurate &= testCalculation_strtol("402823466");
 | 
						|
	accurate &= testCalculation_strtol("402823466e+28F");
 | 
						|
	accurate &= testCalculation_strtol("402823466385288598117");
 | 
						|
	accurate &= testCalculation_strtol("-402823466");
 | 
						|
	accurate &= testCalculation_strtol("-402823466e+28F");
 | 
						|
	accurate &= testCalculation_strtol(".00234567");
 | 
						|
	accurate &= testCalculation_strtol("-234567");
 | 
						|
	accurate &= testCalculation_strtol("234567");
 | 
						|
	accurate &= testCalculation_strtol("-234567");
 | 
						|
	accurate &= testCalculation_strtol("1175494351");
 | 
						|
	accurate &= testCalculation_strtol("11754943512");
 | 
						|
	accurate &= testCalculation_strtol("11754943513");
 | 
						|
	accurate &= testCalculation_strtol("11754943514");
 | 
						|
	accurate &= testCalculation_strtol("-1175494351");
 | 
						|
	accurate &= testCalculation_strtol("123456789");
 | 
						|
	accurate &= testCalculation_strtol("-123456789");
 | 
						|
	accurate &= testCalculation_strtol("123456.789");
 | 
						|
	accurate &= testCalculation_strtol("-123456.789");
 | 
						|
	accurate &= testCalculation_strtol("-109446526");
 | 
						|
 | 
						|
	if(!accurate)
 | 
						|
	{
 | 
						|
		logTestString("Calculation is not accurate, so the speed is irrelevant\n");
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
#ifndef _DEBUG	// it's only faster in release
 | 
						|
	IrrlichtDevice* device = createDevice(video::EDT_NULL);
 | 
						|
	if (!device)
 | 
						|
		return false;
 | 
						|
	ITimer* timer = device->getTimer();
 | 
						|
 | 
						|
	const int ITERATIONS = 1000000;
 | 
						|
	int i;
 | 
						|
 | 
						|
	s32 value;
 | 
						|
	u32 then = timer->getRealTime();
 | 
						|
	for(i = 0; i < ITERATIONS; ++i)
 | 
						|
		value = strtol("-3402823466", 0, 10);
 | 
						|
 | 
						|
	const u32 strtolTime = timer->getRealTime() - then;
 | 
						|
 | 
						|
	then += strtolTime;
 | 
						|
	for(i = 0; i < ITERATIONS; ++i)
 | 
						|
		value = strtol10("-3402823466");
 | 
						|
	const u32 strtol10Time = timer->getRealTime() - then;
 | 
						|
 | 
						|
	then += strtol10Time;
 | 
						|
	for(i = 0; i < ITERATIONS; ++i)
 | 
						|
		value = old_strtol10("-3402823466");
 | 
						|
	const u32 oldstrtol10Time = timer->getRealTime() - then;
 | 
						|
 | 
						|
	logTestString("Speed test\n      strtol time = %d\n    strtol10 time = %d\nold strtol10 time = %d\n",
 | 
						|
		strtolTime, strtol10Time, oldstrtol10Time);
 | 
						|
 | 
						|
	device->closeDevice();
 | 
						|
	device->run();
 | 
						|
	device->drop();
 | 
						|
 | 
						|
	if (strtol10Time > (1.2f*strtolTime))
 | 
						|
	{
 | 
						|
		logTestString("The fast method is slower than strtol()\n");
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
#endif // #ifndef _DEBUG
 | 
						|
 | 
						|
	return true;
 | 
						|
}
 | 
						|
 | 
						|
bool fast_atof(void)
 | 
						|
{
 | 
						|
	bool ok = true;
 | 
						|
	ok &= test_fast_atof() ;
 | 
						|
	ok &= test_strtol();
 | 
						|
	return ok;
 | 
						|
}
 |