/* BaseFromBase.c */

/*
	written by:
	Robert M. Delaney
	Emeritus Professor of Physics
	Saint Louis University
*/

#include "fp.h"

/*
	prepareNice clears out SP, TAB, LF, and CR from inStr
*/

static void prepareNice(char *inStr)
{
	int	i, j, length;
	char	ch;
	
	length = strlen(inStr);
	j = 0;
	for(i=0;i<length;i++)
	{
		ch = inStr[i];
		if(!(ch==32 || ch==9 || ch==10 || ch==13))
			inStr[j++] = ch;
	}
	
	inStr[j] = 0;
	
}/* prepareNice */

// Give isBasePoint the input string. If there is a period a 1 is returned and its position
// is returned in basePointIndex, else a 0 is returned.
// If a -1 is returned there is more than one period or some other error,
// and there is an input error.

static int isBasePoint(int *basePointIndex, char* inStr)
{
	int     len, i, basePointCount;
	char	ch;
	
	len = strlen(inStr);
	if(len<1)
		return -1;
	
	i = 0;
	basePointCount = 0;
	*basePointIndex = 0;
	while(i<len)
	{
		ch = inStr[i];
		if(ch=='.')
		{
			basePointCount++;
			if(basePointCount==1)
				*basePointIndex = i;
		}
		i++;
	}
	
	if(basePointCount==0)
		return 0;
	
	if(basePointCount==1)
		return 1;
	
	return -1;
	
}/* isBasePoint */

// Give digitCount the input string. It will count the number of digits present.
// a digit is one of: 
// 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<36><37>...<65535>
// If there is a problem a 0 is returned, else 1 is returned.

static int digitCount(int *theCount, char* inStr)
{
	int	len, i;
	char	ch;
	
	*theCount = 0;
	
	len = strlen(inStr);
	if(len<1)
		return 0;
	
	i = 0;
	
	while(i<len)
	{
		ch = inStr[i];
		if(ch!='<')
			(*theCount)++;
		else
		{
			while(ch!='>' && i<len)
				ch = inStr[++i];
			if(i==len)
				return 0;
			(*theCount)++;
		}
		i++;
	}
	
	return 1;
	
}/* digitCount */


// give this a string containing one of the "digits"
// it will return an unsigned short with the decimal value of the "digit"
// and a return int = 1 for true, 0 for false
static int evalDigit(unsigned short *digitValue, char* digitStr)
{
	int				len, i, temp;
	char				ch;
	unsigned short		ten=10;
	
	len = strlen(digitStr);
	
	if(len==0)
		return 0;
	
	if(len==1)  // we have a probable digit value < 36
	{
		ch = digitStr[0];
		if(ch>='0' && ch<='9')
			*digitValue = (ch - '0');
		else
		{
			if(ch>='A' && ch<='Z')
				*digitValue = ten + (ch - 'A');
			else
			{
				if(ch>='a' && ch<='z')
					*digitValue = ten + (ch - 'a');
				else
				{
					return 0;
				}
			}
		}
		return 1;
	}
	
	// now len>1, and we know that len must be >2
	if(len<3)
		return 0;
	
	// the calling program will ensure that the "digit" is of form <...>
	// we have to get the insides and make sure it's a legal number from 0 to 65535
	// the calling program will worry about whether baseFrom is exceeded
	// we remove the brackets by shifting down one char, and putting 0 in the right place
	for(i=0;i<len-2;i++)
	{
		digitStr[i] = digitStr[i+1];
	}
	digitStr[len-2] = 0;
	
	if(sscanf(digitStr, "%d", &temp)!=1)
		return 0;
	
	if(temp<0 || temp>65535)
		return 0;
	
	*digitValue = temp;
	
	return 1;
	
}/* evalDigit */


/*
	We assume a base point number for base b in the form:
	a[1]*b^(-1) + a[2]*b ^(-2) + .... + a[n]*b^(-n)
	Note that it is required that 0<=a[i]<b. We are then guaranteed
	that the series sums to less than one.
	We multiply the series by a positive integer, theInteger (another base != b), and truncate
	the result to an integer (necessarily less than the multiplying integer),
	which is developed in a[0].
	
	The basePointArray is predimensioned of dimension numPlaces+1
 */

