All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines
Public Types | Static Public Member Functions
QGpCoreTools::Number Class Reference

#include <Number.h>

List of all members.

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)

Member Enumeration Documentation

Enumerator:
Fixed 
Scientific 
Weeks 
Days 
Hours 
Minutes 
Seconds 

Member Function Documentation

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.

Precondition:
float f=0.002; double d=f; d is 0.0020000000949949026108 d=0.002; d is 0.0020000000000000000416

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.

See also:
toDouble(double a), toDouble (float a)

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]

Convert char format to type

  • 'f' for Fixed
  • 'e' for Scientific
  • 't' for Time

References Days, Fixed, Hours, Minutes, Scientific, Seconds, and Weeks.

{
  switch(t) {
  case 'e':
    return Scientific;
  case 't': // Compatibility
  case 'w':
    return Weeks;
  case 'd':
    return Days;
  case 'h':
    return Hours;
  case 'm':
    return Minutes;
  case 's':
    return Seconds;
  default:
    return Fixed;
  }
}
char QGpCoreTools::Number::type ( Type  t) [inline, static]

References Days, Fixed, Hours, Minutes, Scientific, Seconds, and Weeks.

{
  switch(t) {
  case Fixed:
    break;
  case Scientific:
    return 'e';
  case Weeks:
    return 'w';
  case Days:
    return 'd';
  case Hours:
    return 'h';
  case Minutes:
    return 'm';
  case Seconds:
    return 's';
  }
  return 'f';
}

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines