#include <ctype.h>
#include <stdlib.h>

#include "real.h"

const real ZERO(0.0);
const real UNO(1.0);
const real CENTO(100.0);

#ifdef __LONGDOUBLE__

#include <math.h>

#include <stdio.h>
inline long double _atold(const char* str)
{
  long double num = 0.0;
  sscanf(str, "%Lf", &num);
  return num;
}

real::real () : _dec(0.0)
{ }

real::real (const real& b) : _dec(b._dec)
{ }

real::real (long double a) : _dec(a)
{ }

void real::set_int64(__int64 b)
{
	_dec = (long double)b;
}

bool real::is_real (const char *s)
{             
  if (s && *s)
  {  
    const long double n = _atold(s);
    if (n == 0.0)
    {
      for(; *s; s++) if (*s != '0' && *s != ' ' && *s != '.')
        return FALSE;
    }    
  }  
  return TRUE;
}               

real::real (const char *s)
{                        
  _dec = (s && *s) ? _atold(s) : 0.0;
}

real& real::operator = (const real& b)
{
  _dec = b._dec;
  return *this;
}

real& real::operator = (long double b)
{
  _dec = b;
  return *this;
}

real& real::operator += (long double b)
{     
  _dec += b;
  return *this;
}

real& real::operator -= (long double b)
{     
  _dec -= b;
  return *this;
}

real& real::operator *= (long double b)
{
  _dec *= b;
  return *this;
}

real& real::operator /= (long double b)
{ 
  CHECK(b != 0.0, "Division by zero");
  _dec /= b;
  return *this;
}


// @doc EXTERNAL

// @mfunc Ritorna il segno del reale                       
//
// @rdesc Ritorna i seguenti valori:
// 
// @flag <lt> 0 | Se il numero e' minore di 0
// @flag = 0 | Se il numero e' uguale a 0
// @flag <gt> 0 | Se il numero e' maggiore di 0
int real::sign () const
{
  const int s = _dec > 0.0 ? +1 : (_dec < 0.0 ? -1 : 0);
  return s;
}

real real::operator - () const
{
  real n(-_dec);
  return n;
}

long real::integer () const
{
  return (long)floorl(_dec);
}

// Certified 91%
// @doc EXTERNAL

// @mfunc Trasforma un reale in stringa
//
// @rdesc Ritorna la stringa nella lunghezza richiesta
const char *real::string (
  int len,        // @parm Lunghezza della stringa (compreso decimali)
  int dec,        // @parm Numero di decimali (default UNDEFINED)
  char pad) const // @parm Carattere di riempimento (default ' ')
  // @parm char * | picture | Formato della stringa

  // @syntax string (int len, int dec, char pad);
  // @syntax string (const char *picture);
  //
  // @comm Nel primo caso ritorna una stringa lunga <p len> con <p dec> decimali e
  //       inserisce nella stringa stessa il carattere <p pad> nel caso la
  //       lunghezza richiesta sia maggiore di quella che risulterebbe per la
  //       completa rappresentazione del reale.
  //       <nl>Nel secondo caso ritorna la stringa con il formato stabilito in
  //       <p picture>.

{          
  TString16 fmt("%");
  if (pad != ' ') fmt << '0';
  if (len != 0) fmt << len;
  if (dec != UNDEFINED) fmt << '.' << dec;
  fmt << "Lf";

  TString& tmp = get_tmp_string();
	char* __string = tmp.get_buffer(len);

  sprintf(__string, fmt, _dec);

  if (len == 0 && dec == UNDEFINED && strchr(__string, '.') != NULL)
  {                                              
    int cut = strlen (__string);
    for (int i = cut-1; i >= 0; i--)
    {
      if (__string[i] == '0')
        cut--;
      else
      {  
        if(__string[i] == '.')
          cut--;
        break;
      }    
    }  
    __string[cut] = '\0';    
  }  
  return __string;
}

// Childish algorithm faster and more accurate than powl(10.0, pow)
HIDDEN void ipow10(int pow, double& m, double& d)
{                         
  m = d = 1.0;
  if (pow > 0)
  {
    for (int i = pow; i > 0; i--)   
    {
      m *= 10.0;
      d *= 0.1;
    }
  }
  else
  {
    for (int i = pow; i < 0; i++)   
    {
      m *= 0.1;
      d *= 10.0;
    }
  }        
}

int real::precision() const
{
  const TFixed_string s(string());
  const int d = s.find('.');
  const int p = d < 0 ? 0 : (s.len()-d-1);
  return p;
}


// @doc EXTERNAL

// @mfunc real& | real | round | Arrotonda al numero di decimali passati
real& real::round (
  int prec)  // @parm Numero di decimali a cui arrotondare il numero (default 0)

  // @comm Nel caso <p prec> sia:    
  //
  // @flag <gt> 0 | Arrotonda al decimale
  // @flag = 0 | Arrotonda all'intero
  // @flag <lt> 0  | Arrotonda al valore passato (es. -3 arrotonda alle mille)
{    
  if (abs(prec) < 20)
  {
    double m, d;
    if (prec != 0)
    {                  
      ipow10(prec, m, d);
      if (prec < 0)
        _dec /= d;
      else  
        _dec *= m;
    }  
    
    if (_dec >= 0.0)
      _dec = floorl(_dec + 0.5);
    else
      _dec = ceill(_dec - 0.5);  
    
    if (prec != 0)
		{
      if (prec < 0)
        _dec *= d;
      else  
        _dec /= m;
		}
  }  
  return *this;
}