static void BasePointConvert(unsigned short *basePointArray, int numPlaces,
					  unsigned int *a, int n, int b, int theInteger)
{
	int				i, j;
	unsigned int		d;
	
	for(j=1;j<=numPlaces;j++)
	{
		a[0] = 0;
		
		for(i=1;i<=n;i++)
			a[i] = theInteger*a[i];
		
		// now we start with a[n] and develop its expansion as c + d*b (c<b).
		// we make a[n]=c and add d to a[n-1]. Then do same with a[n-1] and so on.
		for(i=n;i>0;i--)
		{
			d = a[i]/b;
			a[i] = a[i] - d*b;
			a[i-1] = a[i-1] + d;
		}
		
		basePointArray[j] = a[0];
	}
	
}/* BasePointConvert */


static char* translateBasePointRight(char* inStr, int *carryIn, int baseTo, int baseFrom, int numPlaces)
{
	int				i, j, k, length, inDigitCount, carry, iChar;
	char				*outStr, ch;
	char				digitStr[8];
	unsigned short		digitValue, *basePointArray;
	unsigned int		*a; // array formed from inStr
	char				*blookup = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	
	length = strlen(inStr);
	*carryIn = 0;
	
	if(digitCount(&inDigitCount, inStr)==0)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		return outStr;
	}
	
	if(inDigitCount==0)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		return outStr;
	}
	
	// need to form a array
	//outStr = (char*)malloc((9*log(baseFrom)/log(baseTo)+1.5)*inDigitCount*sizeof(char));
	a = (unsigned int*)malloc((inDigitCount+1)*sizeof(unsigned int));
	
	// fill the a array
	i = 0;
	for(k=1;k<=inDigitCount && i<length;k++)
	{
		ch = inStr[i];
		if(ch!='<')
		{
			digitStr[0] = ch;
			digitStr[1] = 0;
		}
		else
		{
			j = 0;
			digitStr[j++] = ch; // we get the '<'
			while(ch!='>' && i<length)
			{
				ch = inStr[++i];
				digitStr[j++] = ch;
			}
			if(i==length)
			{
				outStr = (char*)malloc(sizeof(char));
				outStr[0] = 0;
				free(a);
				return outStr;
			}
			digitStr[j] = 0;
		}
		i++;
		
		if(evalDigit(&digitValue, digitStr)==0)
		{
			outStr = (char*)malloc(sizeof(char));
			outStr[0] = 0;
			free(a);
			return outStr;
		}
		
		if(digitValue>=baseFrom)
		{
			outStr = (char*)malloc(sizeof(char));
			outStr[0] = 0;
			free(a);
			return outStr;
		}
		
		a[k] = digitValue;
	}
	
	basePointArray = (unsigned short*)malloc((numPlaces+2)*sizeof(unsigned short));
	
	BasePointConvert(basePointArray, numPlaces+1, a, inDigitCount, baseFrom, baseTo);
	free(a);
	// should round here and get value of *carryIn
	carry = baseTo/2;
	k = numPlaces + 1;
	while(carry>0 && k>0)
	{
		basePointArray[k] = basePointArray[k] + carry;
		if(basePointArray[k]>=baseTo)
		{
			basePointArray[k] = basePointArray[k] - baseTo;
			carry = 1;
			k--;
		}
		else
			carry = 0;
	}
	
	if(carry>0)
		*carryIn = carry;
	
	// now get rid of trailing zeroes
	
	k = numPlaces;
	while(basePointArray[k]==0 && k>0)
	{
		numPlaces--;
		k--;
	}
	
	outStr = (char*)malloc(7*(numPlaces+1)*sizeof(char));
	
	// now convert basePointArray into outStr, include leading base point
	outStr[0] = '.';
	iChar = 1;
	for(k=1;k<=numPlaces;k++)
	{
		if(basePointArray[k]<36)
			outStr[iChar++] = blookup[basePointArray[k]];
		else
		{
			sprintf(digitStr, "<%d>", (int)basePointArray[k]);
			length = strlen(digitStr);
			for(i=0;i<length;i++)
				outStr[iChar++] = digitStr[i];
		}
	}
	outStr[iChar] = 0;
	
	//if(numPlaces==0)
	//	outStr[0] = 0;  // get rid of base point
	
	free(basePointArray);
	
	return outStr;
	
}/* translateBasePointRight */


