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

#include "fp.h"

// Constructor
mb::mb()
{
	n = nn = 0;
	b = 0;
}


// Destructor
mb::~mb()
{
	if(nn && b)
    {
        free(b);
        n = nn = 0;
        b = NULL;
    }
}


mb::mb(const char *inString)
{
	if(!strlen(inString) || (strlen(inString)==1 && inString[0]=='0'))
    {
        n = nn = 0;
        b = 0;
        return;
    }
	
    mbConvFromStr(*this, inString);
}


mb::mb(double x)
{
    n = nn = 0;
    b = 0;
    
    if(!x)
        return;
    
    //equate(xt, x);
    equate(*this, x);
    /*
    n = xt.n;
    nn = abs(n);
    b = (UINT32*)malloc(nn*sizeof(UINT32));
    if(!b)
        exit(1);
    for(i=0;i<nn;i++)
        b[i] = xt.b[i];
     */
}


ostream& operator <<(ostream &s, const mb& x)
{
	char	*xString;
	
	xString = mb2Str(x);
	s << xString;
	
	free(xString);
	
	return s;
}


istream& operator >>(istream &s, mb& x)
{
	char	xStr[256]; // increase if needed
	bool	isGood;
	
	s.width(256); // increase if needed
	
	// get length of s
	//s.seekg(0, ios::end);
	//length = s.tellg();
	//s.seekg(0, ios::beg);
	
	s >> xStr;
	
	//length = s.tellg();
	
	isGood = init(x, xStr);
	
	if(!isGood)
		cerr << "conversion error!" << endl;
	
	return s;
}



mb mb::operator- ()
{
	mb		z;
	
	equate(z, *this);
	z.n = -z.n;
	return z;
}


mb mb::operator- () const
{
	mb		z;
	
	equate(z, *this);
	z.n = -z.n;
	return z;
}


mb& mb::operator= (const mb& x)
{
	INT32	i;
	
	if(this==&x)
		return *this;
    
    if((*this).nn && (*this).b)
        free((*this).b);
	
	if(!x.n)
	{
		n = nn = 0;
		b = 0;
		return *this;
	}
	
	n = x.n;
	nn = abs(x.n);
	b = (UINT32*)malloc(nn*sizeof(UINT32));
	if(!b)
		exit(1);
	
	for(i=0;i<nn;i++)
		b[i] = x.b[i];
	
	return *this;
}

mb& mb::operator= (INT32 x)
{
    if(nn && b)
    {
        free(b);
        n = nn = 0;
        b = NULL;
    }
    
    if(!x)
    {
        n = nn = 0;
        b = NULL;
        return *this;
    }
    
    if(sizeof(long)==4)
        long32tomb(*this, x);
    else
        long64tomb(*this, x);
    
    return *this;
}

mb& mb::operator= (INT64 x)
{
    if(nn && b)
    {
        free(b);
        n = nn = 0;
        b = NULL;
    }
    
    if(!x)
    {
        n = nn = 0;
        b = NULL;
        return *this;
    }
    
    long64tomb(*this, x);
    
    return *this;
}

mb& mb::operator= (double x)
{
    if(nn && b)
    {
        free(b);
        n = nn = 0;
        b = NULL;
    }
    
	if(!x)
	{
		n = nn = 0;
		b = 0;
		return *this;
	}
	
	equate(*this, x);
	
	return *this;
}


bool mb::operator> (const mb& y)
{
	
	if(compare(*this, y)==1)
		return true;
	
	return false;
}


bool mb::operator>= (const mb& y)
{
	
	if(!(compare(*this, y)==-1))
		return true;
	
	return false;
}


bool mb::operator== (const mb& y)
{
	
	if(!compare(*this, y))
		return true;
	
	return false;
}


bool mb::operator!= (const mb& y)
{
	
	if(!compare(*this, y))
		return false;
	
	return true;
}


bool mb::operator> (INT32 y)
{
	
	if(compare(*this, y)==1)
		return true;
	
	return false;
}


bool mb::operator>= (INT32 y)
{
	
	if(!(compare(*this, y)==-1))
		return true;
	
	return false;
}