real& real::ceil (int prec)
{
  double m, d;
  if (prec != 0)
  {
    ipow10(prec, m, d);
    _dec *= m;
  }
  _dec = ceill(_dec);
  if (prec != 0)
//      _dec *= d;   Risulta stranamente molto impreciso!
    _dec /= m;

  return *this;
}

real& real::floor (int prec)
{
  double m, d;
  if (prec != 0)
  {
    ipow10(prec, m, d);
    _dec *= m;
  }
  _dec = floorl(_dec);
  if (prec != 0)
//      _dec *= d;   Risulta stranamente molto impreciso!
    _dec /= m;

  return *this;
}

real& real::trunc(int prec)
{
  double m, d;
  if (prec != 0)
  {
    ipow10(prec, m, d);
    _dec *= m;
  }
  _dec = floorl(_dec);
  if (prec != 0)
//      _dec *= d;   Risulta stranamente molto impreciso!
    _dec /= m;
  return *this;
}


// @doc EXTERNAL

// @func Scambia il numero reale <p a> con il numero real <p b>
void swap (
  real& a,  // @parm Primo numero da scambiare
  real& b)  // @parm Secondo numero da scambiare

{
  const real n = a;
  a = b;
  b = n;
}           

long double operator%(const real& a, const real& b)
{
  const long double times = floorl(a / b);
  const long double resto = a - b * times;
  return resto;
}

long double sqrt(long double a) 
{  
  return sqrtl(a); 
}

long double sqr(long double a)
{
  return a*a; 
}

long double exp10(long double a) 
{
  return powl(10.0, a);
}

long double pow(long double a, long double b)
{
  return powl(a, b);
}

long double exp(long double a) 
{
  return expl(a);
}

long double log10(long double a)
{
  return log10l(a);
}

long double log(long double a)
{                             
  return logl(a);
}

long double sin(long double a)
{
  return sinl(a);
}

long double cos(long double a)
{
  return cosl(a);
}

long double tan(long double a)
{
  return tanl(a);
}

long double abs(long double a)
{
  return fabsl(a);
}

#else

#include <gm.h>

extern "C"
{
  double pow (double, double);
}                               // Should be #include <math.h>


HIDDEN real __tmp_real;

real::real ()
{
  dzero (ptr ());
  trail();
}

real::real (const real & b)
{
  dcpy (ptr (), b.ptr ());
}

real::real (double a)
{
  dftodr (ptr (), a, 9);        // Round the number (1.0 is NOT 0.999999999)

  trail( );      // Delete Trailing zeroes

}

void real::set_int64(__int64 b)
{
	TString80 s; s.format("%I64d", b);

  atod (ptr (), (char *) (const char *) s);
  trail();
}

void real::trail( )
{
  deltrz (ptr (), ptr () );      // Delete Trailing zeroes
}

bool real::is_real (const char *s)
{
  bool ok = TRUE;
  if (s)
  {
    while (*s == ' ')
      s++;                    // Remove leading spaces before atod
    if (*s)
      ok = atod (__tmp_real.ptr (), (char *) s) != GM_NULL;
  }
  return ok;
}

real::real (const char *s)
{
  if (s)
    while (*s == ' ')
      s++;                      // Remove leading spaces before atod

  if (s && *s)
    atod (ptr (), (char *) s);
  else
    dzero (ptr ());
  
  trail();
}

real& real::operator =(const real & b)
{
  dcpy (ptr (), b.ptr ());
  return *this;
}

real& real::operator =(double a)
{
  const real n (a);
  operator = (n);
  return *this;
}

real& real::operator += (const real & b)
{
  dadd (ptr (), ptr (), b.ptr ());
  trail( );
  return *this;
}

real& real::operator += (double a)
{
  adddfd (ptr (), ptr (), a);
  trail( );
  return *this;
}

real& real::operator -= (const real & b)
{
  dsub (ptr (), ptr (), b.ptr ());
  trail( );
  return *this;
}

real& real::operator *= (const real & b)
{
  dmul (ptr (), ptr (), b.ptr ());
  trail( );
  return *this;
}

real& real::operator /= (const real & b)
{
  const DEC *dst = ddiv (ptr (), ptr (), b.ptr ());

#ifdef DBG
  if (dst == GM_NULL)
  {
    char * s = get_tmp_string().get_buffer(256);
		errname (s, gmec ());
    error_box ("Division error: %s", s);

  }
#endif
  trail( );
  return *this;
}

bool real::is_zero () const
{
  return diszero (ptr ()) != 0;
}

// @doc EXTERNAL

// @mfunc Ritorna il segno del reale                       
//
// @rdesc Ritorna i seguenti valori:
// 
// @flag <lt> 0 | Se il numero e' minore di 0
// @flag = 0 | Se il numero e' uguale a 0
// @flag <gt> 0 | Se il numero e' maggiore di 0
int real::sign () const

{
  return dsign (ptr ());
}

real real::operator - () const
{
  real n;
  dchgs (n.ptr (), ptr ());
  //  n.trail( );
  return n;
}

long real::integer () const
{
  return (long)dtodf(ptr ());
}

