/*

   Copyright (C) 2001,2002,2003,2004 Michael Rubinstein

   This file is part of the L-function package L.

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   Check the License for details. You should have received a copy of it, along
   with the package; see the file 'COPYING'. If not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

/*
  Michael Rubinstein's addition to mpreal.h
*/

#ifndef Lmpreal_H
#define Lmpreal_H

template<class T> inline void reset(T& t) {
    mpfr_clear(t.mpfr_ptr());
    mpfr_init(t.mpfr_ptr());
}

#include "mpreal.h"

using namespace mpfr;

#define cpplongop(op) \
inline mpreal operator op(const mpreal& x, const long long& y) { return x op (double)y; } \
inline mpreal operator op(const long long& y, const mpreal& x) { return (double)y op x; }

cpplongop(+) cpplongop(*) cpplongop(-) cpplongop(/)

#define cppop(op) \
template<typename T> inline mpreal op(const T& x) {\
        mpreal ret,y=x;\
        mpfr_##op(ret.mpfr_ptr(), y.mpfr_ptr(), __gmp_default_rounding_mode);\
        return ret;\
}
#define cpp_two_op(op) \
template<typename T> inline mpreal op(const T& x) {\
        mpreal ret,y=x;\
        mpfr_##op(ret.mpfr_ptr(), y.mpfr_ptr());\
        return ret;\
}

cppop(abs)
cppop(rint)
cpp_two_op(trunc)
cpp_two_op(floor)
cpp_two_op(ceil)
cppop(sqrt)
cppop(log)
cppop(log2)
cppop(log10)
cppop(exp)
cppop(exp2)
cppop(exp10)
cppop(cos)
cppop(sin)
cppop(tan)
cppop(sec)
cppop(csc)
cppop(cot)
cppop(acos)
cppop(asin)
cppop(atan)
cppop(cosh)
cppop(sinh)
cppop(tanh)
cppop(sech)
cppop(csch)
cppop(coth)
cppop(acosh)
cppop(asinh)
cppop(atanh)
cppop(log1p)
cppop(expm1)
cppop(eint)
cppop(gamma)
cppop(lngamma)
cppop(zeta)
cppop(erf)
cppop(erfc)

template<typename T, typename U> inline mpreal pow(const T& a, const U& b) {
    return exp(log(a)*b);
}

template<typename T> inline mpreal atan2(const T& y, const T& x) {
    mpreal ret,Y=y,X=x;\
    mpfr_atan2(ret.mpfr_ptr(), Y.mpfr_ptr(), X.mpfr_ptr(),__gmp_default_rounding_mode);\
    return ret;\
}

inline const mpreal fmod (const mpreal& x, const mpreal& y)
{
    mpreal a;
    mp_prec_t yp, xp;

    yp = y.get_prec();
    xp = x.get_prec();

    a.set_prec(yp>xp?yp:xp);

    mpfr_fmod(a.mpfr_ptr(), x.mpfr_ptr(), y.mpfr_ptr(), __gmp_default_rounding_mode);

return a;
}


#endif
