/* (C) 2003 XDA Developers itsme@xs4all.nl * * $Header$ */ /* this program is to test if 'fxpt_div32' and 'fxpt_wjdiv32' both give a reasonable result. arm simulator: see http://www.virtutech.com/simics/licenses.html in the cross-compile version of gdb there should also be an arm simulator. http://celab21.pc.elec.uq.edu.au/~tina/arm-gcc.html http://dcs.gla.ac.uk/~micheal/phd/swarm.html ( swarm ) http://www.dcs.warwick.ac.uk/~csuix/project/ ( tarmac ) http://www.cs.bris.ac.uk/~brown/docs ( armphetamine ) http://www.dynarec.com/ ( dynamic recompilations ) http://simos.stanford.edu/ ( simos ) ftp://ftp.treblig.org/pub/linux/arcem numbers with a large deviation: dividend / divisor = result myresult float bdfe5d10 / ff73b855 = 7874df33 7874df3b -66.0064/ -0.5480= 120.4565 bf7b33a0 / ff73b855 = 75bddf36 75bddf3e -64.5187/ -0.5480= 117.7417 4362d980 / ff73b855 = 85068aa9 85068aa0 67.3861/ -0.5480=-122.9744 all a deviation of max 0.5e-6 */ #include #include "debug.h" typedef signed long int32; typedef int32 fxpt_32; extern "C" fxpt_32 fxpt_div32(fxpt_32 a, fxpt_32 b, int fr_bits); extern "C" fxpt_32 fxpt_wjdiv32(fxpt_32 a, fxpt_32 b, int fr_bits); /* rounding: -2.51 -2.50 -2.49 -1.51 -1.50 -1.49 -0.51 -0.50 -0.49 -0.01 0.00 0.01 0.49 0.50 0.51 1.49 1.50 1.51 2.49 2.50 2.51 ? 2 2 ? 1 1 ? 0 0 0 0 0 ? 1 1 ? 2 2 ? 3 for the numbers marked with '?' it is indeterminate which way it rounds. in binary: 1111110.00 -> 1111110 1111110.01 -> 1111110 1111110.10 -> ? 1111110.11 -> 1111111 0000011.00 -> 0000011 0000011.01 -> 0000011 0000011.10 -> ? 0000011.11 -> 0000100 */ double flp_div(double a, double b) { if (b==0.0) return (a>=0)?1e99 : -1e99; return a/b; } fxpt_32 fxpt_flpdiv32(fxpt_32 a, fxpt_32 b, int fr_bits) { if (b==0) return (a>=0)?0x7fffffff:0x80000000; double val= a; val /= b; val *= (1<= 2147483647.0) return 0x7fffffff; else if (val <= -2147483648.0) return 0x80000000; else return (fxpt_32)val; } double toflp(fxpt_32 val, int fr_bits) { return (double)val*pow(2, -fr_bits); } /* ------- various types of rounding ---------- rnd(-0.5), rnd(+0.5) -1, 0 ceil.rnd1(-1) 0, 1 floor.rnd1(+1) -1, 1 int.rnd1( 0) 0, 0 ceil.rnd2(+1, -1) floor.rnd2(-1, +1) int.rnd1( 0) == int.rnd2(-1, -1) == int.rnd2(-1, 0) == int.rnd2(+1, 0) == int.rnd2(+1, +1) == ceil.rnd2(-1, -1) == floor.rnd2(+1, 0) == floor.rnd2(+1, +1) -------------------------------------------- */ int g_cvtype; int converttoint(double a) { switch(g_cvtype) { case 0: return a; case 1: return ceil(a); case 2: return floor(a); default: debug("cvtype may not be %d\n", g_cvtype); return 0; } } int rnd0(double a) { return converttoint(a); } int rnd1(double a, int type) { switch (type) { case -1: a -= 0.5; break; case 0: if (a<0) a -= 0.5; else a += 0.5; break; case 1: a += 0.5; break; } return converttoint(a); } int rnd2(double a, int type1, int type2) { int sign; if (a<0) { sign= -1; if (type1==1) a= -a; } else if (a>0) { if (type1==-1) a= -a; sign= 1; } else { sign= 0; } if (type1==1) { if (sign<0) return -rnd1(a, type2); else return rnd1(a, type2); } else if (type1==-1) { if (sign<0) return rnd1(a, type2); else return -rnd1(a, type2); } else { debug("type1 may not be %d\n", type1); return 0; } } void tstround() { for (int i=-15 ; i<16 ; i++) { double a= i; a/=4; debug("%d %3d : %8.2f ", g_cvtype, i, a); for (g_cvtype=0 ; g_cvtype<3 ; g_cvtype++) { debug(" %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d", rnd0(a), rnd1(a, -1), rnd1(a, 0), rnd1(a, 1), rnd2(a, -1, -1), rnd2(a, -1, 0), rnd2(a, -1, 1), rnd2(a, 1, -1), rnd2(a, 1, 0), rnd2(a, 1, 1)); } debug("\n"); } } /* ------------------------------------------ */ int g_stats[32*32]; #define CLEARSTATS memset(g_stats, 0, sizeof(g_stats)) #define STATOFFSET(a) (((a)<-16)?0:((a)>=16)?31:((a)+16)) #define ADDSTAT(a,b) g_stats[STATOFFSET(a)*32+STATOFFSET(b)]++ #define GETSTAT(a,b) g_stats[STATOFFSET(a)*32+STATOFFSET(b)] void dumpstats() { for (int iorg=-16 ; iorg<16 ; iorg++) { for (int inew=-16 ; inew<16 ; inew++) { int count= GETSTAT(iorg, inew); if (count) debug(" %5d org%2d new%2d\n", count, iorg, inew); } } } #define MAXDEV 8 bool g_doTestFloat= true; void dotest(fxpt_32 a, fxpt_32 b) { fxpt_32 corg= fxpt_div32(a, b, 24); fxpt_32 cflp= (g_doTestFloat)?fxpt_flpdiv32(a, b, 24):corg; fxpt_32 cnew= fxpt_wjdiv32(a, b, 24); ADDSTAT(corg-cflp, cnew-cflp); if (corg-cflp<-MAXDEV || corg-cflp>=MAXDEV || cnew-cflp<-MAXDEV || cnew-cflp>=MAXDEV) { debug("%08lx / %08lx = %08lx %08lx %08lx", a, b, cflp, corg, cnew); if (g_doTestFloat) { double cdbl= flp_div(toflp(a, 24),toflp(b, 24)); debug(" %9.4f/%9.4f=%9.4f %9.4f %9.4f %9.4f", toflp(a, 24), toflp(b, 24), toflp(cflp, 24), toflp(corg, 24), toflp(cnew, 24), cdbl); } debug("\n"); } } unsigned long tstvalues[]= { 0x80000000, 0x80000001, 0x80000002, 0x90000000, 0xabababab, 0xf0000000, 0xffffff00, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000001, 0x00000002, 0x00000100, 0x10000000, 0x56565656, 0x70000000, 0x7ffffffd, 0x7ffffffe, 0x7fffffff }; #define N_TSTVALS (sizeof(tstvalues)/sizeof(unsigned long)) int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DebugSetLogfile("tstdiv.log"); //tstround(); int i,j; debug(" -------- 1st set of tests\n"); CLEARSTATS; for (i=-1234 ; i<1234 ; i+=13) { for (j=-1234 ; j<1234 ; j+=17) { dotest(i<<16, j<<16); } } debug(" -------- 2nd set of tests\n"); for (i=0 ; i LSTEP1 and LSTEP2 #define LSTARTEND 0x7f000000 #define LSTEP 0x007ef230 for (i=-LSTARTEND ; i