Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/misc.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                                  misc.cpp
00003                                 ----------
00004     begin                : Wed Nov 11 2004
00005     copyright            : (C) 2014 by YodaLee
00006     email                : lc85301@gmail.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00022 #ifdef HAVE_CONFIG_H
00023 # include <config.h>
00024 #endif
00025 
00026 #include <cmath>
00027 #include "misc.h"
00028 #include "main.h"
00029 
00030 #include <cstdio>
00031 #include <QString>
00032 #include <QStringList>
00033 #include <QRegExp>
00034 #include <QFileInfo>
00035 #include <QDir>
00036 
00037 // #########################################################################
00038 QString misc::complexRect(double real, double imag, int Precision)
00039 {
00040   QString Text;
00041   if(fabs(imag) < 1e-250) Text = QString::number(real,'g',Precision);
00042   else {
00043     Text = QString::number(imag,'g',Precision);
00044     if(Text.at(0) == '-') {
00045       Text.replace(0,1,'j');
00046       Text = '-'+Text;
00047     }
00048     else  Text = "+j"+Text;
00049     Text = QString::number(real,'g',Precision) + Text;
00050   }
00051   return Text;
00052 }
00053 
00054 QString misc::complexDeg(double real, double imag, int Precision)
00055 {
00056   QString Text;
00057   if(fabs(imag) < 1e-250) Text = QString::number(real,'g',Precision);
00058   else {
00059     Text  = QString::number(sqrt(real*real+imag*imag),'g',Precision) + " / ";
00060     Text += QString::number(180.0/pi*atan2(imag,real),'g',Precision) + QString::fromUtf8("°");
00061   }
00062   return Text;
00063 }
00064 
00065 QString misc::complexRad (double real, double imag, int Precision)
00066 {
00067   QString Text;
00068   if(fabs(imag) < 1e-250) Text = QString::number(real,'g',Precision);
00069   else {
00070     Text  = QString::number(sqrt(real*real+imag*imag),'g',Precision);
00071     Text += " / " + QString::number(atan2(imag,real),'g',Precision) + "rad";
00072   }
00073   return Text;
00074 }
00075 
00076 // #########################################################################
00077 QString misc::StringNum(double num, char form, int Precision)
00078 {
00079   int a = 0;
00080   char *p, Buffer[512], Format[6] = "%.00g";
00081 
00082   if(Precision < 0) {
00083     Format[1]  = form;
00084     Format[2]  = 0;
00085   }
00086   else {
00087     Format[4]  = form;
00088     Format[2] += Precision / 10;
00089     Format[3] += Precision % 10;
00090   }
00091   sprintf(Buffer, Format, num);
00092   p = strchr(Buffer, 'e');
00093   if(p) {
00094     p++;
00095     if(*(p++) == '+') { a = 1; }   // remove '+' of exponent
00096     if(*p == '0') { a++; p++; }    // remove leading zeros of exponent
00097     if(a > 0)
00098       do {
00099         *(p-a) = *p;
00100       } while(*(p++) != 0);    // override characters not needed
00101   }
00102 
00103   return QString(Buffer);
00104 }
00105 
00106 // #########################################################################
00107 QString misc::StringNiceNum(double num)
00108 {
00109   char Format[6] = "%.8e";
00110   if(fabs(num) < 1e-250)  return QString("0");  // avoid many problems
00111   if(fabs(log10(fabs(num))) < 3.0)  Format[3] = 'g';
00112 
00113   int a = 0;
00114   char *p, *pe, Buffer[512];
00115 
00116   sprintf(Buffer, Format, num);
00117   p = pe = strchr(Buffer, 'e');
00118   if(p) {
00119     if(*(++p) == '+') { a = 1; }    // remove '+' of exponent
00120     if(*(++p) == '0') { a++; p++; } // remove leading zeros of exponent
00121     if(a > 0)
00122       do {
00123         *(p-a) = *p;
00124       } while(*(p++) != 0);  // override characters not needed
00125 
00126     // In 'g' format, trailing zeros are already cut off !!!
00127     p = strchr(Buffer, '.');
00128     if(p) {
00129       if(!pe)  pe = Buffer + strlen(Buffer);
00130       p = pe-1;
00131       while(*p == '0')   // looking for unneccessary zero characters
00132         if((--p) <= Buffer)  break;
00133       if(*p != '.')  p++;  // no digit after decimal point ?
00134       while( (*(p++) = *(pe++)) != 0 ) ;  // overwrite zero characters
00135     }
00136   }
00137 
00138   return QString(Buffer);
00139 }
00140 
00141 // #########################################################################
00142 void misc::str2num(const QString& s_, double& Number, QString& Unit, double& Factor)
00143 {
00144   QString str = s_.stripWhiteSpace();
00145 
00146 /*  int i=0;
00147   bool neg = false;
00148   if(str[0] == '-') {      // check sign
00149     neg = true;
00150     i++;
00151   }
00152   else if(str[0] == '+')  i++;
00153 
00154   double num = 0.0;
00155   for(;;) {
00156     if(str[i] >= '0')  if(str[i] <= '9') {
00157       num = 10.0*num + double(str[i]-'0');
00158     }
00159   }*/
00160 
00161   QRegExp Expr( QRegExp("[^0-9\\x2E\\x2D\\x2B]") );
00162   int i = str.find( Expr );
00163   if(i >= 0)
00164     if((str.at(i).latin1() | 0x20) == 'e') {
00165       int j = str.find( Expr , ++i);
00166       if(j == i)  j--;
00167       i = j;
00168     }
00169 
00170   Number = str.left(i).toDouble();
00171   Unit   = str.mid(i).stripWhiteSpace();
00172   if(Unit.length()>0)
00173   {
00174     switch(Unit.at(0).latin1()) {
00175       case 'T': Factor = 1e12;  break;
00176       case 'G': Factor = 1e9;   break;
00177       case 'M': Factor = 1e6;   break;
00178       case 'k': Factor = 1e3;   break;
00179       case 'c': Factor = 1e-2;  break;
00180       case 'm': Factor = 1e-3;  break;
00181       case 'u': Factor = 1e-6;  break;
00182       case 'n': Factor = 1e-9;  break;
00183       case 'p': Factor = 1e-12; break;
00184       case 'f': Factor = 1e-15; break;
00185   //    case 'd':
00186       default:  Factor = 1.0;
00187     }
00188   }
00189   else
00190   {
00191     Factor = 1.0;
00192   }
00193 
00194   return;
00195 }
00196 
00197 // #########################################################################
00198 QString misc::num2str(double Num)
00199 {
00200   char c = 0;
00201   double cal = fabs(Num);
00202   if(cal > 1e-20) {
00203     cal = log10(cal) / 3.0;
00204     if(cal < -0.2)  cal -= 0.98;
00205     int Expo = int(cal);
00206 
00207     if(Expo >= -5) if(Expo <= 4)
00208       switch(Expo) {
00209         case -5: c = 'f'; break;
00210         case -4: c = 'p'; break;
00211         case -3: c = 'n'; break;
00212         case -2: c = 'u'; break;
00213         case -1: c = 'm'; break;
00214         case  1: c = 'k'; break;
00215         case  2: c = 'M'; break;
00216         case  3: c = 'G'; break;
00217         case  4: c = 'T'; break;
00218       }
00219 
00220     if(c)  Num /= pow(10.0, double(3*Expo));
00221   }
00222 
00223   QString Str = QString::number(Num);
00224   if(c)  Str += c;
00225 
00226   return Str;
00227 }
00228 
00229 // #########################################################################
00230 void misc::convert2Unicode(QString& Text)
00231 {
00232   bool ok;
00233   int i = 0;
00234   QString n;
00235   unsigned short ch;
00236   while((i=Text.find("\\x", i)) >= 0) {
00237     n = Text.mid(i, 6);
00238     ch = n.mid(2).toUShort(&ok, 16);
00239     if(ok)  Text.replace(n, QChar(ch));
00240     i++;
00241   }
00242   Text.replace("\\n", "\n");
00243   Text.replace("\\\\", "\\");
00244 }
00245 
00246 // #########################################################################
00247 void misc::convert2ASCII(QString& Text)
00248 {
00249   Text.replace('\\', "\\\\");
00250   Text.replace('\n', "\\n");
00251 
00252   int i = 0;
00253   QChar ch;
00254   char Str[8];
00255   while(Text.size()<i) {  // convert special characters
00256     if(ch > QChar(0x7F)) {
00257       sprintf(Str, "\\x%04X", ch.unicode());
00258       Text.replace(ch, Str);
00259     }
00260   }
00261 }
00262 
00263 // #########################################################################
00264 // Converts a path to an absolute path and resolves paths relative to the
00265 // Qucs home directory
00266 QString misc::properAbsFileName(const QString& Name)
00267 {
00268   QString s = Name;
00269   QFileInfo Info(s);
00270 
00271   if(Info.isRelative())
00272   {
00273       // if it's a relative file, look for it relative to the
00274       // working directory (the qucs home directory)
00275       s = QucsSettings.QucsWorkDir.filePath(s);
00276   }
00277   // return the clean path
00278   return QDir::cleanPath(s);
00279 }
00280 
00281 // #########################################################################
00282 QString misc::properFileName(const QString& Name)
00283 {
00284   QFileInfo Info(Name);
00285   return Info.fileName();
00286 }
00287 
00288 // #########################################################################
00289 // Takes a file name (with path) and replaces all special characters.
00290 QString misc::properName(const QString& Name)
00291 {
00292   QString s = Name;
00293   QFileInfo Info(s);
00294   if(Info.extension() == "sch")
00295     s = s.left(s.length()-4);
00296   if(s.at(0) <= '9') if(s.at(0) >= '0')
00297     s = 'n' + s;
00298   s.replace(QRegExp("\\W"), "_"); // none [a-zA-Z0-9] into "_"
00299   s.replace("__", "_");  // '__' not allowed in VHDL
00300   if(s.at(0) == '_')
00301     s = 'n' + s;
00302   return s;
00303 }
00304 
00305 // #########################################################################
00306 // Creates and returns delay time for VHDL entities.
00307 bool misc::VHDL_Delay(QString& td, const QString& Name)
00308 {
00309   if(strtod(td.latin1(), 0) != 0.0) {  // delay time property
00310     if(!misc::VHDL_Time(td, Name))
00311       return false;    // time has not VHDL format
00312     td = " after " + td;
00313     return true;
00314   }
00315   else if(isalpha(td.latin1()[0])) {
00316     td = " after " + td;
00317     return true;
00318   }
00319   else {
00320     td = "";
00321     return true;
00322   }
00323 }
00324 
00325 // #########################################################################
00326 // Checks and corrects a time (number & unit) according VHDL standard.
00327 bool misc::VHDL_Time(QString& t, const QString& Name)
00328 {
00329   char *p;
00330   double Time = strtod(t.latin1(), &p);
00331   while(*p == ' ') p++;
00332   for(;;) {
00333     if(Time >= 0.0) {
00334       if(strcmp(p, "fs") == 0)  break;
00335       if(strcmp(p, "ps") == 0)  break;
00336       if(strcmp(p, "ns") == 0)  break;
00337       if(strcmp(p, "us") == 0)  break;
00338       if(strcmp(p, "ms") == 0)  break;
00339       if(strcmp(p, "sec") == 0) break;
00340       if(strcmp(p, "min") == 0) break;
00341       if(strcmp(p, "hr") == 0)  break;
00342     }
00343     t = QString::fromUtf8("§")  + QObject::tr("Error: Wrong time format in \"%1\". Use positive number with units").arg(Name)
00344             + " fs, ps, ns, us, ms, sec, min, hr.\n";
00345     return false;
00346   }
00347 
00348   t = QString::number(Time) + " " + QString(p);  // the space is mandatory !
00349   return true;
00350 }
00351 
00352 // #########################################################################
00353 // Returns parameters for Verilog modules.
00354 QString misc::Verilog_Param(const QString Value)
00355 {
00356   if(strtod(Value.latin1(), 0) != 0.0) {
00357     QString td = Value;
00358     if(!misc::Verilog_Time(td, "parameter"))
00359       return Value;
00360     else
00361       return td;
00362   }
00363   else
00364     return Value;
00365 }
00366 
00367 // #########################################################################
00368 // Creates and returns delay time for Verilog modules.
00369 bool misc::Verilog_Delay(QString& td, const QString& Name)
00370 {
00371   if(strtod(td.latin1(), 0) != 0.0) {  // delay time property
00372     if(!misc::Verilog_Time(td, Name))
00373       return false;    // time has not Verilog format
00374     td = " #" + td;
00375     return true;
00376   }
00377   else if(isalpha(td.latin1()[0])) {
00378     td = " #" + td;
00379     return true;
00380   }
00381   else {
00382     td = "";
00383     return true;
00384   }
00385 }
00386 
00387 // #########################################################################
00388 // Checks and corrects a time (number & unit) according Verilog standard.
00389 bool misc::Verilog_Time(QString& t, const QString& Name)
00390 {
00391   char *p;
00392   double Time = strtod(t.latin1(), &p);
00393   double factor = 1.0;
00394   while(*p == ' ') p++;
00395   for(;;) {
00396     if(Time >= 0.0) {
00397       if(strcmp(p, "fs") == 0) { factor = 1e-3; break; }
00398       if(strcmp(p, "ps") == 0) { factor = 1;  break; }
00399       if(strcmp(p, "ns") == 0) { factor = 1e3;  break; }
00400       if(strcmp(p, "us") == 0) { factor = 1e6;  break; }
00401       if(strcmp(p, "ms") == 0) { factor = 1e9;  break; }
00402       if(strcmp(p, "sec") == 0) { factor = 1e12; break; }
00403       if(strcmp(p, "min") == 0) { factor = 1e12*60; break; }
00404       if(strcmp(p, "hr") == 0)  { factor = 1e12*60*60; break; }
00405     }
00406     t = QString::fromUtf8("§")  + QObject::tr("Error: Wrong time format in \"%1\". Use positive number with units").arg(Name)
00407             + " fs, ps, ns, us, ms, sec, min, hr.\n";
00408     return false;
00409   }
00410 
00411   t = QString::number(Time*factor);
00412   return true;
00413 }
00414 
00415 // #########################################################################
00416 bool misc::checkVersion(QString& Line)
00417 {
00418   QStringList sl = QStringList::split('.',PACKAGE_VERSION);
00419   QStringList ll = QStringList::split('.',Line);
00420   if (ll.count() != 3 || sl.count() != 3)
00421     return false;
00422   int sv = (int)sl.at(1).toLongLong()*10000+sl.at(2).toLongLong()*100;
00423   int lv = (int)ll.at(1).toLongLong()*10000+ll.at(2).toLongLong()*100;
00424   if(lv > sv) // wrong version number ? (only backward compatible)
00425     return false;
00426   return true;
00427 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines