
#include "bits/bitlex.h"

#include "bits/print-bin.h"

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

//#include "bits/graycode.h"
//#include "bits/bitcount.h"
//#include "bits/bitlow.h"

#include "nextarg.h"


//% Generating binary words in subset-lexicographic order.

// Cf. bits/fibrep-sl-demo.cc for the same order for Fibonacci words.

//#define TIMING // uncomment to disable printing

int
main(int argc, char **argv)
{
    ulong n = 5;
    NXARG(n, "n-bit binary words");
    const ulong mm = 1UL<<(n-1); // last
    bool bq = 0;
    NXARG(bq, "Whether to print list backwards");
    // Note: with benchmark: whether to go backwards
    const ulong rq = n;


#ifndef TIMING

    if ( !bq )
    {
        ulong x = 1UL<<(n-1);  // first subset
        ulong ct = 0;
        do
        {
            ++ct;
            cout  << setw(4) << ct << ":";
            print_bin("  ", x, n);
            cout << "  = " << setw(2) << x;
//            cout << "   b=" << setw(2) << bit_count(x);
            print_bit_set("  ", x, rq);
            cout << endl;

            x = next_lexrev(x);
        }
        while ( x );
    }
    else
    {
        ulong x = 0;
        ulong ct = 1;

        do
        {
            x = prev_lexrev(x);

            cout  << setw(4) << ct << ":";
            print_bin("  ", x, n);
            cout << "  = " << setw(2) << x;  // A108918
//            cout << "   b=" << setw(2) << bit_count(x);
//            if ( is_lexrev_fixed_point(x) )  cout << " *";  else  cout << "  ";
            print_bit_set("  ", x, rq);
//            cout << "  :"<< lowest_one_idx(x) << ":";  // OEIS A082850 - 1
            ++ct;
            cout << endl;
        }
        while ( x != mm );
    }
#else

    if ( !bq )
    {
        cout << "forward:" << endl;
        ulong x = (1UL<<(n-1));
        do
        {
//            { print_bin("  ", x, n); cout << endl; }
            x = next_lexrev(x);
        }
        while ( x!=0 );
    }
    else
    {
        cout << "backward:" << endl;
        ulong x = 0;
        do
        {
            x = prev_lexrev(x);
//            { print_bin("  ", x, n); cout << endl; }
        }
        while ( x!=mm );
    }
#endif

    return  0;
}
// -------------------------

/*
Timing:

 time ./bin 32 0
arg 1: 32 == n  [n-bit binary words]  default=5
arg 2: 0 == bq  [Whether to also print backwards list]  default=0
forward:
./bin 32 0  15.66s user 0.03s system 100% cpu 15.689 total
 ==> 2^32/15.66 == 274,263,556 per second

 time ./bin 32 1
arg 1: 32 == n  [n-bit binary words]  default=5
arg 2: 1 == bq  [Whether to also print backwards list]  default=0
backward:
./bin 32 1  16.93s user 0.00s system 99% cpu 16.937 total
 ==> 2^32/16.93 == 253,689,739 per second
*/

/*
Timing: (AMD Phenom II X4 945 3000MHz)

 time ./bin 32 0
forward:
./bin 32 0  10.71s user 0.00s system 99% cpu 10.717 total
 ==> 2^32/10.71 == 401,024,023 per second

 time ./bin 32 1
backward:
./bin 32 1  9.56s user 0.00s system 99% cpu 9.566 total
 ==> 2^32/9.56 == 449,264,361 per second
*/

/*
BENCHARGS=32 0
BENCHARGS=32 1

*/


/// Emacs:
/// Local Variables:
/// MyRelDir: "demo/bits"
/// makefile-dir: "../../"
/// make-target: "1demo DSRC=demo/bits/bitlex-demo.cc"
/// make-target2: "1demo DSRC=demo/bits/bitlex-demo.cc DEMOFLAGS=-DTIMING"
/// End:

