#if !defined  HAVE_NEGBIN_H__
#define       HAVE_NEGBIN_H__


#include "bits/bitzip.h"  // bit_zip0()

#include "fxttypes.h"
#include "bits/bitsperlong.h"


inline ulong bin2neg(ulong x)
// binary --> radix(-2)
//.
// hakmem, item 128
{
#if  BITS_PER_LONG >= 64
    const ulong m = 0xaaaaaaaaaaaaaaaaUL;
#else
    const ulong m = 0xaaaaaaaaUL;
#endif
    x += m;
    x ^= m;
    return  x;
}
// -------------------------

inline ulong neg2bin(ulong x)
// radix(-2) --> binary
// inverse of bin2neg()
{
#if  BITS_PER_LONG >= 64
    const ulong m = 0xaaaaaaaaaaaaaaaaUL;
#else
    const ulong m = 0xaaaaaaaaUL;
#endif
    x ^= m;
    x -= m;
    return  x;
}
// -------------------------

inline ulong negbin_fixed_point(ulong k)
// Return the k-th fixed point of bin2neg()
// With k=000000ABCDEF (binary) the returned value is 0A0B0C0D0E0F.
{
#if 1
    return bit_zip0(k);
#else
    ulong f = 0;
    for (ulong m=1, s=0;  m!=0;  m<<=1, ++s)  f ^= ( (k&m)<<s );
    return  f;
#endif
}
// -------------------------



inline ulong next_negbin(ulong x)
// With x the radix(-2) representation of n
// return radix(-2) representation of n+1.
{
#if 1 // version 1:
#if  BITS_PER_LONG >= 64
    const ulong m = 0xaaaaaaaaaaaaaaaaUL;
#else
    const ulong m = 0xaaaaaaaaUL;
#endif
    x ^= m;
    ++x;
    x ^= m;
    return x;

#else // version 2:
    ulong s = x << 1;
    ulong y = x ^ s;
    y += 1;
    s ^= y;
    return s;

    // version 3:  use mask 0x5555 and decrement
#endif // VERSION
}
// -------------------------

inline ulong prev_negbin(ulong x)
// With x the radix(-2) representation of n
// return radix(-2) representation of n-1.
{
#if 1 // version 1:
#if  BITS_PER_LONG >= 64
    const ulong m = 0xaaaaaaaaaaaaaaaaUL;
#else
    const ulong m = 0xaaaaaaaaUL;
#endif
    x ^= m;
    --x;
    x ^= m;
    return x;

#else // version 2:
#if  BITS_PER_LONG >= 64
    const ulong m = 0x5555555555555555UL;
#else
    const ulong m = 0x55555555UL;
#endif
    x ^= m;
    ++x;
    x ^= m;
    return x;
#endif // VERSION
}
// -------------------------


#endif  // !defined HAVE_NEGBIN_H__