static char* translateBasePointLeft(char* inStr, int baseTo, int baseFrom, int carryIn)
{
	int				iChar, jDigit,i, j, k, kTrue, length, len, numDigits, inDigitCount;
	unsigned short		carry, digitValue, *inDigitValue;
	unsigned int		temp, temp1;
	char				digitStr[8];
	char				*outStr, *trueOutStr;
	char				*blookup = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", ch;
	int					restAreZero;
	
	length = strlen(inStr);
	
	if(digitCount(&inDigitCount, inStr)==0)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		return outStr;
	}
	
	if(inDigitCount==0)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		return outStr;
	}

	outStr = (char*)malloc(((9*log(baseFrom)/log(baseTo)+1.5)*inDigitCount+1)*sizeof(char));
	inDigitValue = (unsigned short*)malloc((inDigitCount+2)*sizeof(unsigned short));  // look forward to inCarry=1

	// fill the inDigitValue array
	i = 0;
	for(k=0;k<inDigitCount && i<length;k++)
	{
		ch = inStr[i];
		if(ch!='<')
		{
			digitStr[0] = ch;
			digitStr[1] = 0;
		}
		else
		{
			j = 0;
			digitStr[j++] = ch; // we get the '<'
			while(ch!='>' && i<length)
			{
				ch = inStr[++i];
				digitStr[j++] = ch;
			}
			if(i==length)
			{
				outStr[0] = 0;
				return outStr;
			}
			digitStr[j] = 0;
		}
		i++;
		
		if(evalDigit(&digitValue, digitStr)==0)
		{
			outStr[0] = 0;
			return outStr;
		}
		
		if(digitValue>=baseFrom)
		{
			outStr[0] = 0;
			return outStr;
		}
		
		inDigitValue[k] = digitValue;
	}
	
	if(carryIn>0)
	{
		// we add carryIn to our number
		k = inDigitCount - 1;
		while(carryIn>0 && k>=0)
		{
			inDigitValue[k] = inDigitValue[k] + carryIn;
			if(inDigitValue[k]==baseFrom)
				inDigitValue[k--] = 0;
			else
				carryIn = 0;
		}
		
		if(carryIn>0) // we have to shift numbers in array to right, and make inDigitValue[0]=carryIn and inDigitCount++
		{
			for(k=inDigitCount;k>0;k--)
				inDigitValue[k] = inDigitValue[k-1];
			inDigitValue[0] = carryIn;
			inDigitCount++;
		}
	}

	// now we fill outStr
	numDigits = inDigitCount;
	iChar = 0;
	jDigit = 0;

	while(numDigits>0)
	{
		temp = inDigitValue[jDigit];
		for(k=jDigit;k<inDigitCount;k++)
		{
			// divide temp by baseTo and get carry
			temp1 = temp/baseTo;
			carry = temp - baseTo*temp1;
			inDigitValue[k] = temp1; // new digit value
			if(k==inDigitCount-1)
			{
				if(carry<36)
					outStr[iChar++] = blookup[carry];
				else
				{
					sprintf(digitStr, "<%d>", (int)carry);
					length = strlen(digitStr);
					for(i=0;i<length;i++)
						outStr[iChar++] = digitStr[i];
				}
			}
			else
				temp = baseFrom*carry + inDigitValue[k+1];
		}
		if(inDigitValue[jDigit]==0)
		{
			jDigit++;
			numDigits--;
			// if rest of digits are zero we're done
			restAreZero = 1;
			for(k=jDigit;k<inDigitCount;k++)
				if(inDigitValue[k]!=0)
				{
					restAreZero = 0;
					break;
				}
					if(restAreZero==1)
						numDigits = 0;
		}
	}

	outStr[iChar] = 0;

	// copy the digits in reverse from outStr to trueOutStr
	// k will index outStr, kTrue will index trueOutStr
	// kTrue will initially point either to where a single char will go or to where a > will go
	// we'll read outStr from left to right and fill trueOutStr from right to left
	trueOutStr = (char*)malloc((9*log(baseFrom)/log(baseTo)+1.5)*inDigitCount*sizeof(char));
	length = strlen(outStr);
	trueOutStr[length] = 0;
	k = 0;
	kTrue = length-1;

	while(k<length)
	{
		ch = outStr[k++];
		if(ch!='<')
			trueOutStr[kTrue--] = ch;
		else
		{
			j = 0;
			while(ch!='>')
			{
				digitStr[j++] = ch;
				ch = outStr[k++];
			}
			digitStr[j++] = ch; // this should be '>'
			digitStr[j] = 0;
			len = strlen(digitStr);
			for(j=0;j<len;j++)
				trueOutStr[kTrue-len+j+1] = digitStr[j];
			kTrue-=len;
		}
	}

	free(inDigitValue);
	free(outStr);

	return trueOutStr;

}/* translateBasePointLeft */


static char* convToLowerCase(const char* inString)
{
	int			i, length;
	char*		outString;
	
	length = strlen(inString);
	outString = (char*)malloc((length+1)*sizeof(char));
	
	for(i=0;i<length;i++)
		outString[i] = tolower(inString[i]);
	outString[length] = 0;
	
	return outString;
	
}/* convToLowerCase */


// converts non-floating point numbers in bases which can range from 2 to 36 (originally)
// now want to go to 65536
// so "digits" are 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<36><37>...<65535>
static char* myBaseFromBase(char* inStr, int baseTo, int baseFrom, int numPlaces, bool isUpperCase)
{
	char				*outStr, *outRightStr, *outLeftStr, *inRightStr, *outString;
	int				i, length, leftLen, rightLen, basePointIndex;
	int					isBasePointReturn;
	int				carryIn;
	bool				isNegative;
	int				len;
	
	//prepareNice(inStr);
	
	length = strlen(inStr);
	
	if(length==0 || baseTo==1 || baseFrom==1 || baseTo>65536 || baseFrom>65536)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		return outStr;
	}
	
	if(baseTo==baseFrom)
	{
		if(isUpperCase)
		{
			outStr = (char*)malloc((length+1)*sizeof(char));
			strcpy(outStr, inStr);
		}
		else
			outStr = convToLowerCase(inStr);
		
		return outStr;
	}
	
	carryIn = 0; // =1 when rounding after base point propagates a carryIn=1 to left of base point
	
	// handle - sign
	isNegative = false;
	if(inStr[0]=='-')
	{
		isNegative = true;
		for(i=0;i<length;i++)
			inStr[i] = inStr[i+1];
		length--;
	}
	
	isBasePointReturn = isBasePoint(&basePointIndex, inStr);
	
	// error
	if(isBasePointReturn==-1)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		return outStr;
	}
	
	// something and no base point
	if(isBasePointReturn==0)
	{
		outStr = translateBasePointLeft(inStr, baseTo, baseFrom, carryIn);
		
		if(isNegative)
		{
			len = strlen(outStr);
			for(i=len;i>=0;i--)
			{
				outStr[i+1] = outStr[i];
			}
			outStr[0] = '-';
		}
		 
		
		if(isUpperCase)
			return outStr;
		else
		{
			outString = convToLowerCase(outStr);
			free(outStr);
			return outString;
		}

	}
	
	// something and base point, but nothing more
	if(isBasePointReturn==1)
	{
		if(basePointIndex==(length-1))
		{
			inStr[length-1] = 0; // eliminate base point
			outStr = translateBasePointLeft(inStr, baseTo, baseFrom, carryIn);
			
			if(isNegative)
			{
				len = strlen(outStr);
				for(i=len;i>=0;i--)
				{
					outStr[i+1] = outStr[i];
				}
				outStr[0] = '-';
			}
			
			if(isUpperCase)
				return outStr;
			else
			{
				outString = convToLowerCase(outStr);
				free(outStr);
				return outString;
			}
		}
	}
	
	// base point, then something
	
	if(isBasePointReturn==1)
	{
		if(basePointIndex==0)
		{
			for(i=1;i<length;i++)
				inStr[i-1] = inStr[i];
			inStr[length-1] = 0;  // eliminated base point
			// translateBasePointRight here
			outStr = translateBasePointRight(inStr, &carryIn, baseTo, baseFrom, numPlaces);
			if(carryIn>0)
			{
				outStr[0] = '1';
				outStr[1] = 0;
			}
			if(carryIn==0 && outStr[1]==0) // only have base point
			{
				outStr[0] = '0';
				outStr[1] = 0;
			}
			
			if(isNegative)
			{
				len = strlen(outStr);
				for(i=len;i>=0;i--)
				{
					outStr[i+1] = outStr[i];
				}
				outStr[0] = '-';
			}
			
			if(isUpperCase)
				return outStr;
			else
			{
				outString = convToLowerCase(outStr);
				free(outStr);
				return outString;
			}
		}
	}
	
	// now we have a full base point number
	// we split it and use the base point right first (inRightStr) to get carryIn for base point left (inStr)
	inRightStr = (char*)malloc((length-basePointIndex)*sizeof(char));
	for(i=basePointIndex+1;i<length;i++)
		inRightStr[i-basePointIndex-1] = inStr[i];
	inRightStr[length-basePointIndex-1] = 0;
	
	outRightStr = translateBasePointRight(inRightStr, &carryIn, baseTo, baseFrom, numPlaces);
	free(inRightStr);
	
	if(outRightStr[0]==0)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		return outStr;
	}
	
	if(outRightStr[1]==0)  //only a base point is present
		outRightStr[0] = 0;
	
	inStr[basePointIndex] = 0; // truncate to base point left
	
	outLeftStr = translateBasePointLeft(inStr, baseTo, baseFrom, carryIn);
	
	leftLen = strlen(outLeftStr);
	rightLen = strlen(outRightStr);
	
	outStr = (char*)malloc((leftLen+rightLen+2)*sizeof(char));
	
	strcpy(outStr, outLeftStr);
	strcat(outStr, outRightStr);

	free(outLeftStr);
	free(outRightStr);
	
	if(isNegative)
	{
		len = strlen(outStr);
		for(i=len;i>=0;i--)
		{
			outStr[i+1] = outStr[i];
		}
		outStr[0] = '-';
	}
	
	if(isUpperCase)
		return outStr;
	else
	{
		outString = convToLowerCase(outStr);
		free(outStr);
		return outString;
	}
	
}/* myBaseFromBase */


// handles a fraction input
static char* IsFraction(char* inStrUser, int baseTo, int baseFrom, int numPlaces, bool isUpperCase)
{
	char		*inStr, *outStr, *outStrTen, *numStr, *denStr, *numStrTen, *denStrTen;
	int		i, length, lenDen, slashIndex;
	int		newBlockPrec, saveBlockPrec;
	fp			fpNum, fpDen, fpNumber;
	char		ch;
	bool		isNegative;
	
	// can't have base point
	length = strlen(inStrUser);
	for(i=0;i<length;i++)
	{
		ch = inStrUser[i];
		if(ch=='.' || ch=='^')
		{
			outStr = (char*)malloc(sizeof(char));
			outStr[0] = 0;
			return outStr;
		}
	}
	
	inStr = (char*)malloc((length+1)*sizeof(char));
	strcpy(inStr, inStrUser);
	
	prepareNice(inStr);
	length = strlen(inStr);
	
	// handle - sign
	isNegative = false;
	if(inStr[0]=='-')
	{
		isNegative = true;
		for(i=0;i<length;i++)
			inStr[i] = inStr[i+1];
		length--;
	}
	
	// find slash
	slashIndex = -1;
	for(i=0;i<length;i++)
	{
		if(inStr[i]=='/')
		{
			slashIndex = i;
			break;
		}
	}
	
	if(slashIndex==-1)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		free(inStr);
		return outStr;
	}
	
	numStr = (char*)malloc((slashIndex+1)*sizeof(char));
	for(i=0;i<slashIndex;i++)
		numStr[i] = inStr[i];
	numStr[slashIndex] = 0;
	
	lenDen = length - slashIndex - 1;
	denStr = (char*)malloc((lenDen+1)*sizeof(char));
	for(i=0;i<lenDen;i++)
		denStr[i] = inStr[i+slashIndex+1];
	denStr[lenDen] = 0;
	
	free(inStr);
	
	numStrTen = myBaseFromBase(numStr, 10, baseFrom, 0, isUpperCase);
	denStrTen = myBaseFromBase(denStr, 10, baseFrom, 0, isUpperCase);
	
	saveBlockPrec = getBlockPrec();
	
	newBlockPrec = (4*numPlaces)/blockBits;
	
	if(!newBlockPrec)
		newBlockPrec = 3;
	else
	{
		newBlockPrec+=2;
	}
	
	setBlockPrec(newBlockPrec);
	//setDecPrec(8*newBlockPrec);
	
	equate(fpNum, numStrTen);
	equate(fpDen, denStrTen);
	
	free(numStrTen);
	free(denStrTen);
	
	fpNumber = fpNum / fpDen;
	
	outStrTen = fpToStr(fpNumber, log(baseTo)*numPlaces/log(10)+1);
	
	outStr = myBaseFromBase(outStrTen, baseTo, 10, numPlaces, isUpperCase);
	
	free(outStrTen);
	
	if(isNegative)
	{
		length = strlen(outStr);
		for(i=length;i>=0;i--)
		{
			outStr[i+1] = outStr[i];
		}
		outStr[0] = '-';
	}
	
	setBlockPrec(saveBlockPrec);
	
	return outStr;
	
}/* IsFraction */


