#include "gennum.h"
#include "exceptions.h"

// Numeric functions.
// Some ops are also in gfunc.C.

Root *DoMkComplex(Root *x, Root *y)
{
    const Real *re = ConvertReal(x);
    const Real *im = ConvertReal(y);
    if (re == NULL || im == NULL) return NULL;
    return new ComplexPair(*re, *im);
}

Root* DoRem(Numeric* x, Numeric* y)
{
    const Real *xr = ConvertReal(x);
    const Real *yr = ConvertReal(y);
    if (xr == NULL || yr == NULL) return NULL;
    const Real* remainder;
    div(*xr, *yr, TruncateMode, NULL, &remainder);
    return (Root*)remainder;
}

Root* DoMod(Numeric* x, Numeric* y)
{
    const Real *xr = ConvertReal(x);
    const Real *yr = ConvertReal(y);
    if (xr == NULL || yr == NULL) return NULL;
    const Real* remainder;
    div(*xr, *yr, FloorMode, NULL, &remainder);
    return (Root*)remainder;
}

Root *DoPower(Numeric* xn, Numeric* yn)
{
    xn = (Numeric*)power(xn, yn);
    if (xn == NULL) RaiseDomainError(NULL);
    return xn;
}

Root* DoFloor(Real* arg)
{
    return (Root*)&arg->to_integer(FloorMode);
}
Root* DoCeiling(Real* arg)
{
    return (Root*)&arg->to_integer(CeilingMode);
}
Root* DoTruncate(Real* arg)
{
    return (Root*)&arg->to_integer(TruncateMode);
}
Root* DoRound(Real* arg)
{
    return (Root*)&arg->to_integer(RoundMode);
}

Root *DoShift(Integer *n1, Integer *n2)
{
    long count;
    if (!n2->getlong(&count)) RaiseDomainError(NULL);
    return (Root*)&(*n1 << count);
}

Root* DoExactToInexact(Numeric *num)
{
    Numeric *n = (Numeric*)num->numeric();
    return n->as_inexact();
}

Root* DoInexactToExact(Numeric *num)
{
    Numeric *n = (Numeric*)num->numeric();
    return n->as_exact();
}
