#if !defined HAVE_PERM_INVOLUTION_H__
#define      HAVE_PERM_INVOLUTION_H__

#include "aux0/swap.h"
#include "comb/comb-print.h"
#include "fxttypes.h"

class perm_involution
// Involutions (self-inverse permutations)
{
public:
    ulong *p_;  // self-inverse permutation in 0, 1, ..., n-1
    ulong n_;   // number of elements to permute
public:
    perm_involution(ulong n)
    {
        n_ = n;
        p_ = new ulong[n_];
        first();
    }

    ~perm_involution()  { delete [] p_; }

    void first()  { for (ulong i=0; i<n_; i++)  p_[i] = i; }

    const ulong * data()  const  { return p_; }

    bool next()
    {
        for (ulong j=n_-1; j!=0; --j)
        {
            ulong ip = p_[j];   // inverse perm == perm
            p_[j] = j;  p_[ip] = ip; // undo prior swap
            --ip;
            while ( (long)ip>=0 )
            {
                if ( p_[ip]==ip )
                {
                    swap2(p_[j], p_[ip] );
                    return true;
                }
                --ip;
            }
        }
        return false;  // current permutation is last
    }

    void print(const char *bla, bool dfz=false)  const
    // If dfz is true then Dots are printed For Zeros.
    { print_perm(bla, data(), n_, dfz); }
};
// -------------------------


#endif  // !defined HAVE_PERM_INVOLUTION_H__

