/*
 *  mb2Str.cpp
 *  fp
 *
 *  Created by Robert Delaney on 4/24/09.
 *  Copyright 2009 __Bob Delaney's Science Software__. All rights reserved.
 *
 */

/*
 This is the NTL method for converting an mb into a string
*/

#include "fp.h"

static int iodigits=9, ioradix=1000000000, sIndex;

static void PrintDigits(char* s, int d, int justify);

struct lstack {
   int top;
   int alloc;
   int *elts;

   lstack() { top = -1; alloc = 0; elts = 0; }
   ~lstack() { }

   int pop() { return elts[top--]; }
   int empty() { return (top == -1); }
   void push(int x);
};

void lstack::push(int x)
{
   if (alloc == 0) {
      alloc = 100;
      elts = (int *) malloc(alloc * sizeof(int));
	   if(!elts)
		   exit(1);
   }

   top++;

   if (top + 1 > alloc) {
      alloc = 2*alloc;
      elts = (int *) realloc(elts, alloc * sizeof(int));
   }

   elts[top] = x;
}


char* mb2Str(const mb& x)
{
	static mb		xt; // b
	static lstack	S;
	static bool		initGood=false;
	char			*decStr;  // s
	int			r, mySize;
	bool			isNegative;
	
	if(!initGood)
	{
		init(xt);
		initGood = true;
	}
    //init(xt);

	//b = a;
	equate(xt, x);
	if(xt.n<0)
	{
		xt.n = -xt.n;
		isNegative = true;
	}
	else
		isNegative = false;
	
	// estimate length of decStr; note that hexStr had currentSize = 8*abs(xt.n) w/o minus sign
	// so at 2 dec digits per hexit (F=15) we need a size of 16*abs(xt.n) + 2 (for minus sign + 0)
	mySize = 16*abs(xt.n) + 10;
	decStr = (char*)malloc(mySize*sizeof(char));
	if(!decStr)
		exit(1);
	
	if (xt.n==0)
	{
		decStr[0] = '0';
		decStr[1] = 0;
		return decStr;
	}

	sIndex = 0;

	if(isNegative)
	{
		decStr[0] = '-';
		sIndex = 1;
	}

	do
	{
		r = mbShortDiv(xt, xt, ioradix);
		S.push(r);
	}
	while(xt.n>0);

	r = S.pop();
	PrintDigits(decStr, r, 0);

	while (!S.empty())
	{
		r = S.pop();
		PrintDigits(decStr, r, 1);
	}

	decStr[sIndex] = 0;
	
	return decStr;
	
}


void PrintDigits(char* s, int d, int justify)
{
   static char *buf = 0;

   if (!buf)
   {
      buf = (char *) malloc(iodigits);
	   if(!buf)
		   exit(1);
   }

   int i = 0;

   while (d)
   {
      buf[i] = (d % 10) + '0';
      d = d / 10;
      i++;
   }

   if (justify)
   {
      int j = iodigits - i;
      while (j > 0) {
         s[sIndex] = '0';
         sIndex++;
         j--;
      }
   }

   while (i > 0) {
      i--;
      s[sIndex] = buf[i];
      sIndex++;
   }
}
