suggested improvements to D (popcount and first1)

Warren D Smith wds at math.temple.edu
Tue Jan 9 10:57:21 PST 2007


reply to Don Clugston

Yes, the "repeated doubling of wisdom"
bitcount routine you wrote is a good way to do it.
Also, more brute-force, but on many machines faster, is to use
precomputed popcount lookup tables.

Lookup tables can also be used to implement first1, and so
can a "repeated wisdom doubling" approach to implement a binary search.
Another way to do first1(uint x) is first to compute  y=x^(x-1)   which if x!=0
is a uint with a single 1 bit located at the same place as the
least-significant 1 bit in x, and second to hash y, for example
use y%C as the hash function [value in {0..C-1}] and you cleverly choose the
constant C so that this hash function always gives different values
for different y of this form (i.e. perfect hash)
and do a hash-table lookup in a C-entry table.
If I recall right, which I may not, C=63 works.
Unfortunately the "%" is slow on the hardware I used.

All that is suckingly slow compared to hardware support, though.

--

>Are there many applications of [add with carry, etc]
>OTHER than bignum arithmetic? My
>feeling is that you'd always want to do bignum in asm anyway.

>Note that D is a great language for writing asm in; you can have a
>single source code shared between Windows, *nix, and the new x86 >Macs.

But I want to write PORTABLE, i.e. not-asm, bignum code.
Why is the language denying me the power of the machine?
That is the opposite of its job.  Especially if we are talking
about a power that every machine provides.

It is kind of like saying:  "you can only breathe air from now on, if
you use a gas mask.  This is a great advance in technology versus just
breathing, so be happy."

The other main application of add-with-carry is to spot integer overflow.

Look, if you just provide, e.g.
    AddWithCarry( in uint x, in uint y, out uint z, out bool carry )
    DoubleMultiply( in uint32 x, in uint32 y, out uint64 z )
        [or maybe two out-arguments, an uper and lower one]
    FullDivide( in uint64 y, in uint32 z, out uint32 quotient,
          out uint32 remainder )
and similar stuff, problem is over.   (Ignore my crappy syntax,
just use this idea but with better syntax.)




More information about the Digitalmars-d mailing list