
/*	ulpow -- BASE_TYPE exponentiation (no overflow detection)
 *
 *	Based on lpow() code distributed by Doug Gwyn
 */

#include "hexcalc.h"			/* contains BASE_TYPE typedef */

BASE_TYPE ulpow(base, exponent)		/* returns base^exponent */
BASE_TYPE base;
BASE_TYPE exponent;
{
	BASE_TYPE result;		/* result accumulator */

	/* handle simple special cases separately: */
	if (exponent == 0)
	{
		return 1;		/* includes 0^0 */
	}
	else if (base == 0)
	{
		return 0;		/* exp. < 0 should be EDOM */
	}
	else if (base == 1)
	{
		return 1;
	}
	else if (base == -1)
	{
#if 0	/* intended code: */
		return exponent % 2 == 0 ? 1 : -1;
#else	/* faster equivalent (suggested by Dan Levy of Teletype): */
		return (exponent & 1) == 0 ? 1 : -1;
#endif
	}
	else if (exponent < 0)
	{
		return 0;
	}

	/* general case with exponent > 0: */
	result = 1;
	for ( ; ; )	/* LOOP INVARIANT: result*base^exponent */
	{
#if 0	/* intended code: */
		if (exponent % 2 != 0)
#else	/* faster equivalent (suggested by Dan Levy of Teletype): */
		if ((exponent & 1) != 0)
#endif
		{
			result *= base;
		}
#if 0	/* intended code: */
		if ((exponent /= 2) == 0)
#else	/* faster equivalent (suggested by Dan Levy of Teletype): */
		if ((exponent >>= 1) == 0)
#endif
		{
			break;		/* result now stable */
		}
		base *= base;
	}

	return result;
}