// Certified 91%
// @doc EXTERNAL

// @mfunc Trasforma un reale in stringa
//
// @rdesc Ritorna la stringa nella lunghezza richiesta
const char *real::string (
  int len,        // @parm Lunghezza della stringa (compreso decimali)
  int dec,        // @parm Numero di decimali (default UNDEFINED)
  char pad) const // @parm Carattere di riempimento (default ' ')
  // @parm char * | picture | Formato della stringa

  // @syntax string (int len, int dec, char pad);
  // @syntax string (const char *picture);
  //
  // @comm Nel primo caso ritorna una stringa lunga <p len> con <p dec> decimali e
  //       inserisce nella stringa stessa il carattere <p pad> nel caso la
  //       lunghezza richiesta sia maggiore di quella che risulterebbe per la
  //       completa rappresentazione del reale.
  //       <nl>Nel secondo caso ritorna la stringa con il formato stabilito in
  //       <p picture>.

{
  __tmp_real = *this;
  if (dec != UNDEFINED)
    __tmp_real.round (dec);
  else
    __tmp_real.trail();

  char * s = get_tmp_string().get_buffer(80);
	dtoa (s, __tmp_real.ptr ());
  int lun = strlen (s);


  if (lun < len)
  {
    const int delta = len - lun;
    for (int i = lun; i >= 0; i--)
      s[i + delta] = s[i];
    for (i = 0; i < delta; i++)
      s[i] = pad;
  }

  return s;
}

// @doc EXTERNAL

// @func ostream& | operator <lt><lt> | Permette di reindirizzare il numero
//                                      reale per la stampa
//
// @rdesc Ritorna l'utput sul quale e' stata reindirizzata la stampa
ostream & operator << (
  ostream & out,   // @parm Indica l'output sul quale stampare il numero
  const real & a)  // @parm Numero da stampare

{
  return out << a.string ();
}

// @doc EXTERNAL

// @func istream& | operator <gt><gt> | Permette di leggere un numero reale
//
// @rdesc Ritorna l'output sul quale e' stato letto il numero
istream & operator >> (
  istream & in,  // @parm Input da cui leggere il numero
  real & a)      // @parm Indirizzo in cui posizionare il numero

{
  TString80 s;
  in >> s;
  atod (a.ptr (), s.get_buffer());

  a.trail();
  return in;
}


int real::precision() const
{
  return dprec(ptr());
}

// @doc EXTERNAL

// @mfunc real& | real | round | Arrotonda al numero di decimali passati
real & real ::round (
  int prec)  // @parm Numero di decimali a cui arrotondare il numero (default 0)

  // @comm Nel caso <p prec> sia:    
  //
  // @flag <gt> 0 | Arrotonda al decimale
  // @flag = 0 | Arrotonda all'intero
  // @flag <lt> 0  | Arrotonda al valore passato (es. -3 arrotonda alle mille)
{
  if (abs(prec < 20))
  {
    if (prec < 0)
    {
      const double p = ::pow (10.0, -prec);
      divdfd (ptr (), ptr (), p);
      dround (ptr (), ptr (), 0);
      muldfd (ptr (), ptr (), p);
      trail();
    }
    else
      dround (ptr (), ptr (), prec);
  }
  return *this;
}

real & real ::ceil (int prec)
{
  double p = 1.0;
  if (prec != 0)
  {
    p = ::pow (10.0, -prec);
    divdfd (ptr (), ptr (), p);
  }

  DEC integer;
  dint (&integer, ptr ());      // Extract the integer part
  
  if (disgt (ptr (), &integer))   // If positive ...
    addid (ptr (), &integer, 1);  // ... add 1
  else
    dcpy(ptr(), &integer);        // If negative

  if (prec != 0)
    muldfd (ptr (), ptr (), p);
  
  trail();
  return *this;
}

real & real ::floor (int prec)
{
  double p = 1.0;
  if (prec != 0)
  {
    p = ::pow (10.0, -prec);
    divdfd (ptr (), ptr (), p);
  }

  DEC integer;
  dint (&integer, ptr ());      // Extract the integer part

  if (dislt (ptr (), &integer))   // If negative ...
    addid (ptr (), &integer, -1);  // ... subtract 1
  else
    dcpy(ptr(), &integer);        // If positive

  if (prec != 0)
    muldfd (ptr (), ptr (), p);
  
  trail();
  return *this;
}

real & real ::trunc (int prec)
{
  dtrunc (ptr (), ptr (), prec);
  return *this;
}

// @doc EXTERNAL

// @func real | operator + | Somma due numeri reali
//
// @rdesc Ritorna il valore della somma
real operator + (
  const real & a,  // @parm Primo addendo da sommare
  const real & b)  // @parm Secondo addendo da sommare

  // @syntax operator +(const real &a, const real &b);
  // @syntax operator +(double a, const real &b);
  // @syntax operator +(const real &a, double b);

{
  dadd (__tmp_real.ptr (), a.ptr (), b.ptr ());
  return __tmp_real;
}

real operator + (double a, const real & b)

{
  __tmp_real = a;
  return __tmp_real += b;
}

real operator + (const real & a, double b)

{
  __tmp_real = a;
  return __tmp_real += b;
}

// @doc EXTERNAL