bool mb::operator== (INT32 y)
{
	
	if(!compare(*this, y))
		return true;
	
	return false;
}


bool mb::operator!= (INT32 y)
{
	
	if(!compare(*this, y))
		return false;
	
	return true;
}


bool mb::operator! ()
{
	
	if(!n)
		return true;
	
	return false;
}


bool mb::operator<= (const mb& y)
{
	
	if(!(compare(*this, y)==1))
		return true;
	
	return false;
}


bool mb::operator< (const mb& y)
{
	
	if(compare(*this, y)==-1)
		return true;
	
	return false;
}


bool mb::operator> (const mb& y) const
{
	
	if(compare(*this, y)==1)
		return true;
	
	return false;
}


bool mb::operator>= (const mb& y) const
{
	
	if(!(compare(*this, y)==-1))
		return true;
	
	return false;
}


bool mb::operator== (const mb& y) const
{
	
	if(!compare(*this, y))
		return true;
	
	return false;
}


bool mb::operator!= (const mb& y) const
{
	
	if(!compare(*this, y))
		return false;
	
	return true;
}


bool mb::operator! () const
{
	
	if(!n)
		return true;
	
	return false;
}


bool mb::operator<= (const mb& y) const
{
	
	if(!(compare(*this, y)==1))
		return true;
	
	return false;
}


bool mb::operator< (const mb& y) const
{
	
	if(compare(*this, y)==-1)
		return true;
	
	return false;
}


mb mb::operator+ (const mb& y)
{
	mb		z;
	
	add(z, *this, y);
	
	return z;
}


mb mb::operator- (const mb& y)
{
	mb		z;
	
	sub(z, *this, y);
	
	return z;
}


mb mb::operator* (const mb& y)
{
	mb		z;
	
	mul(z, *this, y);
	
	return z;
}


mb mb::operator/ (const mb& y)
{
	mb		z;
	
	div(z, *this, y);
	
	return z;
}


mb mb::operator+ (const mb& y) const
{
	mb		z;
	
	add(z, *this, y);
	
	return z;
}


mb mb::operator- (const mb& y) const
{
	mb		z;
	
	sub(z, *this, y);
	
	return z;
}


mb mb::operator* (const mb& y) const
{
	mb		z;
	
	mul(z, *this, y);
	
	return z;
}


mb mb::operator/ (const mb& y) const
{
	mb		z;
	
	div(z, *this, y);
	
	return z;
}


mb& mb::operator+= (const mb& y)
{
	add(*this, *this, y);
	
	return *this;
}


mb& mb::operator-= (const mb& y)
{
	sub(*this, *this, y);
	
	return *this;
}


mb& mb::operator*= (const mb& y)
{
	mul(*this, *this, y);
	
	return *this;
}


mb& mb::operator/= (const mb& y)
{
	div(*this, *this, y);
	
	return *this;
}


mb mb::operator+ (double y)
{
	mb		z;
		
	add(z, *this, y);
	
	return z;
}


mb mb::operator- (double y)
{
	mb		z;
	
	sub(z, *this, y);
	
	return z;
}


mb mb::operator* (double y)
{
	mb		z;
	
	mul(z, *this, y);
	
	return z;
}


mb mb::operator/ (double y)
{
	mb		z;
		
	div(z, *this, y);
	
	return z;
}


mb mb::operator+ (double y) const
{
	mb		z;
	
	add(z, *this, y);
	
	return z;
}


mb mb::operator- (double y) const
{
	mb		z;
	
	sub(z, *this, y);
	
	return z;
}


mb mb::operator* (double y) const
{
	mb		z;
	
	mul(z, *this, y);
	
	return z;
}


mb mb::operator/ (double y) const
{
	mb		z;
	
	div(z, *this, y);
	
	return z;
}


mb& mb::operator+= (double y)
{
	add(*this, *this, y);
	
	return *this;
}


mb& mb::operator-= (double y)
{
	sub(*this, *this, y);
	
	return *this;
}


mb& mb::operator*= (double y)
{
	mul(*this, *this, y);
	
	return *this;
}


mb& mb::operator/= (double y)
{
	div(*this, *this, y);
	
	return *this;
}


