//
// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// Bitfield.hpp --
//
// Author           : Aaron B. Moss
// Created On       : Thu May 9 10:00:00 2019
// Last Modified By : Aaron B. Moss
// Last Modified On : Thu May 9 10:00:00 2019
// Update Count     : 1
//

#pragma once

#include <strings.h>  // for ffs

/// Make a type a bitfield.
/// Include in type definition to add operators. Used to simulate inheritance because union 
/// does not allow it. Requires type to have `unsigned val` field
/// @param BFType  Name of containing type
#define MakeBitfield( BFType )                                         \
	constexpr BFType() : val( 0 ) {}                                   \
	constexpr BFType( unsigned int v ) : val( v ) {}                   \
	bool operator[]( unsigned int i ) const { return val & (1 << i); } \
	bool any() const { return val != 0; }                              \
	void reset() { val = 0; }                                          \
	int ffs() { return ::ffs( val ) - 1; }                             \
	BFType operator&=( BFType other ) {                                \
		val &= other.val; return *this;                                \
	}                                                                  \
	BFType operator&( BFType other ) const {                           \
		BFType q = other;                                              \
		q &= *this;                                                    \
		return q;                                                      \
	}                                                                  \
	BFType operator|=( BFType other ) {                                \
		val |= other.val; return *this;                                \
	}                                                                  \
	BFType operator|( BFType other ) const {                           \
		BFType q = other;                                              \
		q |= *this;                                                    \
		return q;                                                      \
	}                                                                  \
	BFType operator-=( BFType other ) {                                \
		val &= ~other.val; return *this;                               \
	}

/// Adds default printing operator to a bitfield type.
/// Include in definition to add print function, requires other bitfield operators.
/// @param N  Number of bits in bitfield
#define MakeBitfieldPrint( N )                                         \
	static const char* Names[];                                        \
	void print( std::ostream & os ) const {                            \
		if ( (*this).any() ) {                                         \
			for ( unsigned int i = 0; i < N; i += 1 ) {                \
				if ( (*this)[i] ) {                                    \
					os << Names[i] << ' ';                             \
				}                                                      \
			}                                                          \
		}                                                              \
	}

// Local Variables: //
// tab-width: 4 //
// mode: c++ //
// compile-command: "make install" //
// End: //