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