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

#include "fp.h"

INT32 decPrec=16;

void setDecPrec(INT32 prec)
{
	if(!prec)
		decPrec = 16;
	else
		decPrec = abs(prec);
}


INT32 getDecPrec()
{
	return decPrec;
}


// Constructor
fp::fp()
{
	i.n = i.nn = 0;
	i.b = 0;
	e = 0;
}


fp::~fp()
{
    
}


fp::fp(const char *inString)
{
    i.n = i.nn = 0;
    i.b = 0;
    e = 0;
    
    if(!fpConvFromString(*this, inString))
    {
        i.n = i.nn = 0;
        i.b = 0;
        e = 0;
    }
}


fp::fp(double x)
{
    i.n = i.nn = 0;
    i.b = 0;
    e = 0;
	equate(*this, x);
}


ostream& operator <<(ostream &s, const fp& x)
{
	char	*xString;
	
	xString = fpToStr(x, decPrec);
	s << xString;
	
	free(xString);
	
	return s;
}


istream& operator >>(istream &s, fp& 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;
}


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


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


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


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


fp& fp::operator= (double x)
{
	fp		xt;
	INT32	j;
	
    if(i.nn && i.b)
    {
        free(i.b);
        i.n = i.nn = e = 0;
        i.b = NULL;
    }
	
	if(!x)
	{
		i.n = i.nn = e = 0;
		i.b = 0;
		return *this;
	}
	
	equate(xt, x);
	
	i.n = xt.i.n;
	i.nn = abs(xt.i.n);
	e = xt.e;
	i.b = (UINT32*)malloc(i.nn*sizeof(UINT32));
	if(!i.b)
		exit(1);
	for(j=0;j<i.nn;j++)
		i.b[j] = xt.i.b[j];
	
	return *this;
}


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


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


bool fp::operator== (const fp& y)
{

	if(!compare(*this, y))
		return true;
	
	return false;
}


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


bool fp::operator! ()
{
	
	if(!i.n)
		return true;
	
	return false;
}


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


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


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


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


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


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


bool fp::operator! () const
{
	
	if(!i.n)
		return true;
	
	return false;
}


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


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


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


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


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


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


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


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


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


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


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


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


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


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


bool fp::operator> (double y)
{
	fp		yt;
	
	equate(yt, y);
	
	if(compare(*this, yt)==1)
		return true;
	
	return false;
}


bool fp::operator>= (double y)
{
	fp		yt;
	
	equate(yt, y);
	
	if(!(compare(*this, yt)==-1))
		return true;
	
	return false;
}


bool fp::operator== (double y)
{
	fp		yt;
	
	equate(yt, y);
	
	if(!compare(*this, yt))
		return true;
	
	return false;
}


bool fp::operator!= (double y)
{
	fp		yt;
	
	equate(yt, y);
	
	if(!compare(*this, yt))
		return false;
	
	return true;
}


bool fp::operator<= (double y)
{
	fp		yt;
	
	equate(yt, y);
	
	if(!(compare(*this, yt)==1))
		return true;
	
	return false;
}


bool fp::operator< (double y)
{
	fp		yt;
	
	equate(yt, y);
	
	if(compare(*this, yt)==-1)
		return true;
	
	return false;
}


bool fp::operator> (double y) const
{
	fp		yt;
	
	equate(yt, y);
	
	if(compare(*this, yt)==1)
		return true;
	
	return false;
}


bool fp::operator>= (double y) const
{
	fp		yt;
	
	equate(yt, y);
	
	if(!(compare(*this, yt)==-1))
		return true;
	
	return false;
}


bool fp::operator== (double y) const
{
	fp		yt;
	
	equate(yt, y);
	
	if(!compare(*this, yt))
		return true;
	
	return false;
}


bool fp::operator!= (double y) const
{
	fp		yt;
	
	equate(yt, y);
	
	if(!compare(*this, yt))
		return false;
	
	return true;
}


bool fp::operator<= (double y) const
{
	fp		yt;
	
	equate(yt, y);
	
	if(!(compare(*this, yt)==1))
		return true;
	
	return false;
}


bool fp::operator< (double y) const
{
	fp		yt;
	
	equate(yt, y);
	
	if(compare(*this, yt)==-1)
		return true;
	
	return false;
}


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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



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


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


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


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


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


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


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


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


/*
fp& fp::operator^= (const fp& y)
{
	pow(*this, *this, y);
	
	return *this;
}


fp& fp::operator^= (double y)
{
	pow(*this, *this, y);
	
	return *this;
}


fp fp::operator^ (const fp& y)
{
	fp		z;
	
	pow(z, *this, y);
	
	return z;
}


fp fp::operator^ (double y)
{
	fp		z;
	
	pow(z, *this, y);
	
	return z;
}


fp fp::operator^ (const fp& y) const
{
	fp		z;
	
	pow(z, *this, y);
	
	return z;
}


fp fp::operator^ (double y) const
{
	fp		z;
	
	pow(z, *this, y);
	
	return z;
}
 */


fp& fp::operator<< (INT32 y)
{
	e = e + y;
	
	return *this;
}


fp& fp::operator>> (INT32 y)
{
	e = e - y;
	
	return *this;
}


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


void fp::operator++ (int)
{
	++(*this);
}


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


void fp::operator-- (int)
{
	--(*this);
}


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


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


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


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



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


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


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


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

