/*********************************************************************
 * This file is part of the cpplibs suite.
 *
 * Copyright (C) 2001 Topi Mäenpää
 * All rights reserved.
 *
 * This program is free software. You can redistribute and/or modify
 * it under the terms of the free software licence found in the
 * accompanying file "COPYING". The licence terms must always be
 * redistributed with this source file. The above copyright notice
 * must be reproduced in all modified and unmodified copies of this
 * source file.
 *
 * $Revision: 1.2 $
 *********************************************************************/

#include "Number.h"
#include "Boolean.h"

namespace util
{
	SmartPtr<Computable> Number::complement() const throw (ComputationException&)
	{
		return SmartPtr<Computable>(new Boolean(doubleValue() == 0));
	}

	SmartPtr<Computable> Number::plus(const Computable& c, bool switched) const throw (ComputationException&)
	{
		const Number* number = dynamic_cast<const Number*>(&c);
		if (number)
			return SmartPtr<Computable>(new Double(doubleValue() + number->doubleValue()));
		throw createException("+",c);
	}
	
	SmartPtr<Computable> Number::minus(const Computable& c) const throw (ComputationException&)
	{
		const Number* number = dynamic_cast<const Number*>(&c);
		if (number)
			return SmartPtr<Computable>(new Double(doubleValue() - number->doubleValue()));
		throw createException("-",c);
	}

	SmartPtr<Computable> Number::multiply(const Computable& c, bool switched) const throw (ComputationException&)
	{
		const Number* number = dynamic_cast<const Number*>(&c);
		if (number)
			return SmartPtr<Computable>(new Double(doubleValue() * number->doubleValue()));
		throw createException("*",c);
	}
	
	SmartPtr<Computable> Number::divide(const Computable& c) const throw (ComputationException&)
	{
		const Number* number = dynamic_cast<const Number*>(&c);
		if (number)
			return SmartPtr<Computable>(new Double(doubleValue() / number->doubleValue()));
		throw createException("/",c);
	}

	SmartPtr<Computable> Number::modulus(const Computable& c) const throw (ComputationException&)
	{
		const Number* number = dynamic_cast<const Number*>(&c);
		if (number)
			{
				double i1 = doubleValue() - long(doubleValue());
				double i2 = number->doubleValue() - long(number->doubleValue());
				if (i1 == 0 && i2 == 0)
					return SmartPtr<Computable>(new Double(long(doubleValue()) % long(number->doubleValue())));
				else
					return SmartPtr<Computable>(new Double(doubleValue()));
			}
		throw createException("/",c);
	}

	int Number::compare(const Computable& c) const throw (ComputationException&)
	{
		const Number* number = dynamic_cast<const Number*>(&c);
		if (number)
			{
				double d1 = doubleValue(), d2 = number->doubleValue();
				if (d1 > d2)
					return 1;
				else if (d2 > d1)
					return -1;
				return 0;
			}
		throw OperationNotDefinedException("Number::compare(Computable&): Cannot compare " + getClassName() +
																			 " and " + c.getClassName());
	}
}