// @func real | operator - | Sottrae due numeri reali
//
// @rdesc Ritorna il valore della sottrazione
real operator - (
  const real & a,  // @parm Primo addendo da sottrarre
  const real & b)  // @parm Secondo addendo da sottrarre

  // @syntax operator -(const real &a, const real &b);
  // @syntax operator -(double a, const real &b);
  // @syntax operator -(const real &a, double b);
{
  dsub (__tmp_real.ptr (), a.ptr (), b.ptr ());
  __tmp_real.trail();
  return __tmp_real;
}

real operator - (double a, const real & b)
{
  __tmp_real = a;
  dsub (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ());
  __tmp_real.trail( );
  return __tmp_real;
}

real operator - (const real & a, double b)
{
  __tmp_real = -b;
  __tmp_real += a;    
  __tmp_real.trail();
  return __tmp_real;
}

// @doc EXTERNAL

// @func real | operator * | Moltiplica due numeri reali
//
// @rdesc Ritorna il valore della moltiplicazione
real operator *(
  const real & a,  // @parm Primo numero da moltiplicare
  const real & b)  // @parm Secondo numero da moltiplicare

  // @syntax operator *(const real &a, const real &b);
  // @syntax operator *(double a, const real &b);
  // @syntax operator *(const real &a, double b);

{
  dmul (__tmp_real.ptr (), a.ptr (), b.ptr ());
  __tmp_real.trail( );
  return __tmp_real;
}

real operator *(double a, const real & b)
{
  __tmp_real = a;
  dmul(__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ());
  __tmp_real.trail( );
  return __tmp_real;
}

real operator *(const real & a, double b)
{
  __tmp_real = b;
  dmul (__tmp_real.ptr (), a.ptr (), __tmp_real.ptr ());
  __tmp_real.trail( );
  return __tmp_real;
}

// @doc EXTERNAL

// @func real | operator / | Divide due numeri reali
//
// @rdesc Ritorna il valore della divisione
real operator / (
  const real & a,  // @parm Primo numero da dividere
  const real & b)  // @parm Secondo numero da dividere

  // @syntax operator /(const real &a, const real &b);
  // @syntax operator /(double a, const real &b);
  // @syntax operator /(const real &a, double b);
{
  ddiv (__tmp_real.ptr (), a.ptr (), b.ptr ());
  __tmp_real.trail( );
  return __tmp_real;
}

real operator / (double a, const real & b)
{
  __tmp_real = a;
  ddiv (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ());
  __tmp_real.trail( );
  return __tmp_real;
}

real operator / (const real & a, double b)
{
  __tmp_real = b;
  ddiv (__tmp_real.ptr (), a.ptr (), __tmp_real.ptr ());
  __tmp_real.trail( );
  return __tmp_real;
}

// @doc EXTERNAL

// @func bool | operator <gt> | Controlla se un reale e' maggiore di un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' maggiore di <p b>
// @flag FALSE | Se <p a> e' non maggiore di <p b>
bool operator > (
  const real & a,  // @parm Primo numero da conforntare
  const real & b)  // @parm Secondo numero da confrontare

  // @syntax operator <gt> (const real &a, const real &b);
  // @syntax operator <gt> (double a, const real &b);
{
  return disgt (a.ptr (), b.ptr ()) != 0;
}

bool operator > (double a, const real & b)
{
  // dftod(__tmp_real.ptr(), a);
  // return disgt(__tmp_real.ptr(), b.ptr());
  const double n = dtodf (b.ptr ());
  return a > n;
}

// @doc EXTERNAL

// @func bool | operator <lt> | Controlla se un reale e' minore di un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' minore di <p b>
// @flag FALSE | Se <p a> e' non minore di <p b>
bool operator < (
  const real & a,  // @parm Primo numero da conforntare
  const real & b)  // @parm Secondo numero da confrontare

  // @syntax operator <lt> (const real &a, const real &b);
  // @syntax operator <lt> (double a, const real &b);

{
  return dislt (a.ptr (), b.ptr ()) != 0;
}

bool operator < (double a, const real & b)

{
  // dftod(__tmp_real.ptr(), a);
  // return dislt(__tmp_real.ptr(), b.ptr());
  const double n = dtodf (b.ptr ());
  return a < n;
}

// @doc EXTERNAL

// @func bool | operator <gt>= | Controlla se un reale e' maggiore o uguale ad
//                               un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' maggiore o uguale a <p b>
// @flag FALSE | Se <p a> e' minore di <p b>
bool operator >= (
  const real & a,  // @parm Primo numero da conforntare
  const real & b)  // @parm Secondo numero da confrontare

  // @syntax operator <gt>= (const real &a, const real &b);
  // @syntax operator <gt>= (double a, const real &b);

{
  return disge (a.ptr (), b.ptr ()) != 0;
}

bool operator >= (double a, const real & b)

{
  // dftod(__tmp_real.ptr(), a);
  // return disge(__tmp_real.ptr(), b.ptr());
  const double n = dtodf (b.ptr ());
  return a >= n;
}

// @doc EXTERNAL

// @func bool | operator <lt>= | Controlla se un reale e' minore o uguale ad
//                               un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' minore o uguale a <p b>
// @flag FALSE | Se <p a> e' maggiore di <p b>
bool operator <= (
  const real & a,  // @parm Primo numero da conforntare
  const real & b)  // @parm Secondo numero da confrontare

  // @syntax operator <lt>= (const real &a, const real &b);
  // @syntax operator <lt>= (double a, const real &b);
{
  return disle (a.ptr (), b.ptr ()) != 0;
}

