/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#include <misc/multiply.h>
#include <misc/bits.h>

/****************************************************************************/
/*					Public API functions									*/
/****************************************************************************/

/** @addtogroup misc_mult */
/** @{ */

/**
*	Prepares for an unsigned 32-bit division by a constant.
*
*	Division is a costy operation on the ARM7TDMI core because it does not
*	have a hardware divider. However, division by a constant can be done
*	fast by using 64-bit multiplication. There is a cost of calculating the
*	parameters, but then the division itself will be very fast.
*
*	If you compile for the ARM and you divide by a constant, gcc actually
*	calculates those values and generates the relevant fast code sequence.
*	On the other hand, if you compile for THUMB it will call the division
*	routine even for constants, because the necessary instructions are not
*	available in THUMB mode.
*	<br><br>
*	This routine calculates the necessary values and allows you to use the
*	fast division in THUMB mode. In addition, regardless of whether you
*	compile for ARM or THUMB, if you have to divide with the same number
*	several times, then it might be worth to use this function, because the
*	initial cost of calculating the parameters will be amortised over several
*	calls to the actual fast division routine.
*	<br><br>
*	To use the fast division, first you have to call this function, passing
*	it the divisor. It will then return a 64-bit value that contains the
*	parameters needed for the actual division. You then pass this object and
*	the value you want to divide to the udiv32() function, which will perform
*	the division very fast. For example, let's assume that you have to divide
*	the elements of an array by the same number. You could do it this way:
*	@code
*	void ArrayDivide( unsigned *array, unsigned size, unsigned divisor )
*	{
*	long long	params;
*
*		params = udiv32prep( divisor );
*
*		for ( ; size-- ; array++ )
*
*			*array = udiv32( params, *array );
*	}
*	@endcode
*	The cost of calculating the parameters is approximately equal to four
*	32-bit divisions. The cost of doing a fast division using the precalculated
*	value is roughly the same as a 64-bit multiply. If you have to divide at
*	least five times with the same number, then it is worth to use the fast
*	division.
*
*	@param	div		The value that you want to divide with.
*					It must <b>not</b> be 0. If it is, then the returned value
*					will be such that udiv32() will return 0 regardless of its
*					actual argument.
*
*	@return			A 64-bit object that can be passed to udiv32() so that it
*					will divide its argument by <tt>div</tt>.
*/

long long	udiv32prep( unsigned div )
{
unsigned	l, r;

	if ( ! div ) return( 0 );
	l = 32 - ldzcnt( div - 1 );
	r = ( (unsigned long long) ( ( 1 << l ) - div ) << 32 ) / div + 1;
	return( ( (long long) r << 32 ) | ( l ? 2 * l - 1 : 0 ) );
}

/**
*	Unsigned 32-bit division by a constant.
*
*	This function divides its second argument by a constant and returns the
*	quotient. The divisor constant is determined by the first argument and
*	must have been obtained by a call to the udiv32prep() function.
*
*	@param	divisor		The 64-bit data structure calculated by the
*						udiv32prep() function, representing a 32-bit divisor.
*
*	@param	dividend	The 32-bit number to divide.
*
*	@return				The 32-bit quotient.
*/

unsigned	udiv32( long long divisor, unsigned dividend );

/** @} */


