#include <Number.h>
Public Types | |
enum | Type { Fixed = 0, Scientific, Weeks, Days, Hours, Minutes, Seconds } |
Static Public Member Functions | |
static QList< int > | divisors (int n) |
static unsigned char | fromBinaryCodedDecimal (unsigned char bcd) |
static unsigned short | fromBinaryCodedDecimal (unsigned short bcd) |
static unsigned int | fromBinaryCodedDecimal (unsigned int bcd) |
static unsigned int | nextPowerOfTwo (unsigned int val) |
static QString | secondsToTime (double sec, Number::Type type=Number::Weeks, int numberPrecision=-1) |
static double | sign (double val) |
static int | sign (int val) |
static double | timeToSeconds (const QString &str) |
static unsigned char | toBinaryCodedDecimal (unsigned char val) |
static unsigned short | toBinaryCodedDecimal (unsigned short val) |
static unsigned int | toBinaryCodedDecimal (unsigned int val) |
static double | toDouble (const QString &str, Type t, bool *ok=0) |
static double | toDouble (float f) |
static double | toDouble (const Complex &c) |
static double | toDouble (double a) |
static QString | toString (double val, Type t, int precision) |
static QString | toString (double val, int precision) |
static QString | toString (const Complex &val, int precision) |
static Type | type (char t) |
static char | type (Type t) |
QList< int > QGpCoreTools::Number::divisors | ( | int | n | ) | [static] |
Return all divisors of n
{ // max number to analyse: 157609=397*397 static const int primes[]={ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397}; QList<int> ds; int q=398, d=2, i=0; while(d<q) { q=n/d; if((q*d)==n) { n=q; ds << d; } else { i++; } d=primes[i]; } ds << n; return ds; }
unsigned char QGpCoreTools::Number::fromBinaryCodedDecimal | ( | unsigned char | bcd | ) | [static] |
{
return ((bcd & 0xF0u) >> 3)*5u+
(bcd & 0x0Fu);
}
unsigned short QGpCoreTools::Number::fromBinaryCodedDecimal | ( | unsigned short | bcd | ) | [static] |
{
return ((bcd & 0xF000u) >> 9)*125u+
((bcd & 0x0F00u) >> 6)*25u+
((bcd & 0x00F0u) >> 3)*5u+
(bcd & 0x000Fu);
}
unsigned int QGpCoreTools::Number::fromBinaryCodedDecimal | ( | unsigned int | bcd | ) | [static] |
{
return ((bcd & 0xF0000000u) >> 21)*78125u+
((bcd & 0x0F000000u) >> 18)*15625u+
((bcd & 0x00F00000u) >> 15)*3125u+
((bcd & 0x000F0000u) >> 12)*625u+
((bcd & 0x0000F000u) >> 9)*125u+
((bcd & 0x00000F00u) >> 6)*25u+
((bcd & 0x000000F0u) >> 3)*5u+
(bcd & 0x0000000Fu);
}
unsigned int QGpCoreTools::Number::nextPowerOfTwo | ( | unsigned int | val | ) | [static] |
Returns the next power of two for any unsigned integer less than or equal to 2147483647. Inspired from http://acius2.blogspot.com/2007/11/calculating-next-power-of-2.html
Converts number to a solid '1' number before adding just 1.
{ val--; // if val is already a power of 2 val=(val >> 1) | val; val=(val >> 2) | val; val=(val >> 4) | val; val=(val >> 8) | val; val=(val >> 16) | val; val++; return val; }
QString QGpCoreTools::Number::secondsToTime | ( | double | sec, |
Number::Type | type = Number::Weeks , |
||
int | numberPrecision = -1 |
||
) | [static] |
Convert sec seconds into a string with format ".w.d.h.n.s"
References Days, Fixed, Hours, Minutes, Scientific, Seconds, str, TRACE, and Weeks.
Referenced by toString().
{ TRACE; switch(type) { case Fixed: return QString::number(sec, 'f', numberPrecision); case Scientific: return QString::number(sec, 'g', numberPrecision); case Weeks: case Days: case Hours: case Minutes: case Seconds: break; } if(sec==0.0) { return "0s"; } QString str; if(sec<0.0) { sec=-sec; str+="-"; } double sec0=sec; if(sec>=604800.0 && type<=Number::Weeks) { int week=(int)floor(sec/604800.0); sec=sec-(double)week*604800.0; str+=QString::number(week); str+="w"; if(sec==0.0) return str; } if(sec>=86400.0 && type<=Number::Days) { int day=(int)floor(sec/86400.0); sec=sec-(double)day*86400.0; str+=QString::number(day); str+="d"; if(sec==0.0) return str; } else if(sec<sec0) { str+="0d"; } if(sec>=3600.0 && type<=Number::Hours) { int hour=(int)floor(sec/3600.0); sec=sec-(double)hour*3600.0; str+=QString::number(hour); str+="h"; if(sec==0.0) return str; } else if(sec<sec0) { str+="0h"; } if(sec>=60.0 && type<=Number::Minutes) { int min=(int)floor(sec/60.0); sec=sec-(double)min*60.0; str+=QString::number(min); str+="m"; if(sec==0.0) return str; } else if(sec<sec0) { str+="0m"; } if(sec>0.0) { str+=QString::number(sec,'f',numberPrecision); str+="s"; } return str; }
double QGpCoreTools::Number::sign | ( | double | val | ) | [inline, static] |
{ if(val>0.0) { return 1.0; } else if(val<0.0) { return -1.0; } else { return 0.0; } }
int QGpCoreTools::Number::sign | ( | int | val | ) | [inline, static] |
{ if(val>0) { return 1; } else if(val<0) { return -1; } else { return 0; } }
double QGpCoreTools::Number::timeToSeconds | ( | const QString & | str | ) | [static] |
Converts a string with format ".w.d.h.n.s" or "h:m:s" into a number of seconds
References Hours, Minutes, Seconds, and TRACE.
Referenced by toDouble().
{ TRACE; const QChar * p=str.data(); int n=str.count(); QString number; bool ok; int vali; double vald; double sec=0.0; enum ColonState {Unknown, NoColon, Hours, Minutes, Seconds}; ColonState colonState=Unknown; double lastNumberFactor=1.0; // Skip first blanks and check sign int i; bool neg=timeToSecondsSign(p, i, n); for( ; i<n; i++ ) { switch(p[i].unicode()) { case ' ': break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': number+=p[i]; break; case ':': if(number.isEmpty()) return timeToSecondsError(str, i); switch(colonState) { case Unknown: case Hours: vali=number.toInt(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vali*3600.0; colonState=Minutes; lastNumberFactor=60.0; // If next number is the last one, it is minutes break; case Minutes: vali=number.toInt(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vali*60.0; colonState=Seconds; lastNumberFactor=1.0; // If next number is the last one, it is seconds break; case Seconds: vald=number.toDouble(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vald; colonState=Seconds; break; case NoColon: return timeToSecondsError(str, i); } number.clear(); break; case 'w': switch (colonState) { case NoColon: break; case Unknown: colonState=NoColon; break; default: return timeToSecondsError(str, i); } vali=number.toInt(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vali*604800.0; number.clear(); lastNumberFactor=86400.0; // If next number is the last one, it is days break; case 'd': switch (colonState) { case NoColon: break; case Unknown: colonState=NoColon; break; default: return timeToSecondsError(str, i); } vali=number.toInt(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vali*86400.0; number.clear(); lastNumberFactor=3600.0; // If next number is the last one, it is hours break; case 'h': switch (colonState) { case NoColon: break; case Unknown: colonState=NoColon; break; default: return timeToSecondsError(str, i); } vali=number.toInt(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vali*3600.0; number.clear(); lastNumberFactor=60.0; // If next number is the last one, it is minutes break; case 'm': switch (colonState) { case NoColon: break; case Unknown: colonState=NoColon; break; default: return timeToSecondsError(str, i); } vali=number.toInt(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vali*60.0; number.clear(); lastNumberFactor=1.0; // If next number is the last one, it is seconds break; case 's': switch (colonState) { case NoColon: break; case Unknown: colonState=NoColon; break; default: return timeToSecondsError(str, i); } vald=number.toDouble(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vald; number.clear(); break; default: return timeToSecondsError(str, i); } } if(!number.isEmpty()) { vald=number.toDouble(&ok); if(!ok) return timeToSecondsError(str, i); sec+=vald*lastNumberFactor; } return neg ? -sec : sec; }
unsigned char QGpCoreTools::Number::toBinaryCodedDecimal | ( | unsigned char | val | ) | [static] |
References QGpCoreTools::endl(), QGpCoreTools::App::stream(), and QGpCoreTools::tr().
{ if(val>=100) { App::stream() << tr("Number::toBinaryCodedDecimal: overflow, value>=100") << endl; return 0x99; } unsigned char bcd; ldiv_t d; d=ldiv(val, 10); bcd=d.rem; if(d.quot>0) { bcd+=d.quot << 4; } return bcd; }
unsigned short QGpCoreTools::Number::toBinaryCodedDecimal | ( | unsigned short | val | ) | [static] |
References QGpCoreTools::endl(), QGpCoreTools::App::stream(), and QGpCoreTools::tr().
{ if(val>=10000u) { App::stream() << tr("Number::toBinaryCodedDecimal: overflow, value>=10,000") << endl; return 0x9999; } unsigned short bcd; ldiv_t d; d=ldiv(val, 10); bcd=d.rem; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 4; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 8; if(d.quot>0) { bcd+=d.quot << 12; } } else { bcd+=d.quot << 8; } } else if(d.quot>0) { bcd+=d.quot << 4; } return bcd; }
unsigned int QGpCoreTools::Number::toBinaryCodedDecimal | ( | unsigned int | val | ) | [static] |
References QGpCoreTools::endl(), QGpCoreTools::App::stream(), and QGpCoreTools::tr().
{ if(val>=100000000u) { App::stream() << tr("Number::toBinaryCodedDecimal: overflow, value>=100,000,000") << endl; return 0x99999999; } unsigned int bcd; ldiv_t d; d=ldiv(val, 10); bcd=d.rem; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 4; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 8; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 12; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 16; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 20; if(d.quot>9) { d=ldiv(d.quot, 10); bcd+=d.rem << 24; if(d.quot>0) { bcd+=d.quot << 28; } } else { bcd+=d.quot << 24; } } else { bcd+=d.quot << 20; } } else { bcd+=d.quot << 16; } } else { bcd+=d.quot << 12; } } else { bcd+=d.quot << 8; } } else if(d.quot>0) { bcd+=d.quot << 4; } return bcd; }
double QGpCoreTools::Number::toDouble | ( | const QString & | str, |
Type | t, | ||
bool * | ok = 0 |
||
) | [inline, static] |
References Days, Fixed, Hours, Minutes, Scientific, Seconds, timeToSeconds(), and Weeks.
Referenced by QGpCoreTools::SparseMatrix< T >::toUserString(), and QGpCoreTools::MatrixData< T >::toUserString().
{ switch(t) { case Fixed: case Scientific: return str.toDouble(ok); case Weeks: case Days: case Hours: case Minutes: case Seconds: return timeToSeconds(str); } return 0.0; }
double QGpCoreTools::Number::toDouble | ( | float | f | ) | [static] |
Converts a float to a double keeping track of rounding errors. Converting a float to a double in a basic way may lead to strange results.
Tests made with this function:
0.002 returns 0.0020000000000000000416 instead of 0.0020000000949949026108 0.0020405 returns 0.0020405000000000002129 instead of 0.0020405000541359186172 0.002040567 returns 0.0020405670000000000752 instead of 0.0020405671093612909317 204056700000 returns 204056705154.90594482 instead of 204056707072
Offers a transparent conversion from any real type to double.
References QGpCoreTools::exp().
{ if (f==0.0) return 0.0; // Extracts the exponent value of the float (bits 2-9) // Generates a warning difficult to avoid... any other solution? #if Q_BYTE_ORDER==Q_BIG_ENDIAN int exp=((*(reinterpret_cast<unsigned short*>(&f)) & 0x7F80) >> 7)-127; #else int exp=((*(reinterpret_cast<unsigned short*>(&f)+1) & 0x7F80) >> 7)-127; #endif // log10(2)=0.301029995663981198 // Precision for float mantissa is 1/2^23, look for power of 10 to multiply f so that // 1/2^23 stand after decimal point, to remove it by rounding. double fac=pow(10.0,floor(0.301029995663981198*(22-exp))); return round(fac*f)/fac; }
static double QGpCoreTools::Number::toDouble | ( | const Complex & | c | ) | [inline, static] |
References QGpCoreTools::Complex::abs().
{return c.abs();}
static double QGpCoreTools::Number::toDouble | ( | double | a | ) | [inline, static] |
{return a;}
QString QGpCoreTools::Number::toString | ( | double | val, |
Type | t, | ||
int | precision | ||
) | [inline, static] |
References Days, Fixed, Hours, Minutes, Scientific, Seconds, secondsToTime(), and Weeks.
Referenced by QGpCoreTools::MatrixData< T >::toString().
{ switch(t) { case Fixed: return QString::number(val, 'f', precision); case Scientific: return QString::number(val, 'e', precision); case Weeks: case Days: case Hours: case Minutes: case Seconds: return secondsToTime(val, t, precision); } return QString::null; }
QString QGpCoreTools::Number::toString | ( | double | val, |
int | precision | ||
) | [inline, static] |
{ return QString::number(val, 'g', precision); }
QString QGpCoreTools::Number::toString | ( | const Complex & | val, |
int | precision | ||
) | [inline, static] |
References QGpCoreTools::Complex::toString().
{
return val.toString(precision);
}
Number::Type QGpCoreTools::Number::type | ( | char | t | ) | [inline, static] |
char QGpCoreTools::Number::type | ( | Type | t | ) | [inline, static] |