#include "huge.h"

int HTOI(char hex) {
    if ((hex>='0')&&(hex<='9'))
      return hex-'0';
    else if ((hex>='A')&&(hex<='F'))
      return 10+hex-'A';
    else if ((hex>='a')&&(hex<='f'))
      return 10+hex-'a';
    else {
	cerr << "Error converting (" << hex << ") to integer" << endl;
	exit(2);
    }
};

char ITOH(short x) {
    if ((x<0)||(x>15)) {
	cerr << x << " is a bad value for ITOH(x)" << endl;
	exit(3);
    }
    else if (x<10)
      return x+'0';
    else return (x-10)+'A';
};

char* ITOA(unsigned short arg) {
    char *ret=(char*)malloc(5);

    ret[3]=ITOH(arg%16);
    ret[2]=ITOH((arg>>4)%16);
    ret[1]=ITOH((arg>>8)%16);
    ret[0]=ITOH((arg>>12)%16);
    ret[4]='\0';

    return ret;
};
    

Huge::Huge(): length(0) {
    for(int i=0; i<32; i++) v[i]=0;
};

Huge::Huge(int arg) {
    for(int i=0; i<32; i++) v[i]=0;
    v[0]=arg%SHORTMAX;
    v[1]=(arg >> 16) % SHORTMAX;
    if (v[1]) length=2;
    else length=1;
};

Huge::Huge(Huge& other): length(other.length) {
    int i;
    for(i=0; i<length;i++) v[i]=other.v[i];
    for(;i<32; i++) v[i]=0;
};

istream& operator>>(istream& ist, Huge& biggie) {
    String bin;
    int len, walker, eofs;  // eofs=end of first (MSD) short

    ist >> bin;
    len=bin.length();
    if ((len<1)||(len>128)) {
	cerr << "Problem with length of input" << endl;
	exit(1);
    }
    
    //Each short can store 4 hex digits (4 hex * 4 bits == 16 bits)
    biggie.length=(int)len/4;
    if ((biggie.length*4)!=len) biggie.length++;
    
    len--; // Become the maximum index into bin[i]
    for(walker=biggie.length-2; walker>=0; walker--) 
      biggie.v[walker]=HTOI(bin[len-walker*4])+
	16*(HTOI(bin[len-walker*4-1])+
	    16*(HTOI(bin[len-walker*4-2])+
		16*HTOI(bin[len-walker*4-3])));
    len++; // Turn len back into the length of bin.

    if (!(eofs=len%4)) eofs=4;
    if (eofs<len) 
      bin[eofs]='\0';
    biggie.v[biggie.length-1]=strtol((char*)bin, NULL, 16);
    return ist;
};

ostream& operator<<(ostream& ost, Huge& biggie) {
    int walker;
    
    if ((1<<15)==(biggie.v[31]&(1<<15))) {
	ost << "-" << -biggie;
	return ost;
    }

    if (biggie.length>=1) ost << "0x";
    for(walker=biggie.length-1; walker>=0; walker--) 
      ost << ITOA(biggie.v[walker]);
    return ost;
};

Huge operator+(Huge& one, Huge& two) {
    Huge sum; 
    
    /*   i-->%l3, temp-->%l1 */
    /*   &one --> %i0, &two --> %i1 */ 
    
    /*  &sum --> %l5 (goes for 66 bytes...) */
    /*  On Solaris: starts at [%fp - 88], on sunos: [%fp - 80] */
    asm("	mov	%fp,	%l5");
    asm("	add	%l5,	-80,	%l5");   
    asm("	clr	%l1");
    asm("	clr	%l3");
    asm("_loop:");
    asm("	umul	0x2,	%l3,	%l2");
    asm("	lduh	[%i0 + %l2],	%l6");
    asm("	lduh	[%i1 + %l2],	%l7");
    asm("	add	%l6,	%l7,	%l7");
    asm("	add	%l1,	%l7,	%l1");
    asm("	mov 	%l1, 	%l7");
    asm("	sll 	%l7, 	0x10, 	%l7"); /* Mod l7 by 0xFFFF */
    asm("	srl 	%l7,	0x10, 	%l7"); /* Shift left, then right */
    asm("	sth	%l7,	[%l5 + %l2]");
    asm("	srl	%l1,	0x10,	%l1");
    asm("	inc	%l3");
    asm("	cmp	%l3,	0x20");
    asm("	bl	_loop");
    asm("	nop");

    asm("	mov	0x1f,	%l3");         /* Set the length part */
    asm("_loop2:");
    asm("	cmp	%l3,	%g0");
    asm("	bl	_exitloop2");
    asm("	umul	0x2,	%l3,	%l2");
    asm("	lduh	[%l5 + %l2],	%l6");
    asm("	cmp	%l6,	%g0");
    asm("	bnz	_exitloop2");
    asm("	nop");
    asm("	dec	%l3");
    asm("	b	_loop2");
    asm("	nop");
    asm("_exitloop2:");
    asm("	inc	%l3");
    asm("	sth	%l3, 	[%l5 + 0x40]");

    asm("mov %l5, %i0");

    return sum;
	
};
/*
Huge operator+(Huge& one, Huge& two) {
    Huge sum;
    int i, temp=0;
   
    for (i=0; i<32; i++) {
	temp=temp+one.v[i]+two.v[i];
	sum.v[i]=temp%SHORTMAX;
	temp=temp >> 16;
    };
    for (i=31;(i>=0)&&(sum.v[i]==0);i--);
    sum.length=i+1;

    return sum;
	
};
*/
Huge operator-(Huge& one, Huge& two) {
    return one + (-two);
};

Huge operator-(Huge& one) {
    Huge ret(one);
    
    for(int i=0; i<32; i++) ret.v[i]^=SHORTMAX-1;
    ret=ret+ (Huge)1;
    
    return ret;

};

int main() {
    Huge x, y, z;

    cout << "All input and output is in hex!!!" << endl; 
    cout << "Enter x: ";
    cin >> x;
    cout << "Enter y: ";
    cin >> y;
    cout << "x=" << x << endl 
	 << "y=" << y << endl;
    z=-(-x);
    cout << "-(-x)=" << z << endl;
    z=x + y;
    cout << "x+y=" << z << endl;
    z=-x;
    cout << "-x=" << z << endl;
    z=-y;
    cout << "-y=" << z << endl;
    z=-(x + y);
    cout << "-(x+y)=" << z << endl;
    z=(-x)+(-y);
    cout << "(-x)+(-y)=" << z << endl;
    z=x-y;
    cout << "x-y=" << z << endl;
};

	
