campo-sirio/include/real.cpp

789 lines
13 KiB
C++
Raw Normal View History

#include <ctype.h>
#include <stdlib.h>
#include <gm.h>
extern "C" { double pow(double, double); } // Should be #include <math.h>
#include <strings.h>
#include <real.h>
HIDDEN real __tmp_real;
HIDDEN char __string[80];
const real ZERO(0.0);
real::real()
{ dzero(ptr()); }
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)
deltrz(ptr(), ptr()); // Delete Trailing zeroes
}
char* real::eng2ita(char* s)
{
if (s)
{
char* dot = strchr(s, '.');
if (dot) *dot = ',';
}
return s;
}
char* real::ita2eng(const char* 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_real(const char* s)
{
bool ok = FALSE;
if (s)
{
while(*s == ' ') s++; // Remove leading spaces before atod
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());
}
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());
return *this;
}
real& real::operator +=(double a)
{
__tmp_real = *this;
adddfd(ptr(), __tmp_real.ptr(), a);
return *this;
}
real& real::operator -=(const real& b)
{
__tmp_real = *this;
dsub( ptr(), __tmp_real.ptr(), b.ptr());
return *this;
}
real& real::operator *=(const real& b)
{
dmul( ptr(), ptr(), b.ptr());
return *this;
}
real& real::operator /=(const real& b)
{
const DEC* dst = ddiv(ptr(), ptr(), b.ptr());
#ifdef DBG
if (dst == GM_NULL)
{
errname(__string, gmec());
error_box("Division error: %s", __string);
}
#endif
return *this;
}
TObject* real::dup() const
{ return new real(*this); }
bool real::is_zero() const
{
return diszero(ptr());
}
int real::sign() const
{ return dsign(ptr()); }
real real::operator -() const
{
real n;
dchgs(n.ptr(), ptr());
return n;
}
int real::integer() const
{ return dtoi(ptr()); }
// Certified 91%
char* real::string(int len, int dec, char pad) const
{
__tmp_real = *this;
if (dec != UNDEFINED) __tmp_real.round(dec);
else deltrz(__tmp_real.ptr(), __tmp_real.ptr());
// if (len == 0)
dtoa(__string, __tmp_real.ptr());
/*
else
{
char f[16];
if (dec == UNDEFINED) sprintf(f, "%%%dt", len);
else
sprintf(f, "%%%d.%dt", len, dec);
dsprintf(__string, f, __tmp_real.ptr());
}
if (dec <= 0 || dec == UNDEFINED) // Toglie una eventuale parte decimale .00
{
if (dot)
{
for (const char* z = dot + 1; *z; z++)
if (*z != '0') break;
if (!*z) *dot = '\0';
}
}
*/
int lun = strlen(__string);
/*
char* dot = strchr(__string, '.');
int d = dot ? strlen(dot+1) : 0; // Decimals already there
if (d < dec)
{
if (dot == NULL) __string[lun++] = '.');
for (;d < dec; d++) __string[lun++] = '0';
__string[lun] = '\0';
} else
if (dec >= 0 && d > dec)
{
*(dot+dec+(dec>0)) = '\0';
lun = strlen(__string);
}
*/
if (lun < len)
{
const int delta = len - lun;
for (int i = lun; i >= 0; i--)
__string[i+delta] = __string[i];
for (i = 0; i < delta; i++) __string[i] = pad;
}
return __string;
}
// Certified 99%
char* real::stringa(int len, int dec, char pad) const
{
string(len, dec, pad);
if (dec > 0 || dec == UNDEFINED)
eng2ita(__string);
return __string;
}
// Certified 75%
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" };
__tmp_real = *this;
__tmp_real.round(0);
TString r(__tmp_real.string(0, 0));
const bool negativo = r[0] == '-';
if (negativo) r.ltrim(1);
TFixed_string risultato(__string, 80);
risultato.cut(0);
TString centinaia(16);
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";
}
const int d = v/10;
if (d > 1)
{
centinaia << decine[d];
v -= d*10;
}
if (v != 1)
{
centinaia << primi20[v] << potenze[migliaia];
} else
if (val > 1)
{
if (d > 1) centinaia.cut(centinaia.len()-1);
centinaia << "un" << (migliaia ? potenze[migliaia] : "o");
} else centinaia = uni[migliaia];
risultato.insert(centinaia, 0);
}
if (negativo) risultato.insert("meno", 0);
return __string;
}
// Certified 75%
char* real::points(int dec) const
{
const char* str = stringa();
const int neg = (*str == '-') ? 1 : 0;
TFixed_string n((char*)str, 24);
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 __string;
}
HIDDEN int get_picture_decimals(const TString& picture)
{
int decimali = 0;
const int 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;
}
char* real::string(const char* picture) const
{
if (*picture == '\0') return string();
if (*picture == '.') return points(atoi(picture+1));
if (strcmp(picture, "LETTERE") == 0) return literals();
TString v(string());
TString f(picture);
const int voluti = get_picture_decimals(f);
const int virgola = v.find('.');
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;
for (int i = f.len()-1; i >= 0 && j >= 0; i--)
{
char& z = f[i];
if (strchr("#@~", z))
{
char c = v[j--];
if (v[j] == '.') j--;
if (z == '~') c = ' '; else
if (c == '@') c = (z == '@') ? '0' : ' ';
z = c;
}
}
for (; i >= 0; i--)
switch (f[i])
{
case '#':
case '~':
case '.': f[i] = ' '; break;
case '@': f[i] = '0'; break;
default :break;
}
return strcpy(__string, f);
}
ostream& operator <<(ostream& out, const real& a)
{
return out << a.string();
}
istream& operator >>(istream& in, real& a)
{
in >> __string;
atod(a.ptr(), __string);
return in;
}
int real::precision()
{
return dprec(ptr());
}
real& real::round(int prec)
{
if (prec < 0)
{
const double p = ::pow(10.0, -prec);
divdfd(ptr(), ptr(), p);
dround(ptr(), ptr(), 0);
muldfd(ptr(), ptr(), p);
}
else
dround(ptr(), ptr(), prec);
return *this;
}
real& real::ceil(int prec)
{
double p = 1.0;
if (prec)
{
p = ::pow(10.0, -prec);
divdfd(ptr(), ptr(), p);
}
DEC integer; dint(&integer, ptr()); // Extract the integer part
if (disgt(ptr(), &integer)) // If different ...
addid(ptr(), &integer, 1); // add 1
if (prec)
muldfd(ptr(), ptr(), p);
return *this;
}
real& real::trunc(int prec)
{
dtrunc(ptr(), ptr(), prec);
return *this;
}
real operator +(const real& a, const real& 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;
}
real operator -(const real& a, const real& b)
{
dsub(__tmp_real.ptr(), a.ptr(), b.ptr());
return __tmp_real;
}
real operator -(double a, const real& b)
{
__tmp_real = a;
dsub(__tmp_real.ptr(), __tmp_real.ptr(), b.ptr());
return __tmp_real;
}
real operator -(const real& a, double b)
{
__tmp_real = b;
return __tmp_real -= a;
}
real operator *(const real& a, const real& b)
{
dmul(__tmp_real.ptr(), a.ptr(), b.ptr());
return __tmp_real;
}
real operator *(double a, const real& b)
{
muldfd(__tmp_real.ptr(), b.ptr(), a);
return __tmp_real;
}
real operator *(const real& a, double b)
{
muldfd(__tmp_real.ptr(), a.ptr(), b);
return __tmp_real;
}
real operator /(const real& a, const real& b)
{
ddiv(__tmp_real.ptr(), a.ptr(), b.ptr());
return __tmp_real;
}
real operator /(double a, const real& b)
{
__tmp_real = a;
ddiv(__tmp_real.ptr(), __tmp_real.ptr(), b.ptr());
return __tmp_real;
}
real operator /(const real& a, double b)
{
__tmp_real = b;
ddiv(__tmp_real.ptr(), a.ptr(), __tmp_real.ptr());
return __tmp_real;
}
bool operator >(const real& a, const real& b)
{
return disgt(a.ptr(), b.ptr());
}
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;
}
bool operator <(const real& a, const real& b)
{
return dislt(a.ptr(), b.ptr());
}
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;
}
bool operator >=(const real& a, const real& b)
{
return disge(a.ptr(), b.ptr());
}
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;
}
bool operator <=(const real& a, const real& b)
{
return disle(a.ptr(), b.ptr());
}
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;
}
bool operator ==(const real& 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;
}
bool operator !=(const real& 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;
}
real operator %(const real& a, const long b)
{
dmodl(__tmp_real.ptr(), a.ptr(), b);
return __tmp_real;
}
void swap(real& a, real& b)
{
SwapDecimal(a.ptr(), b.ptr());
}
real fnc_min(const real& a, const real& b)
{
dmin(__tmp_real.ptr(), a.ptr(), b.ptr());
return __tmp_real;
}
real fnc_max(const real& a, const real& b)
{
dmax(__tmp_real.ptr(), a.ptr(), b.ptr());
return __tmp_real;
}
real sqrt(const real& a)
{
dsqrt(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real sqr(const real& a)
{
dmul(__tmp_real.ptr(), a.ptr(), a.ptr());
return __tmp_real;
}
real exp10(const real& a)
{
dalog(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real pow(const real& a, const real& b)
{
dpow(__tmp_real.ptr(), a.ptr(), b.ptr());
return __tmp_real;
}
real exp(const real& a)
{
dexp(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real log10(const real& a)
{
dlog(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real log(const real& a)
{
dln(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real sin(const real& a)
{
dsin(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real cos(const real& a)
{
dcos(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real tan(const real& a)
{
dtan(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
real abs(const real& a)
{
dabs(__tmp_real.ptr(), a.ptr());
return __tmp_real;
}
///////////////////////////////////////////////////////////
// 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;
}
void TDistrib::init(const real& r)
{
_current = 0; _prog = 0;
_tot = r; _ready = FALSE;
}