/*
   My VMPU routines... in C.
   -- RKeene [06/10/1999:14:00]  
   rkeene@netfueldesign.com

   Synopsis of procedures status:
   name		| status
   ----------------+-------------------------------------------------
   add()		| works ok with no decimals.
   mul()		| works ok with no decimals.
   sub()		| works ok with no decimals, needs to be rewritten.
   div()		| doesnt do anything.
   pwr()		| doesnt do anything.
   addlead()	| works ok.
   addtrail()	| works ok.
   striplead()	| works ok.
   isgreater()	| works ok, with no decimals.
   cleararray()	| works ok, slow.
   ---------------/ \------------------------------------------------
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define		LIMIT		8192
#define 	DEBUG		0

void add();
void sub();
void mul();
void divd();

void cleararray(char n[LIMIT])
{
   int i;
   for (i=0;i<LIMIT;i++)
   {
      n[i]=0;
   }
}

void addlead(int n, char f, char t[LIMIT])
{
   int i;
   int m;
   char tmp[LIMIT];
   cleararray(tmp);
   m=strlen(t);
   for(i=0;i<n;i++)
   {
      tmp[i]=f;
   }
   for (i=i;i<(n+m);i++)
   {
      tmp[i]=t[i-n];
   }
#if DEBUG>=3
   printf("addlead returning %s\n",tmp);
#endif
   strcpy(t,tmp);
}

void addtrail(int n, char f, char t[LIMIT])
{
   int i;
   int m;
   char tmp[LIMIT];
   cleararray(tmp);
   m=strlen(t);
   if (DEBUG>=3) printf("addtrail(%i,%i,%s) -> ",n,f,t);
   for(i=0;i<m;i++)
   {
      tmp[i]=t[i];
   }
   for (i=i;i<(n+m);i++)
   {
      tmp[i]=f;
   }
   if (DEBUG==3) printf("addtrail returning %s\n",tmp);
   strcpy(t,tmp);
}


/*
   Strip leading 0's from a numeric string.
   sets X to the string.
*/
void striplead(char x[LIMIT], char n[LIMIT])
{
   char tmp[LIMIT];
   int i,sizeofn;
   int begin=-1, neg=0;
   sizeofn=strlen(n);
   if (n[0]=='-') {  neg=1; n[0]='0';  }
   for (i=0;i<sizeofn;i++)
   {
      if (n[i]!='0' && begin==-1) {  begin=i;  }
      if (begin!=-1) {  tmp[i-begin]=n[i];  }
   }
   if (begin!=-1) {  tmp[(i-begin)]=0;  } else {  tmp[0]='0'; tmp[1]=0;  }
   cleararray(x);
   if (neg==1) {  sprintf(x,"%c%s",'-',tmp); n[0]='-';  } else {  strcpy(x,tmp);  }
}


int isgreater(char n1[LIMIT], char n2[LIMIT])
{
   char tmp1[LIMIT];
   char tmp2[LIMIT];
   int sizeofn1,sizeofn2,i,tmpc1,tmpc2,neg=0;
   striplead(tmp1,n1);
   striplead(tmp2,n2);
   if (tmp1[0]=='-') {  neg+=10; tmp1[0]='0';  }
   if (tmp2[0]=='-') {  neg+=1; tmp1[0]='0';  }
   if (neg==1) {  return(1);  }
   if (neg==10) {  return(2);  }
   sizeofn1=strlen(tmp1);
   sizeofn2=strlen(tmp2);
   if (sizeofn1>sizeofn2) return(1);
   if (sizeofn1<sizeofn2) return(2);
   for (i=0;i<sizeofn1;i++)
   {
      tmpc1=tmp1[i]-48;
      tmpc2=tmp2[i]-48;
      if (tmpc1>tmpc2) {  return(1);  }
      if (tmpc1<tmpc2) {  return(2);  }
   }
   return 0;
}


void add(char n1[LIMIT], char n2[LIMIT])
{
   char tmp1[LIMIT];
   char tmp2[LIMIT];
   char tmp3[LIMIT];
   int tmpc1;
   int tmpc2;
   int sizeofn1;
   int sizeofn2;
   int diff;
   int i;
   int remain=0;
   int val,neg=0;
   sizeofn1=strlen(n1);
   sizeofn2=strlen(n2);
   cleararray(tmp1);
   strcpy(tmp2,tmp1);
   strcpy(tmp3,tmp1);
   if(DEBUG>=1) printf("Adding %s(%i) and %s(%i)\n",n1,sizeofn1,n2,sizeofn2);
   diff=abs(sizeofn1-sizeofn2);
   strcpy(tmp1,n1);
   strcpy(tmp2,n2);
   if (tmp1[0]=='-') {  neg+=1; tmp1[0]='0';  }
   if (tmp2[0]=='-') {  neg+=10; tmp2[0]='0';  }
   if (neg==10) {  (void) sub(tmp1,tmp2); strcpy(n1,tmp1); return;  }
   if (neg==1) {  (void) sub(tmp2,tmp1); strcpy(n1,tmp2);
		  printf("-->%s (%s)",n1,tmp2);
		  return;  }
   if (sizeofn1<sizeofn2) {  addlead(diff,'0',tmp1);  }
   if (sizeofn1>sizeofn2) {  addlead(diff,'0',tmp2);  }
   if (DEBUG>=1) printf ("  %s\n+ %s\n",tmp1,tmp2);
   sizeofn2=strlen(tmp2);
   for (i=(sizeofn2-1);i>=0;i--)
   {
      tmpc1=tmp1[i];
      tmpc2=tmp2[i];
      if (tmpc1<48 || tmpc1>57 || tmpc2<48 || tmpc2>57) {  i=0;  }
      val=((tmpc1-48)+(tmpc2-48)+remain);
      if (val>9) {  val -= 10; remain=1;  } else {  remain = 0;  }
      if (DEBUG>=2) {  printf ("%i) %i rem %i (%i,%i)\n",i,val,remain,tmpc1-48,tmpc2-48);  }
      tmp3[i]=(val+48);
   }
   tmp3[sizeofn2]=0;
   if (neg==11) {  sprintf(n1,"%c%s",'-',tmp3);  } else {  strcpy(n1,tmp3);  }
#if DEBUG>=1
   printf("  %s\n",n1);
#endif
}

void mul(char n1[LIMIT], char n2[LIMIT])
{
   char tmp1[LIMIT];
   char tmp2[LIMIT];
   char tmp3[LIMIT];
   char tmp4[LIMIT];
   char offset[LIMIT];
   int sizeofn1;
   int sizeofn2;
   int i,q,tmpc1,tmpc2,val,remain,neg=0;
#if DEBUG>=1
   printf("Multiplying %s by %s...\n",n1,n2);
#endif
   cleararray(tmp1);
   strcpy(tmp2,tmp1);
   strcpy(tmp3,tmp1);
   strcpy(tmp4,tmp1);
   strcpy(offset,tmp1);
   if (strlen(n1)>=strlen(n2)) {  strcpy(tmp1,n1); strcpy(tmp2,n2);  }
   if (strlen(n1)<strlen(n2)) {  strcpy(tmp1,n2); strcpy(tmp2,n1);  }
   if (tmp1[0]=='-') {  tmp1[0]='0'; neg+=1;  }
   if (tmp2[0]=='-') {  tmp2[0]='0'; neg+=1;  }
#if DEBUG>=1
   printf("  %s\n* %s\n",tmp1,tmp2);
#endif
   sizeofn1=strlen(tmp1);
   sizeofn2=strlen(tmp2);
   for (i=(sizeofn2-1);i>=0;i--)
   {
      tmp4[0]='0';
      remain=0;
      for (q=(sizeofn1-1);q>=0;q--)
      {
	 tmpc1=tmp1[q]-48;
	 tmpc2=tmp2[i]-48;
	 val=(tmpc1*tmpc2)+remain;
	 if (val>9) {  remain=val/10; val-=remain*10;  } else {  remain = 0;  }
	 tmp4[q+1]=val+48;
#if DEBUG>=2
	 printf("%i,%i) %i,%i=%i rem %i\n",i,q,tmpc1,tmpc2,val,remain);
#endif
      }
      tmp4[0]=remain+48;
      tmp4[sizeofn1+1]=0;
      addtrail(((i-sizeofn2)*-1)-1,'0',tmp4);
#if (DEBUG>=2)
	 printf("%s(%i) (%s(%i))\n",tmp4,(int) strlen(tmp4),tmp3,(int) strlen(tmp3));
#endif
      add(tmp3,tmp4);
   }
   if (neg==1) {  sprintf(n1,"%c%s",'-',tmp3);  } else {  strcpy(n1,tmp3);  }
#if DEBUG>=1
   printf("  %s(%i)\n",n1,(int) strlen(n1));
#endif
}

