Ruud H.G. van Tol on Thu, 20 Jan 2022 10:25:16 +0100


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: forbidden comparison



On 2022-01-20 01:05, Kevin Ryde wrote:
"Ruud H.G. van Tol" <rvtol@isolution.nl> writes:

my( v= 23, c3= 7);
\\ ...
my( c= c3 * 2 ); while( c < v, c3= c; c*= 2 ); \\un-oddify
What are alternative ways to do such?

Logs can give you k shift either right or 1 too big, and compare to see
which.

k = logint(v,2) - logint(c3,2)
c3 <<= k;
if(c3 >= v, c3>>=1)

Thanks Kevin, so obvious once you see it,
must have been there already
and then getting ignored for years.
It looks expensive, so I need to benchmark.


To show more visually:

|__|__|__|__|__|__|16|
|__|__|__|__|__|40|_8|
|__|28|__|__|52|20|_4|
|__|14|22|34|26|10|_2|
| 9|_7|11|17|13|_5|_1|

For example from 7 to 5,
or rather from 11 to 10:

c3 = c2 = 11;  \\ odd > 1
p2 = 0;
p3 = 0;

while
( c3 >= c2
, c3 = 3 * c3 + 1;
  p3 += 1;
  vc3 = valuation( c3, 2 );
  c3 /= vc3;
  p2 += vc3;
);

So now c3 can end up too small,
and need a doubling correction,
with p2 kept in sync.

This trades one while-loop for another.
Either do the halving until done,
or divide by the valuation(),
and go back up if needed.

This is all about deriving
the "optimal" instances of:

  2^p2 * i + c2 -> 3^p3 * i + c3

I'll also try this on an "(odd - 1) / 2" map.

-- Greetings, Ruud