mb& mb::operator&= (const mb& y)
{
	*this = mbAnd(*this, y);
	return *this;
}


mb& mb::operator&= (INT32 y)
{
	*this = mbAnd(*this, y);
	
	return *this;
}


mb mb::operator& (const mb& y)
{
	mb		z;
	
	z = mbAnd(*this, y);
	
	return z;
}


mb mb::operator& (const mb& y) const
{
	mb		z;
	
	z = mbAnd(*this, y);
	
	return z;
}


mb mb::operator& (INT32 y)
{
	mb		z;
	
	z = mbAnd(*this, y);
	
	return z;
}


mb mb::operator& (INT32 y) const
{
	mb		z;
	
	z = mbAnd(*this, y);
	
	return z;
}


mb& mb::operator|= (const mb& y)
{
	*this = mbOr(*this, y);
	return *this;
}


mb& mb::operator|= (INT32 y)
{
	*this = mbOr(*this, y);
	
	return *this;
}


mb mb::operator| (const mb& y)
{
	mb		z;
	
	z = mbOr(*this, y);
	
	return z;
}


mb mb::operator| (const mb& y) const
{
	mb		z;
	
	z = mbOr(*this, y);
	
	return z;
}


mb mb::operator| (INT32 y)
{
	mb		z;
	
	z = mbOr(*this, y);
	
	return z;
}


mb mb::operator| (INT32 y) const
{
	mb		z;
	
	z = mbOr(*this, y);
	
	return z;
}


mb& mb::operator^= (const mb& y)
{
	*this = mbXor(*this, y);
	return *this;
}


mb& mb::operator^= (INT32 y)
{
	*this = mbXor(*this, y);
	
	return *this;
}


mb mb::operator^ (const mb& y)
{
	mb		z;
	
	z = mbXor(*this, y);
	
	return z;
}


mb mb::operator^ (const mb& y) const
{
	mb		z;
	
	z = mbXor(*this, y);
	
	return z;
}


mb mb::operator^ (INT32 y)
{
	mb		z;
	
	z = mbXor(*this, y);
	
	return z;
}



mb mb::operator^ (INT32 y) const
{
	mb		z;
	
	z = mbXor(*this, y);
	
	return z;
}



mb mb::operator<< (INT32 y)
{
	mb		z;
	
	mbShiftLeft(z, *this, y);
	
	return z;
}


mb mb::operator>> (INT32 y)
{
	mb		z;
	
	mbShiftRight(z, *this, y);
	
	return z;
}


mb& mb::operator++ () // ++A
{
	
	add(*this, *this, 1.);
	
	return *this;
}


mb mb::operator++ (int)  // A++
{
	mb temp = *this;
	
	++(*this);
	return temp;
}


mb& mb::operator-- ()  // --A
{
	sub(*this, *this, 1.);
	
	return *this;
}


mb mb::operator-- (int) // A--
{
	mb temp = *this;
	
	--(*this);
	return temp;
}



mb mb::operator% (const mb& y)
{
	mb		z;
	
	myModulus(z, *this, y);
	
	return z;
}


mb mb::operator% (double y)
{
	mb		z;
	
	myModulus(z, *this, y);
	
	return z;
}


mb mb::operator% (const mb& y) const
{
	mb		z;
	
	myModulus(z, *this, y);
	
	return z;
}


mb mb::operator% (double y) const
{
	mb		z;
	
	myModulus(z, *this, y);
	
	return z;
}


mb operator+ (double x, mb& y)
{
	mb		z;
	mb		xt;
	
	equate(xt, x);
	add(z, xt, y);
	
	return z;
}


mb operator- (double x, mb& y)
{
	mb		z;
	mb		xt;
	
	equate(xt, x);
	sub(z, xt, y);
	
	return z;
}


mb operator* (double x, mb& y)
{
	mb		z;
	mb		xt;
	
	equate(xt, x);
	mul(z, xt, y);
	
	return z;
}


mb operator/ (double x, mb& y)
{
	mb		z;
	mb		xt;
	
	equate(xt, x);
	div(z, xt, y);
	
	return z;
}
