[XviD-devel] Rounding

skal xvid-devel@xvid.org
31 Oct 2002 10:31:50 +0100


	Hi all,

	since the discussion has settled to what looks like
	an agreement, I think it's time to get messier :)

	I made some tests in order to determine what I could 
	positively be 100% sure(*), and it appears that:



a) operator '/2' (truncation toward 0):

 there at least 3 equivalent ways of compute 'y=x/2':

 Reference:   
y = 0.5f*x; 
if (x<0) y=-y; 
y = (int)floor(y);
if (x<0) y = -y;

 bitwise shift:
  y = (x+(x<0))>>1;

 gcc-like:
    y = x/2;     
 (ISO-C does not define the integer division between operand
of opposite signs, but gcc does is 'correctly' using the bitwise
shift above)(with a CMOV instr., btw)


b) operator '//2' (round away from zero to nearest integer)

There at least 4 equivalent ways of compute 'y=x//2':

Reference:
y = 0.5f*x; 
if (x<0) y=-y; 
y = (int)floor(y+.5f);

bitwise shift:
  y = (x+(x>=0))>>1;
or equivalently:
  y = (x+1-(x<0))>>1;

gcc-like:
  y = (x+1)/2 - (x<0);


c) operator '////2' (truncation toward minus infinity)
(used for half/qpel snapping, for instance)

	This one's rather easy:

Reference:
y = ((x&1)==0) ? x/2 : (x-1)/2;

bitwise shift:
y = (x>>1);  



	Now, bearing that in mind, it seems that:

On Wed, 2002-10-30 at 11:08, skal wrote:
> > 
> 
> 	Arghhh... I think I mess with the tables, indeed. I was using
> 	the OR because it's sometime faster than arithmetic operations
> 	(e.g. on Sparcs if I remember well). It's really a coincidence
> 	the ' (x>>1)+ Rnd_Tab_79[x&3]' works for qpel -> halpel.
>

	using Rnd_Tab_78 in replacement for either '/2 + Rnd_Tab_79[]'
	or '//2 + Rnd_Tab_79[]' will not work for qpel 'divide before
	summation' K=1 case. The problem shows up when (x&7)==7,
	since Tab_78[(x&7)] = 1, whereas Tab_79[(x>>1)&3] = 0.


	hope I messed things up properly :)

	bye,

		Skal


(*) 100% sure meaning, of course, that I'm ready to pay a beer to
the first that can prove me wrong ;)