// converts numbers in bases which can range from 2 to 65536
// so "digits" are 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<36><37>...<65535> 
// except for base 10, floating point numbers use b^, meaning "times base to the power of"
// for base 10 either e, E or b^ can be used
char* BaseFromBase(char* inStrUser, int baseTo, int baseFrom, int numPlaces, bool isUpperCase)
{
	int		i, length, theIndex;
	char		ch, *expStr, *expStrTen, *inStr, *outStr;
	int		expFrom, basePointIndex, decExp;
	fp			fpBaseTo, fpBaseFrom, manFrom, manTo, expTo, expToFrac, fullExpTo;
	int		newBlockPrec, saveBlockPrec;
	char		*manFromStrTen, *manToStr, *manToStrTen, *expToStr;
	bool		isNegative;
	int		expToINT32;
	
	// is it a fraction?
	length = strlen(inStrUser);
	for(i=0;i<length;i++)
		if(inStrUser[i]=='/')
			return IsFraction(inStrUser, baseTo, baseFrom, numPlaces, isUpperCase);
	
	inStr = (char*)malloc((strlen(inStrUser)+2)*sizeof(char));
	strcpy(inStr, inStrUser);
	
	prepareNice(inStr);
	
	length = strlen(inStr);
	
	if(length==0 || baseTo==1 || baseFrom==1 || baseTo>65536 || baseFrom>65536)
	{
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		free(inStr);
		return outStr;
	}
	
	if(baseTo==baseFrom)
	{
		if(isUpperCase)
		{
			outStr = (char*)malloc((length+1)*sizeof(char));
			strcpy(outStr, inStr);
		}
		else
			outStr = convToLowerCase(inStr);
		
		free(inStr);
		
		return outStr;
	}
	
	if(baseFrom==10)
	{
		// search for e, E, or ^
		for(i=0;i<=length;i++)
		{
			ch = inStr[i];
			if(ch=='e' || ch=='E' || ch=='^')
			{
				theIndex = i;
				break;
			}
			if(ch==0)  // not floating point
			{
				outStr = myBaseFromBase(inStr, baseTo, baseFrom, numPlaces, isUpperCase);
				free(inStr);
				return outStr;
			}
		}
	}
	else
	{
		// search for ^
		for(i=0;i<=length;i++)
		{
			ch = inStr[i];
			if(ch=='^')
			{
				theIndex = i;
				break;
			}
			if(ch==0)  // not floating point
			{
				outStr = myBaseFromBase(inStr, baseTo, baseFrom, numPlaces, isUpperCase);
				free(inStr);
				return outStr;
			}
		}
	}
	
	// we have a floating point number
	
	expStr = (char*)malloc((length-theIndex)*sizeof(char));
	for(i=theIndex+1;i<=length;i++)
		expStr[i-theIndex-1] = inStr[i];  // expStr has exponent
	
	if(baseFrom==10)
	{
		if(ch=='e' || ch=='E')
		{
			inStr[theIndex] = 0;  // inStr now has mantissa
		}
		else
		{
			inStr[theIndex-1] = 0;  // inStr now has mantissa
		}
	}
	else
	{
		inStr[theIndex-1] = 0;  // inStr now has mantissa
	}
	
	// expStr is an integer string, we need to put it in expStrTen
	expStrTen = myBaseFromBase(expStr, 10, baseFrom, 0, true);
	free(expStr);
	
	// convert expStrTen to a int
	if(!sscanf(expStrTen, "%d", &expFrom))
	{
		// return null string
		outStr = (char*)malloc(sizeof(char));
		outStr[0] = 0;
		free(expStrTen);
		free(inStr);
		return outStr;
	}
	
	free(expStrTen);
	
	// we need to see if inStr has a base point; if not on right we move it to the right,
	// decreasing theExp accordingly
	
	length = strlen(inStr);
	basePointIndex = -1;
	for(i=0;i<length;i++)
	{
		if(inStr[i]=='.')
		{
			basePointIndex = i;
			break;
		}
	}
	
	if(basePointIndex==-1)  // don't have base point so put it at end
	{
		inStr[length] = '.';
		basePointIndex = length;
		length++;
		inStr[length] = 0;
	}
	
	if(basePointIndex>=0)
	{
		// we have to be sure there are not all zeroes past the base point
		i = length - 1;
		ch = inStr[i--];
		while(ch=='0' && i>=basePointIndex)
		{
			inStr[i+1] = 0;
			i--;
			if(i>basePointIndex)
				ch = inStr[i];  // keep one zero if there
		}
		
		length = strlen(inStr);
		
		// need to compute decExp worrying about <..> being counted as one
		bool inBracket;
		inBracket = false;
		decExp = 0;
		for(i=basePointIndex+1;i<length;i++)
		{
			ch = inStr[i];
			if(ch=='<')
			{
				inBracket = true;
				decExp++;
			}
				
			if(ch=='>')
				inBracket = false;
			
			if(!inBracket && !(ch=='>'))
				decExp++;
			
		}
		
		// get rid of base point
		for(i=basePointIndex;i<length;i++)
			inStr[i] = inStr[i+1];
		
		// adjust exponent
		expFrom = expFrom - decExp;
		
		saveBlockPrec = getBlockPrec();
		
		newBlockPrec = (4*numPlaces)/blockBits;
		
		if(!newBlockPrec)
			newBlockPrec = 3;
		else
		{
			newBlockPrec+=2;
		}

		setBlockPrec(newBlockPrec);
		
		fpBaseTo = baseTo;
		fpBaseFrom = baseFrom;
		
		// convert to base 10
		
		manFromStrTen = myBaseFromBase(inStr, 10, baseFrom, 0, true);
		free(inStr);
		
		equate(manFrom, manFromStrTen);
		
		isNegative = false;
		if(manFrom<0)
		{
			isNegative = true;
			manFrom = -manFrom;
		}
		
		fullExpTo = (log(manFrom) + expFrom*log(fpBaseFrom)) / log(fpBaseTo);
		
		expTo = floor(fullExpTo);
		expToFrac = fullExpTo - expTo;
		manTo = pow(fpBaseTo, expToFrac);
		
		// if baseTo=10 then manToStr = manToStrTen and may be too long
		if(baseTo==10)
			manToStrTen = fpToStr(manTo, numPlaces);
		else
			manToStrTen = fpToStr(manTo, 8*newBlockPrec);
		
		
		manToStr = myBaseFromBase(manToStrTen, baseTo, 10, numPlaces, true);
		free(manToStrTen);
		
		// expTo should fit into a int
		equate(expToINT32, expTo);
		char* expToStrTen = (char*)malloc(16*sizeof(char));
		sprintf(expToStrTen, "%d", expToINT32);
		expToStr = myBaseFromBase(expToStrTen, baseTo, 10, 0, true);
		free(expToStrTen);
	}
	
	outStr = (char*)malloc((strlen(manToStr) + strlen(expToStr) + 10)*sizeof(char));
	
	if(isNegative)
	{
		outStr[0] = '-';
		outStr[1] = 0;
		outStr = strcat(outStr, manToStr);
	}
	else
	{
		strcpy(outStr, manToStr);
	}
	
	free(manToStr);
	
	if(baseTo==10)
		outStr = strcat(outStr, "e");
	else
	{
		outStr = strcat(outStr, "b^");
	}
	
	outStr = strcat(outStr, expToStr);
	
	free(expToStr);
	
	setBlockPrec(saveBlockPrec);
	
	return outStr;

}/* BaseFromBase */
