Blame ETL/test/fixed.cpp

darco b3016b
/*! ========================================================================
darco b3016b
** Extended Template and Library Test Suite
darco b3016b
** Fixed-Point Math Test
dooglus 36d01e
** $Id$
darco b3016b
**
darco b3016b
** Copyright (c) 2002 Robert B. Quattlebaum Jr.
dooglus 334e15
** Copyright (c) 2007 Chris Moore
darco b3016b
**
darco b3016b
** This package is free software; you can redistribute it and/or
darco b3016b
** modify it under the terms of the GNU General Public License as
darco b3016b
** published by the Free Software Foundation; either version 2 of
darco b3016b
** the License, or (at your option) any later version.
darco b3016b
**
darco b3016b
** This package is distributed in the hope that it will be useful,
darco b3016b
** but WITHOUT ANY WARRANTY; without even the implied warranty of
darco b3016b
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
darco b3016b
** General Public License for more details.
darco b3016b
**
darco b3016b
** === N O T E S ===========================================================
darco b3016b
**
darco b3016b
** ========================================================================= */
darco b3016b
darco b3016b
/* === H E A D E R S ======================================================= */
darco b3016b
darco b3016b
#define ETL_FIXED_BITS		12
darco b3016b
darco b3016b
#include <etl fixed=""></etl>
darco b3016b
#include <stdio.h></stdio.h>
darco b3016b
#include <etl clock=""></etl>
darco b3016b
darco b3016b
/* === M A C R O S ========================================================= */
darco b3016b
darco b3016b
#ifndef PI
darco b3016b
# define PI (3.1415926535897932384626433832795029L)
darco b3016b
#endif
darco b3016b
darco b3016b
#define ADD_SUB_TEST	20000000
darco b3016b
#define MUL_TEST 		10000000
dooglus 4922c2
#define DIV_TEST		1048573	// at 1048573, fixed point numbers wrap around to zero
darco b3016b
using namespace etl;
darco b3016b
darco b3016b
/* === C L A S S E S ======================================================= */
darco b3016b
darco b3016b
template <class value_type=""></class>
darco b3016b
struct speed_test
darco b3016b
{
darco b3016b
	double add_sub_test(void)
darco b3016b
	{
darco b3016b
		value_type a=1;
darco b3016b
		value_type b=2;
darco b3016b
		value_type c=3;
darco b3016b
		int i;
darco b3016b
		etl::clock MyTimer;
darco b3016b
		MyTimer.reset();
darco b3016b
		for(i=0;i
darco b3016b
		{
dooglus 4922c2
			a+=a; a-=b; a-=c; a+=a;
dooglus 4922c2
			a+=a; a-=b; a-=c; a+=a;
dooglus 4922c2
			a+=a; a-=b; a-=c; a+=a;
dooglus 4922c2
			a+=a; a-=b; a-=c; a+=a;
dooglus 4922c2
			a+=a; a-=b; a-=c; a+=a;
dooglus 4922c2
			a+=a; a-=b; a-=c; a+=a;
dooglus 4922c2
			a+=a; a-=b; a-=c; a+=a;
darco b3016b
		}
dooglus cee594
dooglus 4922c2
		fprintf(stderr, "[%1d]...", int(int(a)/1e9)+5); // so the compiler doesn't optimize everything out
darco b3016b
		return MyTimer();
darco b3016b
	}
darco b3016b
darco b3016b
	double mul_test(void)
darco b3016b
	{
darco b3016b
		value_type a,b,c,d;
dooglus 4922c2
		a=value_type(2.25);
darco b3016b
		b=value_type(2);
darco b3016b
		c=value_type(4.5);
dooglus 4922c2
		d=value_type(1);
dooglus 4922c2
		const value_type one_and_a_half(static_cast<value_type>(1.5));</value_type>
darco b3016b
		int i;
darco b3016b
		etl::clock MyTimer;
darco b3016b
		MyTimer.reset();
dooglus 4922c2
		for(i=1;i
dooglus cee594
		{
dooglus 4922c2
			d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
dooglus 4922c2
			d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
dooglus 4922c2
			d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
dooglus 4922c2
			d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
dooglus 4922c2
			d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
dooglus 4922c2
			d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
dooglus 4922c2
			d*=a;d*=b;d*=c;d*=3;d*=i; b*=c;b*=d;b*=d;b*=3; c*=d;c*=one_and_a_half;c*=a;c*=b;c*=3; a*=c;a*=b;a*=3;
darco b3016b
		}
dooglus 4922c2
dooglus 4922c2
		fprintf(stderr, "[%1d]...", int(int(a)/1e9)+5); // so the compiler doesn't optimize everything out
darco b3016b
		return MyTimer();
darco b3016b
	}
dooglus cee594
darco b3016b
	double div_test(void)
darco b3016b
	{
darco b3016b
		value_type a(30);
darco b3016b
		value_type b(40);
dooglus 4922c2
		value_type acc(0);
dooglus 4922c2
		int i, j;
darco b3016b
		etl::clock MyTimer;
darco b3016b
		MyTimer.reset();
dooglus 4922c2
		for(j=0;j<10;j++)
dooglus 4922c2
			for(i=1;i
dooglus 4922c2
			{
dooglus 4922c2
				a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
dooglus 4922c2
				a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
dooglus 4922c2
				a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
dooglus 4922c2
				a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
dooglus 4922c2
				a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
dooglus 4922c2
				a=3+i; b=40+i; b/=a; a/=(i%20)+1; acc+= a;
dooglus 4922c2
			}
dooglus 4922c2
dooglus 5327ab
		fprintf(stderr, "[%1d]...", int(int(acc)/1e9)+5); // so the compiler doesn't optimize everything out
darco b3016b
		return MyTimer();
darco b3016b
	}
darco b3016b
};
darco b3016b
darco b3016b
/* === P R O C E D U R E S ================================================= */
darco b3016b
darco b3016b
int basic_test(void)
darco b3016b
{
darco b3016b
	int ret=0;
dooglus cee594
darco b3016b
	fixed a,b,c;
darco b3016b
	double d;
dooglus cee594
darco b3016b
	a=-1;
darco b3016b
	a=std::abs(a);
darco b3016b
	if(a!=fixed(1))
darco b3016b
	{
= cd1e3b
		fprintf(stderr, "fixed: abs() failure on line %d in " __FILE__ ".\n", __LINE__);
darco b3016b
		ret++;
darco b3016b
	}
dooglus cee594
darco b3016b
	d=(double)(fixed(2.5)*fixed(3.0f)/7)-(2.5f*3.0f/7.0f);
darco b3016b
	fprintf(stderr,"fixed: 2.5 * 2 / 7 --- Difference: %f\n",d);
dooglus cee594
	if(d<0.0)d=-d;
darco b3016b
	if( d>0.0005)
darco b3016b
	{
= cd1e3b
		fprintf(stderr, "fixed: Failed test on line %d in " __FILE__ ".\n", __LINE__);
darco b3016b
		ret++;
darco b3016b
	}
darco b3016b
darco b3016b
	a=1043;d=1043;
darco b3016b
	a/=27;d/=27;
darco b3016b
	a+=10.42;d+=10.42;
darco b3016b
	a/=6;d/=6;
darco b3016b
	a*=PI;d*=PI;
darco b3016b
	d-=(double)a;
darco b3016b
	fprintf(stderr,"fixed: ( 1043 / 27 + 10.42 ) / 6 * PI --- Difference: %f\n",d);
darco b3016b
	if(d<0.0)d=-d;
dooglus 4922c2
#ifdef ROUND_TO_NEAREST_INTEGER
darco b3016b
	if( d>0.0005)
dooglus 4922c2
#else
dooglus 4922c2
	if( d>0.0025)
dooglus 4922c2
#endif
darco b3016b
	{
= cd1e3b
		fprintf(stderr,"fixed: Failed test on line %d in " __FILE__ ".\n", __LINE__);
darco b3016b
		ret++;
darco b3016b
	}
dooglus cee594
darco b3016b
	return ret;
darco b3016b
}
darco b3016b
darco b3016b
int char_test(void)
darco b3016b
{
darco b3016b
	int ret=0;
dooglus cee594
darco b3016b
	fixed_base<unsigned char,8=""> fix;</unsigned>
darco b3016b
	double flt;
dooglus cee594
darco b3016b
	if(sizeof(fix)!=sizeof(unsigned char))
darco b3016b
	{
darco b3016b
		ret++;
darco b3016b
		fprintf(stderr,"fixed: Size of fixed_base<unsigned char,8=""> is wrong!\n");</unsigned>
darco b3016b
	}
dooglus cee594
darco b3016b
	flt=1.0;
darco b3016b
	fix=1.0;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
darco b3016b
darco b3016b
	flt*=0.7;
darco b3016b
	fix*=0.7;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
darco b3016b
darco b3016b
	flt*=0.7;
darco b3016b
	fix*=0.7;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
dooglus cee594
darco b3016b
	flt*=0.7;
darco b3016b
	fix*=0.7;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
dooglus cee594
darco b3016b
	flt*=0.7;
darco b3016b
	fix*=0.7;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
dooglus cee594
darco b3016b
	flt*=0.7;
darco b3016b
	fix*=0.7;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
darco b3016b
darco b3016b
	//flt/=0.7;
darco b3016b
	//fix/=0.7;
darco b3016b
	//fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
darco b3016b
darco b3016b
	flt+=0.3;
darco b3016b
	fix+=0.3;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
darco b3016b
darco b3016b
	flt*=2;
darco b3016b
	fix*=2;
darco b3016b
	fprintf(stderr,"fixed: value=%f, data=%d, shouldbe=%f, error=%f\n",(float)fix,fix.data(),flt,(float)fix-flt);
darco b3016b
dooglus cee594
darco b3016b
	return ret;
darco b3016b
}
darco b3016b
darco b3016b
/* === E N T R Y P O I N T ================================================= */
darco b3016b
darco b3016b
int main()
darco b3016b
{
darco b3016b
	int error=0;
dooglus cee594
darco b3016b
	error+=basic_test();
darco b3016b
	error+=char_test();
dooglus cee594
darco b3016b
	speed_test<float> float_test;</float>
darco b3016b
	speed_test<int> int_test;</int>
darco b3016b
	speed_test<fixed> fixed_test;</fixed>
dooglus cee594
darco b3016b
	{
darco b3016b
		double flt,fix,inte;
dooglus 4922c2
		fprintf(stderr,"\nAddition/subtraction test...\n");
darco b3016b
dooglus 4922c2
		fprintf(stderr,"  calculating float.....");
darco b3016b
		flt=float_test.add_sub_test();
dooglus 4922c2
		fprintf(stderr,"   float time: %f sec\n",flt);
darco b3016b
dooglus 4922c2
		fprintf(stderr,"  calculating fixed.....");
darco b3016b
		fix=fixed_test.add_sub_test();
dooglus 4922c2
		fprintf(stderr,"   fixed time: %f sec\n",fix);
darco b3016b
dooglus 4922c2
		fprintf(stderr,"  calculating integer...");
darco b3016b
		inte=int_test.add_sub_test();
dooglus 4922c2
		fprintf(stderr," integer time: %f sec\n",inte);
darco b3016b
darco b3016b
		if(flt>fix)
darco b3016b
			fprintf(stderr,"Fixed point wins by %f seconds! (%f%% faster)\n",flt-fix,flt/fix*100.0f-100.0f);
darco b3016b
		else
darco b3016b
			fprintf(stderr,"Floating point wins by %f seconds! (%f%% faster)\n",fix-flt,fix/flt*100.0f-100.0f);
dooglus cee594
darco b3016b
	}
dooglus cee594
darco b3016b
	{
darco b3016b
		double flt,fix,inte;
dooglus 4922c2
		fprintf(stderr,"\nProduct test...\n");
dooglus 4922c2
		fprintf(stderr,"  calculating float.....");
darco b3016b
		flt=float_test.mul_test();
dooglus 4922c2
		fprintf(stderr,"   float time: %f sec\n",flt);
dooglus 4922c2
		fprintf(stderr,"  calculating fixed.....");
darco b3016b
		fix=fixed_test.mul_test();
dooglus 4922c2
		fprintf(stderr,"   fixed time: %f sec\n",fix);
dooglus 4922c2
		fprintf(stderr,"  calculating integer...");
darco b3016b
		inte=int_test.mul_test();
dooglus 4922c2
		fprintf(stderr," integer time: %f sec\n",inte);
darco b3016b
		if(flt>fix)
darco b3016b
			fprintf(stderr,"Fixed point wins by %f seconds! (%f%% faster)\n",flt-fix,flt/fix*100.0f-100.0f);
darco b3016b
		else
darco b3016b
			fprintf(stderr,"Floating point wins by %f seconds! (%f%% faster)\n",fix-flt,fix/flt*100.0f-100.0f);
darco b3016b
	}
darco b3016b
darco b3016b
	{
darco b3016b
		double flt,fix,inte;
dooglus 4922c2
		fprintf(stderr,"\nDivision test...\n");
dooglus 4922c2
		fprintf(stderr,"  calculating float.....");
darco b3016b
		flt=float_test.div_test();
dooglus 4922c2
		fprintf(stderr,"   float time: %f sec\n",flt);
dooglus 4922c2
		fprintf(stderr,"  calculating fixed.....");
darco b3016b
		fix=fixed_test.div_test();
dooglus 4922c2
		fprintf(stderr,"   fixed time: %f sec\n",fix);
dooglus 4922c2
		fprintf(stderr,"  calculating integer...");
darco b3016b
		inte=int_test.div_test();
dooglus 4922c2
		fprintf(stderr," integer time: %f sec\n",inte);
darco b3016b
		if(flt>fix)
darco b3016b
			fprintf(stderr,"Fixed point wins by %f seconds! (%f%% faster)\n",flt-fix,flt/fix*100.0f-100.0f);
darco b3016b
		else
darco b3016b
			fprintf(stderr,"Floating point wins by %f seconds! (%f%% faster)\n",fix-flt,fix/flt*100.0f-100.0f);
dooglus 4922c2
		fprintf(stderr,"\n");
darco b3016b
	}
dooglus cee594
darco b3016b
	return error;
darco b3016b
}