git » metnum-tp1.git » master » tree

[master] / aritmetica.cpp

#include <stdint.h>
#include "aritmetica.hpp"

uint64_t to_u64(double n)
{
	uint64_t *p;
	p = (uint64_t *) &n;
	return *p;
}

uint64_t to_u64(numero n)
{
	return to_u64(n.to_double());
}

double to_double(uint64_t n)
{
	double *p;
	p = (double *) &n;
	return *p;
}

double trunc(int prec, double n)
{
	/* Sabemos que el double tiene 64 bits en total, de los cuales se usan
	 * 52 para la mantisa. Para recortar, dejamos en 0 todo lo que excede
	 * a la precision pedida, aplicando una máscara. */

	/* Armamos la máscara */
	uint64_t mask = 0xFFFFffffFFFFffffLLU;
	mask = mask << (52 - prec);

	uint64_t t = to_u64(n) & mask;

	return to_double(t);
}

double round_up(int prec, double n)
{
	double round = trunc(prec + 1, n) - trunc(prec, n);
	return trunc(prec, n + round);
}


/*
 * Clase número
 */

/* Por default usamos truncamiento como metodo de aproximacion */
double (*numero::aprox_m) (int prec, double n) = trunc;

numero::numero(int prec, double real)
{
	this->prec = prec;
	this->real = numero::aprox_m(prec, real);
}

int numero::get_prec() const
{
	return this->prec;
}

/* Todas las operaciónes son iguales, por lo que armamos una macro para
 * crearlas y ahorrarnos el copy-paste */
#define DEF_OP(OP) \
	numero numero::operator OP (const numero &b) const \
	{ \
		return numero(this->prec, \
				numero::aprox_m(this->prec, this->real) \
					OP \
				numero::aprox_m(this->prec, b.real)); \
	} \
	\
	numero numero::operator OP (const double &b) const \
	{ \
		return numero(this->prec, \
				numero::aprox_m(this->prec, this->real) \
					OP \
				numero::aprox_m(this->prec, b)); \
	} \
	\
	numero operator OP (const double &a, const numero &b) \
	{ \
		return numero(b.get_prec(), \
				numero::aprox_m(b.get_prec(), a) \
					OP \
				b.to_double()); \
	}

DEF_OP(+)
DEF_OP(-)
DEF_OP(*)
DEF_OP(/)

numero numero::operator = (double n)
{
	this->real = trunc(this->prec, n);
	return *this;
}

numero numero::operator = (numero n)
{
	this->prec = n.prec;
	this->real = n.real;
	return *this;
}

bool numero::operator == (numero n)
{
	return (n.real == this->real);
}
//numero::operator double() const
//{
//	return this->real;
//}

double numero::to_double() const
{
	return this->real;
}