/****************************************************************************/
/*	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 <stdlib.h>
#include <misc/multiply.h>
#include <blc_stdlib.h>

/****************************************************************************/
/*							Explanation										*/
/****************************************************************************/

/*
*	The idea is that we have a 64 bit number. We first process the top
*	part, so that we know that the remaining number is less than 1E18.
*	If the remaining number is N and we can calculate N / 1E9 and
*	N % 1E9, then we managed to simplify our task to 2 conversions,
*	each being only 32 bit long. So, we start with a number less than
*	1E18. What we do is that we multiply this 60-bit number with a 26 bit
*	approximation of 1E-9 * 2^55, which is 0x225c17d. In theory, we
*	now have a result of a fractional multiply shifted up by 55 bits.
*	If we shift it right by that 55 bits, that is, we extract the integer
*	part of the fixpoint result, that would be the higher 9 decimal digits
*	of our number. Unfortunately, our approximation of 1E-9 is incorrect,
*	the above number (after the shifting up) has an error of R~0.018964.
*	(That is, 1E-9 * 2^55 - 0x225c17d is R, we rounded down.)
*	So, when we multiplied, instead of multiplying by 1E-9*2^55, we
*	multiplied with (1E-9*2^55 - R). Then we shifted the result down
*	by 55 bits, so at the end we had (1E-9 - R*2^-55). If we now
*	take our original 0 < N < 1E18 number, we can decompose it to a high
*	and a low part, i.e. N = H*1E9 + L, where both H and L are numbers
*	between 0 and 1E9 - 1. When we did the multiplication and the shift
*	we got: H + L*1E-9 - ( H*R*2^-55 + L*R*1E-9*2^-55 ).
*	Of all these only H can be >= 1, everything else is just a fraction.
*	The problem is that if the L*1E-9 tag is larger than or equal to
*	the sum of the last two tags, then the floor of the result is indeed
*	H. However, if the error tags are larger than the second, the floored
*	result will be less than H.
*	Unfortunately, with large H and low L values that can be the case,
*	while smaller H-s and larger L-s result in a positive fractional.
*	In the former case the result of the flooring operation will be
*	H - 1 (the error can never be >= 1), in the latter we get H.
*	However, if we take the result of the flooring as an estimate of H,
*	we can easily determine L and if it is too large, we realise that H has
*	been underestimated and correct the result.
*	We simply multiply H with 1E9 (an exact multiplication) and subtract
*	the result from N. If the remaining number is >= 1E9, we know that
*	we underestimated H, so we bump it up (and correct the remaining number).
*	The result of the subtract (and possible correction) is L.
*	At this moment we have H and L, the decomposed upper and lower 9 digits
*	of N, each in a separate 32 bit int. We can just convert those individually
*	(a reasonably easy thing to do) and concatenate the resulting strings
*	(don't forget to make sure that the second string has leading zeroes!).
*	Thus, at the price of three 32x32=>64 multiplies we could reduce the
*	64-bit conversion into two 32-bit ones. Those, in turn, use one 32x32=>64
*	multiply plus a simple shift-add loop (9 times) each.
*/

/****************************************************************************/
/*					Local constants											*/
/****************************************************************************/

/** @cond */

#define	CONS_1E18				1000000000000000000ull
#define	CONS_1E9				1000000000ul
#define	CONS_1E_9_SHL55			36028797ul

/** @endcond */

/****************************************************************************/
/*					User API functions										*/
/****************************************************************************/

/** @addtogroup stdlib */
/**	@{ */

/**
*	Convert an unsigned long long to a string in radix 10.
*
*	The function converts the unsigned long long to a string, using
*	decimal conversion. The result is stored left-aligned, without
*	leading zeroes and it is closed with a terminating NUL.
*	The largest number results in a 20-digit decimal, therefore the buffer
*	must be 21 bytes long.
*
*	@param	buff	A character buffer that must be at least 21 bytes long
*	@param	numb	The unsigned long long to convert
*
*	@return			The length of the resulting string, not counting the
*					terminating NUL.
*
*	@note	This function is not a standard C library function.
*/

int		ulltostr10( char *buff, unsigned long long numb )
{
unsigned int		len, dig, sav;
unsigned long long	tmp;

	if ( ! ( numb >> 32 ) ) {

		// The number fits in 32 bits, do a 32-bit conversion

		return( ultostr10( buff, (unsigned long) numb ) );
	}

	len = 0;
	tmp = CONS_1E18;

	// Get rid of the higher order bits. We execute the first 5 steps
	// of a division loop. However, most of the time the number will be
	// smaller than 1E18, so it's worth checking it and avoid the whole
	// division thing if we can save it.

	if ( numb >= tmp ) {

		for ( dig = 0, tmp <<= 4, len = 6 ; --len ; tmp >>= 1 ) {

			if ( numb >= tmp ) {

				dig  |= 1 << len;
				numb -= tmp;
			}
		}

		len   = 0;
		dig >>= 1;

		if ( dig >= 10 ) {

			buff[ 0 ] = '1';
			dig -= 10;
			len = 1;
		}

		buff[ len++ ] = dig + '0';
	}

	// Now we know that the number is less than 1E18, we can use
	// the algorithm described above. It is quite short, actually.
	// First, calculate our estimate of H, then get L with that H.
	// Note that in the second line the shift by 23 is not a mistyped
	// shift by 32. It *is* 55 - 32 = 23. Do not fix it :-)

	dig = umul32x32_64( numb, CONS_1E_9_SHL55 ) >> 32;
	dig = ( umul32x32_64( ( numb >> 32 ), CONS_1E_9_SHL55 ) + dig ) >> 23;
	tmp = numb - umul32x32_64( dig, CONS_1E9 );

	// Let's see if we've underestimated H

	if ( tmp >= CONS_1E9 ) {

		// Yes, compensate both H and the remainder (which is L)

		dig++;
		tmp -= CONS_1E9;
	}

	// Convert H to string,

	if ( len-- ) {

		// We've generated 10^18 digit(s). We must have leading 0-s.
		// However, the since we already consumed all the 10^9 digits
		// of the upper word, so we know that we get a 0 where we already
		// have a valid digit. We have to save it and then restore it.

		sav  = buff[ len ];
		_blc_itoa10( buff + len, dig, 1 );
		buff[ len ] = sav;
		len += 9;
	}
	else {

		// We haven't generated anything yet, we do not want leading 0-s.

		len = _blc_itoa10( buff, dig, 0 ) - 1;
	}

	// Save the last digit, because it will be overwritten by
	// a '0' when we convert L with leading zeroes. Convert L,
	// restore the overwritten digit and we're done.

	sav = buff[ len ];
	_blc_itoa10( buff + len, tmp, 1 );
	buff[ len ] = sav;
	return( len + 10 );
}

/** @} */

