OK, I found a solution that is optimal in over 99% of the cases
(99.195% to be precise), while still being fast (because it avoids
looping over the bits):

==============================8<------------------------------
uint32_t maxOr (uint32_t    minA, uint32_t minB,
                uint32_t    maxA, uint32_t maxB)
{
   if (maxA == 0) return maxB;
   if (maxB == 0) return maxA;

   uint32_t a = maxA ^ minA;
   if (a != 0)
      a = ((1 << highbit (a)) - 1);

   uint32_t b = maxB ^ minB;
   if (b != 0)
      b = ((1 << highbit (b)) - 1);

   uint32_t  t = maxA & maxB;
   if (t != 0)
      t = ((1 << highbit (t)) - 1);

   return min (maxA|maxB|a|b, maxA|maxB|t);
}
------------------------------>8==============================

Mostly it's black magic ;) and it's **much** simpler than the first
version that reached those performances. The explanation is in the
rest of the message.

I will only  talk  about the ``a``  side  of the problem here   (i.e
assume ``maxB==minB``). The ``b`` side is symmetrical.

The idea is to build a value that is  between minA and maxA and will
set as many bits as possible when or'ed with maxB:

- The first thing  we do is to  notice that minA  and  maxA have the
  following  structure   (in binary):  ``minA=A0x`` and ``maxA=A1y``
  where  the ``A`` part is  identical.  Any  number between minA and
  maxA will therefore be of the form  ``a=Az``.  A very conservative
  estimate tells  us   that if  we   set  ``z`` to all  ones,   then
  ``maxB|maxA|z``  will be  greater than  ``maxB|a``  for all ``a``.
  This is computed by ``(1 << highbit (maxA ^ minA)) - 1``;

- Another way to look at the  problem is to  say that a ``0`` bit in
  maxA cannot be  set  unless some higher  ``1`` bit  is unset.  For
  example if maxA is ``0b10`` then if we want  to set bit 0, we need
  to unset bit 1 (which will give us ``0b01``).  So by doing this we
  get a lower  value for ``a|maxB`` unless  this bit was already set
  in maxB. The expression ``maxA & maxB`` gives us  the bits that we
  can unset. Therefore only bits that  are less significant than the
  high bit of ``maxA & maxB`` may  be set.  This  is stored into the
  variable ``t``;

- Either  method  works,  but  neither  is  perfect.  By  taking the
  minimum   of the  two  results, we  get  the best   of both worlds
  (although still isn't perfect).

                Jerome
-- 
mailto:jeber...@free.fr
http://jeberger.free.fr
Jabber: jeber...@jabber.fr

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to