#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] |