void sub(char n1[LIMIT], char n2[LIMIT])
{
   char tmp1[LIMIT];
   char tmp2[LIMIT];
   char tmp3[LIMIT];
   int borrow=0;
   int neg=0, nega=0;
   int i,tmpc1,tmpc2,val,diff,greater;
   int sizeofn1,sizeofn2;
#if (DEBUG>=1)
      printf("Sub calculating %s(%i)-%s(%i)...\n",n1,sizeofn1,n2,sizeofn2);
#endif
   greater=isgreater(n1,n2);
   if (greater==2) {
		      neg=1;
		      strcpy(tmp1,n2);
		      strcpy(tmp2,n1);
		   } else {
			     neg=0;
			     strcpy(tmp1,n1);
			     strcpy(tmp2,n2);
			  }
   if (tmp1[0]=='-') {  tmp1[0]='0'; nega+=10;  }
   if (tmp2[0]=='-') {  tmp2[0]='0'; nega+=1;  }
   if (nega==11) {  tmp1[0]='-'; add(tmp1,tmp2); strcpy(n1,tmp1); return;  }
   if (neg==1 && nega==1) {  add(tmp1,tmp2); sprintf(n1,"%c%s",'-',tmp1); return;  }
   if (neg==0 && nega==1) {  add(tmp1,tmp2); strcpy(n1,tmp1); return;  }
   sizeofn1=strlen(tmp1);
   sizeofn2=strlen(tmp2);
   diff=abs(sizeofn1-sizeofn2);
   if (sizeofn1<sizeofn2) {  addlead(diff,'0',tmp1);  }
   if (sizeofn1>sizeofn2) {  addlead(diff,'0',tmp2);  }
#if (DEBUG>=1)
   {  printf("  %s\n- %s\n",tmp1,tmp2);  }
#endif
   for (i=strlen(tmp1)-1;i>-1;i--)
   {
      tmpc1=tmp1[i]-48;
      tmpc2=tmp2[i]-48;
      val=tmpc1-tmpc2-borrow;
      borrow=0;
      if (val<0 && i==0) {  neg=1;  }
      if (val<0) {  borrow=1; val+=10;  };
#if (DEBUG>=2)
      {  printf("%i) %i,%i=%i\n",i,tmpc1,tmpc2,val);  }
#endif
      tmp3[i+1]=val+48;
   }
/*
      sprintf(tmp3,"%i%s",borrow,tmp3);
*/
   if (neg==1) {  tmp3[0]='-';  } else {  tmp3[0]='0';  }
#if (DEBUG>=1)
   {  printf("  %s\n",tmp3);  }
#endif
   tmp3[sizeofn1+1]=0;
   strcpy(n1,tmp3);
}

void divd(char n1[LIMIT], char n2[LIMIT]) {

					  }

void pwr(char n1[LIMIT],char n2[LIMIT])
{
   char tmp[LIMIT], dec[2];
   strcpy(dec,"1");
   strcpy(tmp,n1);
   sub(n2,dec);
   while(isgreater(n2,"0")==1)
   {
      sub(n2,dec);
      striplead(n2,n2);
/*
	 printf("%s... %s... %s\n",n2,n1,dec);
*/
      mul(n1,tmp);
      striplead(n1,n1);
   }
}


int main(int argc, char *argv[])
{
   char nm1[LIMIT], nm2[LIMIT];
   if (argc<=3) {  printf("Usage:\t%s {add|sub|mul|div|pwr} {number} {number}\n",argv[0]); return(1);  }
   strcpy(nm1,argv[2]);
   strcpy(nm2,argv[3]);
   if (strncmp("add",argv[1],3)==0) {  add(nm1,nm2);  }
   if (strncmp("sub",argv[1],3)==0) {  sub(nm1,nm2);  }
   if (strncmp("mul",argv[1],3)==0) {  mul(nm1,nm2);  }
   if (strncmp("pwr",argv[1],3)==0) {  pwr(nm1,nm2);  }
   if (strncmp("div",argv[1],3)==0) {  divd(nm1,nm2);  }
   striplead(nm1,nm1);
   printf("Result=%s\n",nm1);
   return(0);
}