bool operator <= (double a, const real & b)

{
  // dftod(__tmp_real.ptr(), a);
  // return disle(__tmp_real.ptr(), b.ptr());
  const double n = dtodf (b.ptr ());
  return a <= n;
}

// @doc EXTERNAL

// @func bool | operator == | Controlla se un reale e' uguale ad un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' uguale a <p b>
// @flag FALSE | Se <p a> non e' uguale a <p b>
bool operator == (
  const real & a,  // @parm Primo numero da conforntare
  const real & b)  // @parm Secondo numero da confrontare

  // @syntax operator == (const real &a, const real &b);
  // @syntax operator == (double a, const real &b);
{
  return diseq (a.ptr (), b.ptr ()) != 0;
}

bool operator == (double a, const real & b)
{
  const double n = dtodf (b.ptr ());
  return a == n;
}

// @doc EXTERNAL

// @func bool | operator != | Controlla se 2 reali dono diversi
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' diverso da <p b>
// @flag FALSE | Se <p a> e' uguale a <p b>
bool operator != (
  const real & a,  // @parm Primo numero da conforntare
  const real & b)  // @parm Secondo numero da confrontare

  // @syntax operator != (const real &a, const real &b);
  // @syntax operator != (double a, const real &b);
{
  return !diseq (a.ptr (), b.ptr ());
}

bool operator != (double a, const real & b)

{
  const double n = dtodf (b.ptr ());
  return a != n;
}

// @doc EXTERNAL

// @func real | operator % | Ritorna il modulo di due numeri
//
// @rdesc Ritorna il resto della divisione tra due numeri
real operator % (
  const real& a,    // @parm Primo membro della divisione
  const real& b)    // @parm Secondo membro della divisione
  
// @syntax long double operator%(const real& a, const real& b)
// @syntax real operator % (const real& a, const real& b)

{                                      
  const long l = b.integer();
  dmodl (__tmp_real.ptr (), a.ptr (), l);
  return __tmp_real;
}

// @doc EXTERNAL

// @func Scambia il numero reale <p a> con il numero real <p b>
void swap (
  real & a,  // @parm Primo numero da scambiare
  real & b)  // @parm Secondo numero da scambiare

{
  SwapDecimal (a.ptr (), b.ptr ());
}

// @doc EXTERNAL

// @func Ritorna il numero reale piu' piccolo tra <p a> e <p b>
const real& fnc_min (
  const real & a,  // @parm Primo numero da confrontare
  const real & b)  // @parm Secondo numero da confrontare
                   // @parm long double | a | Primo numero da confrontare
                   // @parm long double | b | Secondo numero da confrontare
  
// @syntax const real& fnc_min (const real & a, const real & b)
// @syntax inline long double fnc_min(long double a, long double b) 
  

