/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2008-03-28
**  Copyright: 2008-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#ifndef NUMBER_H
#define NUMBER_H

#include "QGpCoreToolsDLLExport.h"
#include "Trace.h"
#include "Complex.h"
#include "RealMP.h"
#include "ComplexMP.h"
#include "Translations.h"

namespace QGpCoreTools {

class QGPCORETOOLS_EXPORT Number
{
  TRANSLATIONS("Number")
public:
  Number();

  static unsigned int nextPowerOfTwo(unsigned int val);
  static double round(double val, double maximum=1.0);
  static inline double sign(double val);
  static inline int sign(int val);

  static QString toUserString(double val, char format, int precision, QLocale * locale=&_locale);
  static inline QString toString(double val, char format, int precision);
  static inline QString toString(const Complex& val, char format, int precision);
#ifdef MULTI_PRECISION
  static inline QString toString(const RealMP& val, char format, int precision);
  static inline QString toString(const ComplexMP& val, char format, int precision);
#endif

  static double toDouble(const QString& str, bool &ok, QLocale * locale=&_locale);
  static double toDouble(const QVariant& val, bool &ok, QLocale * locale=&_locale);

  static double toDouble(float f);
  static double toDouble(const Complex & c) {return c.abs();}
  static double toDouble(double a) {return a;}

  static unsigned char fromBinaryCodedDecimal(unsigned char bcd);
  static unsigned short fromBinaryCodedDecimal(unsigned short bcd);
  static unsigned int fromBinaryCodedDecimal(unsigned int bcd);
  static unsigned char toBinaryCodedDecimal(unsigned char val);
  static unsigned short toBinaryCodedDecimal(unsigned short val);
  static unsigned int toBinaryCodedDecimal(unsigned int val);

  static QList<int> divisors(int n);

  static QString secondsToDuration(double sec, int numberPrecision=-1, QLocale * locale=&_locale);
  static double durationToSeconds(const QString& str, bool &ok, QLocale * locale=&_locale);
  static double durationToSeconds(const QVariant& val, bool &ok, QLocale * locale=&_locale);
private:
  inline static bool durationToSecondsSign(const QChar * p, int& i, int n);
  static double durationToSecondsError(const QString& str, int pos, bool &ok);
private:

  static QLocale _locale;
};

inline double abs(double a)
{
  return ::fabs(a);
}

inline double abs2(double a)
{
  return a*a;
}

inline QString Number::toString(double val, char format, int precision)
{
  return QString::number(val, format, precision);
}

inline QString Number::toString(const Complex& val, char format, int precision)
{
  return val.toString(format, precision);
}

#ifdef MULTI_PRECISION
inline QString Number::toString(const RealMP& val, char format, int precision)
{
  return val.toString(format, precision);
}

inline QString Number::toString(const ComplexMP& val, char format, int precision)
{
  return val.toString(format, precision);
}
#endif

inline double Number::sign(double val)
{
  if(val>0.0) {
    return 1.0;
  } else if(val<0.0) {
    return -1.0;
  } else {
    return 0.0;
  }
}

inline int Number::sign(int val)
{
  if(val>0) {
    return 1;
  } else if(val<0) {
    return -1;
  } else {
    return 0;
  }
}

} // namespace QGpCoreTools

#endif // NUMBER_H
