// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.

#ifndef tools_mathd
#define tools_mathd

namespace tools {

//have : static const pi = 3.1415926535897931160E0; ???

//HEALPix lsconstants.h. Quite not the same as us.
//const double pi=3.141592653589793238462643383279502884197;
//const double twopi=6.283185307179586476925286766559005768394;
//const double fourpi=12.56637061435917295385057353311801153679;
//const double halfpi=1.570796326794896619231321691639751442099;

inline double pi()      {return 3.1415926535897931160E0;}
inline double two_pi()  {return 6.2831853071795862320E0;}
inline double half_pi() {return 1.5707963267948965580E0;}

inline double deg2rad() {
  static const double s_v = pi()/180.0;
  return s_v;
}
inline double rad2deg() {
  static const double s_v = 180.0/pi();
  return s_v;
}

// for Lib/ExpFunc.
inline bool in_domain_all(double){return true;}
inline bool in_domain_log(double a_x){return (a_x>0?true:false);}
inline bool in_domain_tan(double a_x){
  int n = int(a_x/half_pi());
  if(a_x!=n*half_pi()) return true;
  return (2*int(n/2)==n?true:false);
}
inline bool in_domain_acos(double a_x){
  if((a_x<-1)||(1<a_x)) return false;
  return true;
}

/*
inline double angle_modulo(double a_angle) {
  int64 div = a_angle/two_pi();
  double rest = a_angle - div*two_pi();
  if(rest<0) rest += two_pi();
  return rest;
}
*/

}

//#include "power"

#include <cmath>

namespace tools {

inline double dcos(const double& a_x) {return ::cos(a_x);}
inline double dsin(const double& a_x) {return ::sin(a_x);}
inline double dpow(const double& a_x,const double& a_y) {return ::pow(a_x,a_y);}
inline double dcosh(const double& a_x) {return ::cosh(a_x);}
inline double dsinh(const double& a_x) {return ::sinh(a_x);}

inline double dconj(const double& a_x) {return a_x;}
inline double dfabs(const double& a_x) {return ::fabs(a_x);} //if passing a_fabs(const T&).
inline double dsqrt(const double& a_x) {return ::sqrt(a_x);}

//long double
#ifndef ANDROID
inline long double ldfabs(const long double& a_x) {return ::fabsl(a_x);}
#endif

inline bool dpow(const double& a_x,const double& a_y,double& a_v) {
  if((a_x==0)&&(a_y<0)) {
    a_v = 0;
    return false;
  }
  a_v = dpow(a_x,a_y);
  return true;
}

inline double dgaussian(const double& a_x,const double& a_mean,const double& a_sigma) {
  double _tmp = (a_x-a_mean)/a_sigma;
  return ::exp(-_tmp*_tmp/2.0)/(a_sigma*::sqrt(2*pi()));
}

}

#endif