{
  dmin (__tmp_real.ptr (), a.ptr (), b.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Ritorna il numero reale piu' grande tra <p a> e <p b>
const real& fnc_max (
  const real & a,  // @parm Primo numero da confrontare
  const real & b)  // @parm Secondo numero da confrontare
             // @parm long double | a | Primo numero da confrontare
                   // @parm long double | b | Secondo numero da confrontare

// @syntax const real& fnc_max (const real & a, const real & b)
// @syntax inline long double fnc_max(long double a, long double b) 

{
  dmax (__tmp_real.ptr (), a.ptr (), b.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Ritorna la radice quadrata del numero
real sqrt (
  const real & a)  // @parm Numero del quale calcolare la radice
             // @parm long double | a | Numero del quale calcolare la radice
  
// @syntax real sqrt (const real)
// @syntax long double sqrt(long double)

{
  dsqrt (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Ritorna il quadarato del numero
real sqr (
  const real & a)  // @parm Numero del quale calcolare il quadrato
                   // @parm long double | a | Numero del quale calcolare il quadrato
                   
// @syntax real sqr (const real)
// @syntax long double sqr(long double)
                   
{
  dmul (__tmp_real.ptr (), a.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcola 10 a potenza <p a>
real exp10 (
     const real & a)  // @parm Esponente al quale elevare
                      // @parm long double | a | Esponente al quale elevare
                      
// @syntax real exp10 (const real)
// @syntax long double exp10 (long double)
                      
                      
{
  dalog (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcola l'elevamento a potenza <p b> del numero <p a>
real pow (
     const real & a, // @parm Numero da elevare a potenza
     const real & b) // @parm Esponente
             // @parm long double | a | Numero da elevare a potenza
             // @parm long double | b | Esponente

// @syntax real pow (const real & a, const real & b)             
// @syntax long double pow(long double a, long double b)

{
  dpow (__tmp_real.ptr (), a.ptr (), b.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcola e (nepero) elevato ad <p a>
real exp (
     const real & a) // @parm Esponente
             // @parm long double | a | Esponente

// @syntax real exp (const real & a)             
// @syntax long double exp(long double a)

{
  dexp (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcola il logaritmo in base 10 del numero
real log10 (
  const real & a)  // @parm Numero del quale calcolare il logaritmo
             // @parm long double | a | Numero del quale calcolare il logaritmo

// @syntax real log10 (const real & a)             
// @syntax long double log10(long double a)            

{
  dlog (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcoa il logaritmo naturale (base e) del numero
real log (
  const real & a)  // @parm Numero del quale calcolare il logaritmo
                   // @parm long double | a | Numero del quale calcolare il logaritmo
                   
// @syntax real log (const real & a)
// @syntax long double log(long double a)

{
  dln (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcola il seno dell'angolo
real sin (
  const real & a)  // @parm Angolo passato in radianti 
             // @parm long double | a | Angolo passato in radianti 
             
// @syntax real sin (const real & a)
// @syntax long double sin (long double a)

{
  dsin (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcola il coseno dell'angolo
real cos (
  const real & a)  // @parm Angolo passato in radianti
                   // @parm long double | a | Angolo passato in radianti 
                   
// @syntax real cos (const real & a)
// @syntax long double cos (long double a)
                   

{
  dcos (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Calcola la tangente dell'angolo
real tan (
  const real & a)  // @parm Angolo passato in radianti 
                   // @parm long double | a | Angolo passato in radianti 
                   
// @syntax real tan (const real & a)
// @syntax long double tan (long double a)
                   

{
  dtan (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

// @doc EXTERNAL

// @func Ritorna il valore assoluto di un numero
real abs (
  const real & a)  // @parm Numero del quale si vuole conoscere il valore assoluto
                   // @parm long double | a | Numero del quale si vuole conoscere il valore assoluto
                   
// @syntax real abs (const real & a)
// @syntax long double abs(long double a)

{
  dabs (__tmp_real.ptr (), a.ptr ());
  return __tmp_real;
}

#endif

// Funzioni comuni dei due real

TObject* real::dup () const
{
  return new real(*this);
}

const char *real::eng2ita (char *s)
{
  if (s)
  {
    char *dot = strchr (s, '.');
    if (dot)
      *dot = ',';
  }
  return s;
}

// Elimina gli spazi ed i punti, converte le virgole in punti
const char *real::ita2eng (const char *s)
{
  TString& tmp = get_tmp_string();
	char* __string = tmp.get_buffer(strlen(s));

  int j = 0;
  if (s)
    for (int i = 0; s[i]; i++)
    {
      switch (s[i])
      {
      case ' ':
      case '.':
        break;
      case ',':
        __string[j++] = '.';
        break;
      default:
        __string[j++] = s[i];
        break;
      }
    }
  __string[j] = '\0';
  return __string;
}           

bool real::is_null(const char *s)
{  
  bool z = TRUE;
  if (s != NULL) for (const char* n = s; *n; n++)
  {
    if (strchr("123456789", *n) != NULL)
    {
      z = FALSE;
      break;
    }
    if (strchr(" ,-.0", *n) == NULL)
      break;
  }
  return z;
}

bool real::is_natural (const char *s)
{
  bool ok = s && *s != '\0';
  if (ok)
  {
    while (*s == ' ')
      s++;                    // Remove leading spaces before

    if (*s)
    {
      while (isdigit(*s))
        s++;
      ok = *s == '\0';
    }
    else 
      ok = FALSE;
  }
  return ok;
}

// Certified 75%
const char* real::literals() const
{
  const char *primi20[] =
  {"", "uno", "due", "tre", "quattro",
   "cinque", "sei", "sette", "otto",
   "nove", "dieci", "undici", "dodici",
   "tredici", "quattordici", "quindici", "sedici",
   "diciassette", "diciotto", "diciannove"};
  const char *decine[] =
  {"zero", "dieci", "venti", "trenta", "quaranta",
   "cinquanta", "sessanta", "settanta", "ottanta",
   "novanta", "cento"};
  const char *uni[] =
  {"uno", "mille", "unmilione", "unmiliardo"};

  const char *potenze[] =
  {"", "mila", "milioni", "miliardi"};

  real tmp_real = *this;
  tmp_real.trunc();
  
  TString r (tmp_real.string (0, 0));
  const bool negativo = r[0] == '-';
  if (negativo)
    r.ltrim (1);

  TString& risultato = get_tmp_string(128);
  risultato.cut (0);

  TString centinaia;

  for (int migliaia = 0;; migliaia++)
  {
    int v = r.len () - 3;
    if (v < -2)
      break;

    if (v < 0)
      v = 0;
    const int val = atoi (&r[v]);
    r.cut (v);          // Elimina ultimi 3 caratteri

    v = val;
    if (v >= 100)
    {
      const int c = v / 100;
      if (c > 1)
        centinaia = primi20[c];
      else
        centinaia.cut(0);
      v -= c * 100;
      centinaia << "cento";
    } else centinaia.cut(0);
    const int d = v / 10;
    if (d > 1)
    {
      if (d == 8 && centinaia.right(1)[0] == 'o')
        centinaia.rtrim(1);
      centinaia << decine[d];
      v -= d * 10;
    }

    if (val > 0)
    {
      if (v != 1)
      {         
        if (v == 8) 
          centinaia.rtrim(1);
        centinaia << primi20[v] << potenze[migliaia];
      }
      else if (val > 1)
      {
        if (d > 1) 
          centinaia.rtrim(1);
        centinaia << "un" << (migliaia ? potenze[migliaia] : "o");
      }
      else
        centinaia = uni[migliaia];
    }

    risultato.insert(centinaia, 0);
  }
  
  if (tmp_real != *this)  // Ci sono dei decimali!
  {
    TString80 res = risultato;
    const real tmp_dec = abs(*this - tmp_real);
    TString80 str = tmp_dec.string();
    str.ltrim(2); str.cut(3);
    res << '/' << str;
    risultato = res;
  }

  if (negativo)
    risultato.insert ("meno", 0);
  return risultato;
}

// Certified 75%
const char* real::points (int dec) const
{
  const char *str = stringa (0, dec);
  const int neg = (*str == '-') ? 1 : 0;
  TFixed_string n ((char *)str, 64);
  int i;

  int dot = n.find (',');
  if (dot < 0)
    dot = n.len ();

  if (dec > 0)
  {
    if (n[dot] == '\0')
      n << ',';
    const int d = strlen (str + dot + 1);       // Decimals already there

    if (d <= dec)
      for (i = d; i < dec; i++)
        n << '0';
    else
      n.cut (dot + dec + 1);
  }

  for (i = dot - 3; i > neg; i -= 3)
    n.insert (".", i);

  return str;
}

HIDDEN int get_picture_decimals (const TString& picture, char& decsep)
{
  int decimali = 0; 
  int virgola = -1;
  
  if (decsep == ',')
  {
    int firstcomma = -1, lastcomma = -1, firstdot = -1, lastdot = -1;
    for (int i = 0; picture[i]; i++)
    {
      if (picture[i] == ',')
      { 
        if (firstcomma < 0) firstcomma = i;
        lastcomma = i;  
      }
      else if (picture[i] == '.')
      { 
        if (firstdot < 0) firstdot = i;
        lastdot = i;  
      }
    }
    if (lastcomma >= 0 && lastdot >= 0)
    {
      virgola = lastcomma >  lastdot ? lastcomma : lastdot;
      decsep = picture[virgola];
    }
    else
      if (lastcomma >= 0) virgola = lastcomma;
  }
  else virgola = picture.find('.');   
  
  if (virgola >= 0)
  {
    const int len = picture.len ();
    for (int i = virgola + 1; i < len; i++)
      if (strchr ("#@^", picture[i]))
        decimali++;
  }
  return decimali;
}           

const char* real::string(const char *picture) const
{
  if (*picture == '\0')
    return string ();
  if (*picture == '.')
    return points (atoi (picture + 1));
  if (stricmp (picture, "LETTERE") == 0)
    return literals ();

  TString v (string());
  TString& f = get_tmp_string();
	f = picture;                                       
  
	char decsep =  ',';                            // Separatore dei decimali
  if (f[f.len() - 1] == 'E')
  { 
    f.rtrim(1);
    decsep = '.';
  }

  // Calcola il numero di decimali voluti ed eventualmente 
  // determina il vero separatore dei decimali
  const int voluti = get_picture_decimals (f, decsep);
  const char migsep = decsep == '.' ? ',' : '.'; // Separatore delle migliaia
  
  const int virgola = v.find ('.'); // v e' la nostra cifra, certamente in english format
  int decimali = (virgola >= 0) ? v.len () - virgola - 1 : 0;

  for (; voluti > decimali; decimali++)
    v << '@';
  if (voluti < decimali)
    v.cut (virgola + voluti + (voluti > 0));

  int j = v.len () - 1;
  bool sign(FALSE);
  for (int i = f.len () - 1; i >= 0 && j >= 0; i--)
  {
    char &z = f[i];
    if (strchr ("#@^", z))
    {
      char c = v[j--];
      if (j >= 0 && v[j] == '.')
        j--;
      if (z == '^')
        c = ' ';
      else
      {
        if (c == '@')
          c = (z == '@') ? '0' : ' ';
        else
          if (c == '-')
          {
            if (z == '@') // Altrimenti -10 con picture @@@@@ diventa "00-10"
            {
              if (f[i+1] == migsep)  
                f[i+1] = '0';
              sign=TRUE; // posticipa l'append del segno
              i++;
              c=z; 
            } else {
              if (f[i+1] == migsep )   // Altrimenti -100 diventa -.100
              {
                f[i+1] = '-';
                c = ' ';   //OK
              } 
            } 
          }
      }

      z = c;
    }   
  }
  for (int i2=0; i2 <= i; i2++)
    if (f[i2] == '@')
    {
      if (sign)
      {
        f[i2] = '-'; // add sign in first pos
        sign=FALSE;
      }
      else
        f[i2] = '0';
    }
  for (; i >=0 ; i--)
    switch (f[i])
    {
    case '#':
    case '^':
    case '.':
    case ',':
      f[i] = ' ';
      break;
    default:
      break;
    }
  return f;
}                 

// Certified 99%
const char* real::stringa (int len, int dec, char pad) const
{
  char* str = (char*)string(len, dec, pad);
  if (dec > 0 || dec == UNDEFINED)
    eng2ita (str);
  return str;
}

void real::print_on(ostream& out) const
{
  out << string();
}

///////////////////////////////////////////////////////////
// Distrib
// Oggetto per dividere un real in varie sue percentuali
// in modo che la loro somma dia sempre il real di partenza
// /////////////////////////////////////////////////////////

void TDistrib::add(real slice)
{
  if (slice > real (1.0))
    slice /= 100.0;
  CHECK (!_ready, "TDistrib: les jeux sont faits");
  _slices.add (slice);
}

real TDistrib::get ()
{
  _ready = TRUE;
  CHECK (_current < _slices.items(), "TDistrib: too many gets");
  real r = _tot * ((real &) _slices[_current++]);
  r.round (_decs);
  if (r > _tot - _prog)
  {
    r = _tot - _prog; _prog = _tot;
  }
  else
    _prog += r;
  return r;
}

// @doc EXTERNAL

// @mfunc Inizializza l'oggetto
void TDistrib::init (
  const real & r,  // @parm Importo da dividere
  bool zap)        // @parm Permette di cancellare le percenutali immesse (default FALSE)
  
  // @comm Se <p zap> e' vero cancella tutte le percentuali immesse, altrimenti
  //       cambia solo il totale
{
  _current = 0; _prog = 0;
  _tot = r; _ready = FALSE;
  if (zap) _slices.destroy();
}

///////////////////////////////////////////////////////////
// Generic_distrib
// Oggetto per dividere un real in parti prefissate 
// in modo che la loro somma dia sempre il real di partenza
// /////////////////////////////////////////////////////////


void TGeneric_distrib::add(real slice)
{
  CHECK (!_ready, "TGeneric_distrib: les jeux sont faits");
  _totslices += slice;
  _slices.add (slice);
}

real TGeneric_distrib::get ()
{
  _ready = TRUE;
  CHECK (_current < _slices.items(), "TGeneric_distrib: too many gets");
  real & currslice = (real &) _slices[_current++];
  real r = currslice;
  if (_tot != _totslices)
  {
    if (_tot < 1E9 && currslice < 1E9)
      r = (_tot * currslice) / _totslices;
    else
      r *= (_tot / _totslices);
  }
  r.round (_decs);
  _tot -= r;
  _totslices -= currslice;
  return r;
}

// @doc EXTERNAL

// @mfunc Inizializza l'oggetto
void TGeneric_distrib::init (
  const real & r,  // @parm Importo da dividere
  bool zap)        // @parm Permette di cancellare le percenutali immesse
  //       (default FALSE)

  // @comm Se <p zap> e' vero cancella tutte le percentuali immesse, altrimenti
  //       cambia solo il totale
{
  _current = 0; _totslices = 0;
  _tot = r; _ready = FALSE;
  if (zap) _slices.destroy();
  else                                 
  {
    const int items = _slices.items();
    for (int i = 0; i < items; i++)
      _totslices += (real &) _slices[i];
  }
}

///////////////////////////////////////////////////////////
// Importo
///////////////////////////////////////////////////////////

const TImporto& TImporto::add_to(TToken_string& s, int pos) const
{
  const bool dare = sezione() == 'D';
  const char* v = valore().string();
  s.add(dare ? v : "", pos);
  s.add(dare ? "" : v, pos+1);
  return *this;
}

// Cerified 99%
const TImporto& TImporto::operator =(TToken_string& sv)
{
  _valore = real(sv.get(0));
  if (_valore.is_zero())
  {
    _valore = real(sv.get());
    _sezione = 'A';
  }
  else
    _sezione = 'D';
  return *this;
}


const TImporto& TImporto::set(char s, const real& v)
{
  if (s <= ' ' && v.is_zero())   // Accetta sezioni nulle per importi nulli
    s = 'D';
  CHECKD(s == 'D' || s == 'A', "Sezione errata per importo: codice ", (int)s);
  _sezione = s; _valore = v;
  return *this;
}


const TImporto& TImporto::operator += (const TImporto& i)
{
  if (_valore.is_zero())
    _sezione = i._sezione;

  if (_sezione == i._sezione)
    _valore += i._valore;
  else
    _valore -= i._valore;
  return *this;
}


const TImporto& TImporto::operator -= (const TImporto& i)
{
  if (_valore.is_zero())
    _sezione = i._sezione;

  if (_sezione == i._sezione)
    _valore -= i._valore;
  else
    _valore += i._valore;
  return *this;
}


const TImporto& TImporto::swap_section()
{
  _sezione = (_sezione == 'D') ? 'A' : 'D';
  return *this;
}


// @doc EXTERNAL

// @mfunc Normalizza il segno o la sezione in base al parametro s
const TImporto& TImporto::normalize(
      char s) // @parm Tipo di normalizzazione da effettuare:
            //
            // @flag A | Forza la sezione Avere
            // @flag D | Forza la sezione Dare
        // @flag <gt>0 | Forza il segno negativo
        // @flag <lt>=0 | Forza il segno positivo

{   
  bool ex = FALSE;
  switch (s)
  {
  case 'A':
  case 'D':
    ex = s != _sezione;
    break;
  default:
    if (s < 0)
      ex = _valore.sign() > 0;
    else  
      ex = _valore.sign() < 0;
    break;
  }  
  if (ex)
  {
    _valore = -_valore;
    swap_section();
  }
  return *this;
}


int TImporto::compare(const TSortable& s) const
{
  const TImporto& i = (const TImporto&)s;
  const real v = i.sezione() == sezione() ? i.valore() : -i.valore();
  const real d = valore() - v;
  const int res = d.sign();
  return res;
}

bool TImporto::is_zero() const
{ 
#ifdef __LONGDOUBLE__
  return fabsl(_valore) < 0.00001;
#else
  return _valore.is_zero(); 
#endif  
}