/*
	Twilight Prophecy 3D/Multimedia SDK
	A multi-platform development system for virtual reality and multimedia.

	Copyright (C) 1997-2001 by Twilight 3D Finland Oy Ltd.
*/
#ifndef PRCORE_INTEGER_HPP
#define PRCORE_INTEGER_HPP



namespace prcore
{

	// macro to create 16bit code
#define PRCORE_CODE16(n0,n1) ((uint32)(uint8)(n0) | ((uint32)(uint8)(n1) << 8))

	// macro to create 32bit code
#define PRCORE_CODE32(n0,n1,n2,n3) ((uint32)(uint8)(n0) | ((uint32)(uint8)(n1) << 8) | ((uint32)(uint8)(n2) << 16) | ((uint32)(uint8)(n3) << 24 ))

	// index of the most significant bit in the mask
inline int HighestBit(uint32 mask)
{
	int base = 0;

	if ( mask & 0xffff0000 )
	{
		base = 16;
		mask >>= 16;
	}
	if ( mask & 0x0000ff00 )
	{
		base += 8;
		mask >>= 8;
	}
	if ( mask & 0x000000f0 )
	{
		base += 4;
		mask >>= 4;
	}

	const int lut[] = {-1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3};
	return base + lut[ mask ];
}

	// index of the least significant bit in the mask
inline int LowestBit(uint32 mask)
{
	if ( !mask ) 
		return 0;

	int base = 0;

	if ( !(mask & 0xffff) )
	{
		base = 16;
		mask >>= 16;
	}
	if ( !(mask & 0x00ff) )
	{
		base += 8;
		mask >>= 8;
	}
	if ( !(mask & 0x000f) )
	{
		base += 4;
		mask >>= 4;
	}

	const int lut[] = {-1,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
	return base + lut[ mask & 15 ];
}

	// from Steve Baker's "Cute Code" collection
	// http://web2.airmail.net/sjbaker1/software/cute_code.html

	// number of set bits in the mask
inline int BitsInMask(uint32 mask)
{
	mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1);
	mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2);
	mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4);
	mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8);
	mask = (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16);
	return mask;
}

	// reverse bit order
inline void ReverseBits(uint32& mask)
{
	mask = ((mask >>  1) & 0x55555555) | ((mask <<  1) & 0xaaaaaaaa);
	mask = ((mask >>  2) & 0x33333333) | ((mask <<  2) & 0xcccccccc);
	mask = ((mask >>  4) & 0x0f0f0f0f) | ((mask <<  4) & 0xf0f0f0f0);
	mask = ((mask >>  8) & 0x00ff00ff) | ((mask <<  8) & 0xff00ff00);
	mask = ((mask >> 16) & 0x0000ffff) | ((mask << 16) & 0xffff0000) ;
}

	// is value a power-of-two
inline bool IsPowerOfTwo(uint32 mask)
{
	return (mask & (mask-1)) == 0;
}

	// return the next power-of-two of a 32bit number
inline uint32 NextPowerOfTwo(uint32 v)
{
	v -= 1;
	v |= v >> 16;
	v |= v >> 8;
	v |= v >> 4;
	v |= v >> 2;
	v |= v >> 1;
	return v + 1;
}

} // namespace prcore



#endif