kspread

kspread_functions_engineering.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998-2002 The KSpread Team
00003                            www.koffice.org/kspread
00004    Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 // built-in engineering functions
00023 
00024 #include "functions.h"
00025 #include "valuecalc.h"
00026 #include "valueconverter.h"
00027 
00028 // used by the CONVERT function
00029 #include <qmap.h>
00030 
00031 // these are needed for complex functions, while we handle them in the old way
00032 #include <kglobal.h>
00033 #include <klocale.h>
00034 #include <math.h>
00035 
00036 using namespace KSpread;
00037 
00038 // prototypes (sort alphabetically)
00039 Value func_base (valVector args, ValueCalc *calc, FuncExtra *);
00040 Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *);
00041 Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *);
00042 Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *);
00043 Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *);
00044 Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *);
00045 Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *);
00046 Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *);
00047 Value func_complex (valVector args, ValueCalc *calc, FuncExtra *);
00048 Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *);
00049 Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *);
00050 Value func_convert (valVector args, ValueCalc *calc, FuncExtra *);
00051 Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *);
00052 Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *);
00053 Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *);
00054 Value func_delta (valVector args, ValueCalc *calc, FuncExtra *);
00055 Value func_erf (valVector args, ValueCalc *calc, FuncExtra *);
00056 Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *);
00057 Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *);
00058 Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *);
00059 Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *);
00060 Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *);
00061 Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *);
00062 Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *);
00063 Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *);
00064 Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *);
00065 Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *);
00066 Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *);
00067 Value func_imln (valVector args, ValueCalc *calc, FuncExtra *);
00068 Value func_impower (valVector args, ValueCalc *calc, FuncExtra *);
00069 Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *);
00070 Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *);
00071 Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *);
00072 Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *);
00073 Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *);
00074 Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *);
00075 Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *);
00076 Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *);
00077 
00078 // registers all engineering functions
00079 void RegisterEngineeringFunctions()
00080 {
00081   FunctionRepository* repo = FunctionRepository::self();
00082   Function *f;
00083 
00084   f = new Function ("BASE",        func_base);    // KSpread-specific, like in Quattro-Pro
00085   f->setParamCount (1, 3);
00086   repo->add (f);
00087   f = new Function ("BESSELI",     func_besseli);
00088   f->setParamCount (2);
00089   repo->add (f);
00090   f = new Function ("BESSELJ",     func_besselj);
00091   f->setParamCount (2);
00092   repo->add (f);
00093   f = new Function ("BESSELK",     func_besselk);
00094   f->setParamCount (2);
00095   repo->add (f);
00096   f = new Function ("BESSELY",     func_bessely);
00097   f->setParamCount (2);
00098   repo->add (f);
00099   f = new Function ("BIN2DEC",     func_bin2dec);
00100   repo->add (f);
00101   f = new Function ("BIN2OCT",     func_bin2oct);
00102   repo->add (f);
00103   f = new Function ("BIN2HEX",     func_bin2hex);
00104   repo->add (f);
00105   f = new Function ("COMPLEX",     func_complex);
00106   f->setParamCount (2);
00107   repo->add (f);
00108   f = new Function ("CONVERT",     func_convert);
00109   f->setParamCount (3);
00110   repo->add (f);
00111   f = new Function ("DEC2HEX",     func_dec2hex);
00112   repo->add (f);
00113   f = new Function ("DEC2BIN",     func_dec2bin);
00114   repo->add (f);
00115   f = new Function ("DEC2OCT",     func_dec2oct);
00116   repo->add (f);
00117   f = new Function ("DELTA",       func_delta);
00118   f->setParamCount (1, 2);
00119   repo->add (f);
00120   f = new Function ("ERF",         func_erf);
00121   f->setParamCount (2);
00122   repo->add (f);
00123   f = new Function ("ERFC",        func_erfc);
00124   f->setParamCount (1, 2);
00125   repo->add (f);
00126   f = new Function ("GESTEP",      func_gestep);
00127   f->setParamCount (1, 2);
00128   repo->add (f);
00129   f = new Function ("HEX2BIN",     func_hex2bin);
00130   repo->add (f);
00131   f = new Function ("HEX2DEC",     func_hex2dec);
00132   repo->add (f);
00133   f = new Function ("HEX2OCT",     func_hex2oct);
00134   repo->add (f);
00135   f = new Function ("IMABS",       func_imabs);
00136   repo->add (f);
00137   f = new Function ("IMAGINARY",   func_complex_imag);
00138   repo->add (f);
00139   f = new Function ("IMARGUMENT",  func_imargument);
00140   repo->add (f);
00141   f = new Function ("IMCONJUGATE", func_imconjugate);
00142   repo->add (f);
00143   f = new Function ("IMCOS",       func_imcos);
00144   repo->add (f);
00145   f = new Function ("IMDIV",       func_imdiv);
00146   f->setParamCount (1, -1);
00147   f->setAcceptArray ();
00148   repo->add (f);
00149   f = new Function ("IMEXP",       func_imexp);
00150   repo->add (f);
00151   f = new Function ("IMLN",        func_imln);
00152   repo->add (f);
00153   f = new Function ("IMPOWER",     func_impower);
00154   f->setParamCount (2);
00155   repo->add (f);
00156   f = new Function ("IMPRODUCT",   func_improduct);
00157   f->setParamCount (1, -1);
00158   f->setAcceptArray ();
00159   repo->add (f);
00160   f = new Function ("IMREAL",      func_complex_real);
00161   repo->add (f);
00162   f = new Function ("IMSIN",       func_imsin);
00163   repo->add (f);
00164   f = new Function ("IMSQRT",      func_imsqrt);
00165   repo->add (f);
00166   f = new Function ("IMSUB",       func_imsub);
00167   f->setParamCount (1, -1);
00168   f->setAcceptArray ();
00169   repo->add (f);
00170   f = new Function ("IMSUM",       func_imsum);
00171   f->setParamCount (1, -1);
00172   f->setAcceptArray ();
00173   repo->add (f);
00174   f = new Function ("OCT2BIN",     func_oct2bin);
00175   repo->add (f);
00176   f = new Function ("OCT2DEC",     func_oct2dec);
00177   repo->add (f);
00178   f = new Function ("OCT2HEX",     func_oct2hex);
00179   repo->add (f);
00180 }
00181 
00182 // Function: BASE
00183 Value func_base (valVector args, ValueCalc *calc, FuncExtra *)
00184 {
00185   int base = 10;
00186   int prec = 0;
00187   if (args.count() > 1)
00188     base = calc->conv()->asInteger (args[1]).asInteger();
00189   if (args.count() == 3)
00190     prec = calc->conv()->asInteger (args[2]).asInteger();
00191     
00192   if ((base < 2) || (base > 36))
00193     return Value::errorVALUE();
00194   if (prec < 0) prec = 2;
00195 
00196   return calc->base (args[0], base, prec);
00197 }
00198 
00199 // Function: BESSELI
00200 Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *)
00201 {
00202   Value x = args[0];
00203   Value y = args[1];
00204   return calc->besseli (y, x);
00205 }
00206 
00207 // Function: BESSELJ
00208 Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *)
00209 {
00210   Value x = args[0];
00211   Value y = args[1];
00212   return calc->besselj (y, x);
00213 }
00214 
00215 // Function: BESSELK
00216 Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *)
00217 {
00218   Value x = args[0];
00219   Value y = args[1];
00220   return calc->besselk (y, x);
00221 }
00222 
00223 // Function: BESSELY
00224 Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *)
00225 {
00226   Value x = args[0];
00227   Value y = args[1];
00228   return calc->besseln (y, x);
00229 }
00230 
00231 // Function: DEC2HEX
00232 Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *)
00233 {
00234   return calc->base (args[0], 16);
00235 }
00236 
00237 // Function: DEC2OCT
00238 Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *)
00239 {
00240   return calc->base (args[0], 8);
00241 }
00242 
00243 // Function: DEC2BIN
00244 Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *)
00245 {
00246   return calc->base (args[0], 2);
00247 }
00248 
00249 // Function: BIN2DEC
00250 Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *)
00251 {
00252   return calc->fromBase (args[0], 2);
00253 }
00254 
00255 // Function: BIN2OCT
00256 Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *)
00257 {
00258   return calc->base (calc->fromBase (args[0], 2), 8);
00259 }
00260 
00261 // Function: BIN2HEX
00262 Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *)
00263 {
00264   return calc->base (calc->fromBase (args[0], 2), 16);
00265 }
00266 
00267 // Function: OCT2DEC
00268 Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *)
00269 {
00270   return calc->fromBase (args[0], 8);
00271 }
00272 
00273 // Function: OCT2BIN
00274 Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *)
00275 {
00276   return calc->base (calc->fromBase (args[0], 8), 2);
00277 }
00278 
00279 // Function: OCT2HEX
00280 Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *)
00281 {
00282   return calc->base (calc->fromBase (args[0], 8), 16);
00283 }
00284 
00285 // Function: HEX2DEC
00286 Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *)
00287 {
00288   return calc->fromBase (args[0], 16);
00289 }
00290 
00291 // Function: HEX2BIN
00292 Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *)
00293 {
00294   return calc->base (calc->fromBase (args[0], 16), 2);
00295 }
00296 
00297 // Function: HEX2OCT
00298 Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *)
00299 {
00300   return calc->base (calc->fromBase (args[0], 16), 8);
00301 }
00302 
00303 
00304 // check if unit may contain prefix, for example "kPa" is "Pa" with
00305 // return prefix factor found in unit, or 1.0 for no prefix
00306 // also modify the unit, i.e stripping the prefix from it
00307 // example: "kPa" will return 1e3 and change unit into "Pa"
00308 static double kspread_convert_prefix( QMap<QString,double> map, QString& unit )
00309 {
00310   if( map.contains( unit ) )
00311     return 1.0;
00312 
00313   // initialize prefix mapping if necessary
00314   static QMap<char,double> prefixMap;
00315   if( prefixMap.isEmpty() )
00316   {
00317      prefixMap[ 'E' ] = 1e18;  //  exa
00318      prefixMap[ 'P' ] = 1e15;  //  peta
00319      prefixMap[ 'T' ] = 1e12;  // tera
00320      prefixMap[ 'G' ] = 1e9;   // giga
00321      prefixMap[ 'M' ] = 1e6;   // mega
00322      prefixMap[ 'k' ] = 1e3;   // kilo
00323      prefixMap[ 'h' ] = 1e2;   // hecto
00324      prefixMap[ 'e' ] = 1e1;   // dekao
00325      prefixMap[ 'd' ] = 1e1;   // deci
00326      prefixMap[ 'c' ] = 1e2;   // centi
00327      prefixMap[ 'm' ] = 1e3;   // milli
00328      prefixMap[ 'u' ] = 1e6;   // micro
00329      prefixMap[ 'n' ] = 1e9;   // nano
00330      prefixMap[ 'p' ] = 1e12;  // pico
00331      prefixMap[ 'f' ] = 1e15;  // femto
00332      prefixMap[ 'a' ] = 1e18;  // atto
00333   }
00334 
00335   // check for possible prefix
00336   char prefix = unit[0].latin1();
00337   if( prefixMap.contains( prefix ) )
00338   {
00339     unit.remove( 0, 1 );
00340     return prefixMap[ prefix ];
00341   }
00342 
00343   // fail miserably
00344   return 0.0;
00345 }
00346 
00347 static bool kspread_convert_mass( const QString& fromUnit,
00348   const QString& toUnit, double value, double& result )
00349 {
00350   static QMap<QString, double> massMap;
00351 
00352   // first-time initialization
00353   if( massMap.isEmpty() )
00354   {
00355     massMap[ "g" ]        = 1.0; // Gram (the reference )
00356     massMap[ "sg" ]       = 6.8522050005347800E-05; // Pieces
00357     massMap[ "lbm" ]      = 2.2046229146913400E-03; // Pound
00358     massMap[ "u" ]        = 6.0221370000000000E23; // U (atomic mass)
00359     massMap[ "ozm" ]      = 3.5273971800362700E-02; // Ounce
00360     massMap[ "stone" ]    = 1.574730e-04; // Stone
00361     massMap[ "ton" ]      = 1.102311e-06; // Ton
00362     massMap[ "grain" ]    = 1.543236E01;  // Grain
00363     massMap[ "pweight" ]  = 7.054792E-01; // Pennyweight
00364     massMap[ "hweight" ]  = 1.968413E-05; // Hundredweight
00365     massMap[ "shweight" ] = 2.204623E-05; // Shorthundredweight
00366     massMap[ "brton" ]    = 9.842065E-07; // Gross Registered Ton
00367   }
00368 
00369   QString fromU = fromUnit;
00370   QString toU = toUnit;
00371   double fromPrefix = kspread_convert_prefix( massMap, fromU );
00372   double toPrefix = kspread_convert_prefix( massMap, toU );
00373   if( fromPrefix == 0.0 ) return false;
00374   if( toPrefix == 0.0 ) return false;
00375   if( !massMap.contains( fromU ) ) return false;
00376   if( !massMap.contains( toU ) ) return false;
00377 
00378   result = value * fromPrefix * massMap[toU] / (massMap[fromU] * toPrefix);
00379 
00380   return true;
00381 }
00382 
00383 
00384 static bool kspread_convert_distance( const QString& fromUnit,
00385   const QString& toUnit, double value, double& result )
00386 {
00387   static QMap<QString, double> distanceMap;
00388 
00389   // first-time initialization
00390   if( distanceMap.isEmpty() )
00391   {
00392     distanceMap[ "m" ]         = 1.0;  // meter (the reference)
00393     distanceMap[ "in" ]        = 1.0 / 0.0254; // inch
00394     distanceMap[ "ft" ]        = 1.0 / (12.0 * 0.0254); // feet
00395     distanceMap[ "yd" ]        = 1.0 / (3.0 * 12.0 * 0.0254); // yar
00396     distanceMap[ "mi" ]        = 6.2137119223733397e-4; // mile
00397     distanceMap[ "Nmi" ]       = 5.3995680345572354e-04; // nautical mile
00398     distanceMap[ "ang" ]       = 1e10; // Angstrom
00399     distanceMap[ "parsec" ]    = 3.240779e-17; // Parsec
00400     distanceMap[ "lightyear" ] = 1.057023455773293e-16; // lightyear
00401   }
00402 
00403   QString fromU = fromUnit;
00404   QString toU = toUnit;
00405   double fromPrefix = kspread_convert_prefix( distanceMap, fromU );
00406   double toPrefix = kspread_convert_prefix( distanceMap, toU );
00407   if( fromPrefix == 0.0 ) return false;
00408   if( toPrefix == 0.0 ) return false;
00409   if( !distanceMap.contains( fromU ) ) return false;
00410   if( !distanceMap.contains( toU ) ) return false;
00411 
00412   result = value * fromPrefix * distanceMap[toU] / (distanceMap[fromU] * toPrefix);
00413 
00414   return true;
00415 }
00416 
00417 static bool kspread_convert_pressure( const QString& fromUnit,
00418   const QString& toUnit, double value, double& result )
00419 {
00420   static QMap<QString, double> pressureMap;
00421 
00422   // first-time initialization
00423   if( pressureMap.isEmpty() )
00424   {
00425     pressureMap[ "Pa" ] = 1.0;
00426     pressureMap[ "atm" ] = 0.9869233e-5;
00427     pressureMap[ "mmHg" ] = 0.00750061708;
00428     pressureMap[ "psi" ] = 1 / 6894.754;
00429     pressureMap[ "Torr" ] = 1 / 133.32237;
00430   }
00431 
00432   QString fromU = fromUnit;
00433   QString toU = toUnit;
00434   double fromPrefix = kspread_convert_prefix( pressureMap, fromU );
00435   double toPrefix = kspread_convert_prefix( pressureMap, toU );
00436   if( fromPrefix == 0.0 ) return false;
00437   if( toPrefix == 0.0 ) return false;
00438   if( !pressureMap.contains( fromU ) ) return false;
00439   if( !pressureMap.contains( toU ) ) return false;
00440 
00441   result = value * fromPrefix * pressureMap[toU] / (pressureMap[fromU] * toPrefix);
00442 
00443   return true;
00444 }
00445 
00446 static bool kspread_convert_force( const QString& fromUnit,
00447   const QString& toUnit, double value, double& result )
00448 {
00449   static QMap<QString, double> forceMap;
00450 
00451   // first-time initialization
00452   if( forceMap.isEmpty() )
00453   {
00454     forceMap[ "N" ]      = 1.0; // Newton (reference)
00455     forceMap[ "dyn" ]    = 1.0e5; // dyn
00456     forceMap[ "pond" ]   = 1.019716e2; // pond
00457   }
00458 
00459   QString fromU = fromUnit;
00460   QString toU = toUnit;
00461   double fromPrefix = kspread_convert_prefix( forceMap, fromU );
00462   double toPrefix = kspread_convert_prefix( forceMap, toU );
00463   if( fromPrefix == 0.0 ) return false;
00464   if( toPrefix == 0.0 ) return false;
00465   if( !forceMap.contains( fromU ) ) return false;
00466   if( !forceMap.contains( toU ) ) return false;
00467 
00468   result = value * fromPrefix * forceMap[toU] / (forceMap[fromU] * toPrefix);
00469 
00470   return true;
00471 }
00472 
00473 static bool kspread_convert_energy( const QString& fromUnit,
00474   const QString& toUnit, double value, double& result )
00475 {
00476   static QMap<QString, double> energyMap;
00477 
00478   // first-time initialization
00479   if( energyMap.isEmpty() )
00480   {
00481     energyMap[ "J" ]   = 1.0; // Joule (the reference)
00482     energyMap[ "e" ]   = 1.0e7; //erg
00483     energyMap[ "c" ]   = 0.239006249473467; // thermodynamical calorie
00484     energyMap[ "cal" ] = 0.238846190642017; // calorie
00485     energyMap[ "eV" ]  = 6.241457e+18; // electronvolt
00486     energyMap[ "HPh" ] = 3.72506111e-7; // horsepower-hour
00487     energyMap[ "Wh" ]  = 0.000277778; // watt-hour
00488     energyMap[ "flb" ] = 23.73042222;
00489     energyMap[ "BTU" ] = 9.47815067349015e-4; // British Thermal Unit
00490   }
00491 
00492   QString fromU = fromUnit;
00493   QString toU = toUnit;
00494   double fromPrefix = kspread_convert_prefix( energyMap, fromU );
00495   double toPrefix = kspread_convert_prefix( energyMap, toU );
00496   if( fromPrefix == 0.0 ) return false;
00497   if( toPrefix == 0.0 ) return false;
00498   if( !energyMap.contains( fromU ) ) return false;
00499   if( !energyMap.contains( toU ) ) return false;
00500 
00501   result = value * fromPrefix * energyMap[toU] / (energyMap[fromU] * toPrefix);
00502 
00503   return true;
00504 }
00505 
00506 static bool kspread_convert_power( const QString& fromUnit,
00507   const QString& toUnit, double value, double& result )
00508 {
00509   static QMap<QString, double> powerMap;
00510 
00511   // first-time initialization
00512   if( powerMap.isEmpty() )
00513   {
00514     powerMap[ "W" ]   = 1.0; // Watt (the reference)
00515     powerMap[ "HP" ]  = 1.341022e-3; // Horsepower
00516     powerMap[ "PS" ]  = 1.359622e-3; // Pferdestärke (German)
00517   }
00518 
00519   QString fromU = fromUnit;
00520   QString toU = toUnit;
00521   double fromPrefix = kspread_convert_prefix( powerMap, fromU );
00522   double toPrefix = kspread_convert_prefix( powerMap, toU );
00523   if( fromPrefix == 0.0 ) return false;
00524   if( toPrefix == 0.0 ) return false;
00525   if( !powerMap.contains( fromU ) ) return false;
00526   if( !powerMap.contains( toU ) ) return false;
00527 
00528   result = value * fromPrefix * powerMap[toU] / (powerMap[fromU] * toPrefix);
00529 
00530   return true;
00531 }
00532 
00533 static bool kspread_convert_magnetism( const QString& fromUnit,
00534   const QString& toUnit, double value, double& result )
00535 {
00536   static QMap<QString, double> magnetismMap;
00537 
00538   // first-time initialization
00539   if( magnetismMap.isEmpty() )
00540   {
00541     magnetismMap[ "T" ]   = 1.0;    // Tesla (the reference)
00542     magnetismMap[ "ga" ]   = 1.0e4; // Gauss
00543   }
00544 
00545   QString fromU = fromUnit;
00546   QString toU = toUnit;
00547   double fromPrefix = kspread_convert_prefix( magnetismMap, fromU );
00548   double toPrefix = kspread_convert_prefix( magnetismMap, toU );
00549   if( fromPrefix == 0.0 ) return false;
00550   if( toPrefix == 0.0 ) return false;
00551   if( !magnetismMap.contains( fromU ) ) return false;
00552   if( !magnetismMap.contains( toU ) ) return false;
00553 
00554   result = value * fromPrefix * magnetismMap[toU] / (magnetismMap[fromU] * toPrefix);
00555 
00556   return true;
00557 }
00558 
00559 static bool kspread_convert_temperature( const QString& fromUnit,
00560   const QString& toUnit, double value, double& result )
00561 {
00562   static QMap<QString, double> tempFactorMap;
00563   static QMap<QString, double> tempOffsetMap;
00564 
00565   // first-time initialization
00566   if( tempFactorMap.isEmpty() || tempOffsetMap.isEmpty() )
00567   {
00568     tempFactorMap[ "C" ] = 1.0; tempOffsetMap[ "C" ] = 0.0;
00569     tempFactorMap[ "F" ] = 5.0/9.0; tempOffsetMap[ "F" ] = -32.0;
00570     tempFactorMap[ "K" ] = 1.0; tempOffsetMap[ "K" ] = -273.15;
00571   }
00572 
00573   if( !tempFactorMap.contains( fromUnit ) ) return false;
00574   if( !tempOffsetMap.contains( fromUnit ) ) return false;
00575   if( !tempFactorMap.contains( toUnit ) ) return false;
00576   if( !tempOffsetMap.contains( toUnit ) ) return false;
00577 
00578   result = ( value + tempOffsetMap[ fromUnit ] )* tempFactorMap[ fromUnit ];
00579   result = ( result / tempFactorMap[ toUnit ] ) - tempOffsetMap[ toUnit ];
00580 
00581   return true;
00582 }
00583 
00584 static bool kspread_convert_volume( const QString& fromUnit,
00585   const QString& toUnit, double value, double& result )
00586 {
00587   static QMap<QString, double> volumeMap;
00588 
00589   // first-time initialization
00590   if( volumeMap.isEmpty() )
00591   {
00592     volumeMap[ "l" ]      = 1.0; // Liter (the reference)
00593     volumeMap[ "tsp" ]    = 202.84; // teaspoon
00594     volumeMap[ "tbs" ]    = 67.6133333333333; // sheetspoon
00595     volumeMap[ "oz" ]     = 33.8066666666667; // ounce liquid
00596     volumeMap[ "cup" ]    = 4.22583333333333; // cup
00597     volumeMap[ "pt" ]     = 2.11291666666667; // pint
00598     volumeMap[ "qt" ]     = 1.05645833333333; // quart
00599     volumeMap[ "gal" ]    = 0.26411458333333; // gallone
00600     volumeMap[ "m3" ]     = 1.0e-3; // cubic meter
00601     volumeMap[ "mi3" ]    = 2.3991275857892772e-13; // cubic mile
00602     volumeMap[ "Nmi3" ]   = 1.5742621468581148e-13; // cubic Nautical mile
00603     volumeMap[ "in3" ]    = 6.1023744094732284e1; // cubic inch
00604     volumeMap[ "ft3" ]    = 3.5314666721488590e-2; // cubic foot
00605     volumeMap[ "yd3" ]    = 1.3079506193143922; // cubic yard
00606     volumeMap[ "barrel" ] = 6.289811E-03; // barrel
00607   }
00608 
00609   QString fromU = fromUnit;
00610   QString toU = toUnit;
00611   double fromPrefix = kspread_convert_prefix( volumeMap, fromU );
00612   double toPrefix = kspread_convert_prefix( volumeMap, toU );
00613   if( fromPrefix == 0.0 ) return false;
00614   if( toPrefix == 0.0 ) return false;
00615   if( !volumeMap.contains( fromU ) ) return false;
00616   if( !volumeMap.contains( toU ) ) return false;
00617 
00618   result = value * fromPrefix * volumeMap[toU] / (volumeMap[fromU] * toPrefix);
00619 
00620   return true;
00621 }
00622 
00623 static bool kspread_convert_area( const QString& fromUnit,
00624   const QString& toUnit, double value, double& result )
00625 {
00626   static QMap<QString, double> areaMap;
00627 
00628   // first-time initialization
00629   if( areaMap.isEmpty() )
00630   {
00631     areaMap[ "m2" ]   = 1.0; // square meter (the reference)
00632     areaMap[ "mi2" ]  = 3.8610215854244585e-7; // square mile
00633     areaMap[ "Nmi2" ] = 2.9155334959812286e-7; // square Nautical mile
00634     areaMap[ "in2" ]  = 1.5500031000062000e3; // square inch
00635     areaMap[ "ft2" ]  = 1.0763910416709722e1; // square foot
00636     areaMap[ "yd2" ]  = 1.0936132983377078; // square yard
00637     areaMap[ "acre" ] = 4.046856e3; // acre
00638     areaMap[ "ha" ]   = 1.0e4; // hectare
00639   }
00640 
00641   QString fromU = fromUnit;
00642   QString toU = toUnit;
00643   double fromPrefix = kspread_convert_prefix( areaMap, fromU );
00644   double toPrefix = kspread_convert_prefix( areaMap, toU );
00645   if( fromPrefix == 0.0 ) return false;
00646   if( toPrefix == 0.0 ) return false;
00647   if( !areaMap.contains( fromU ) ) return false;
00648   if( !areaMap.contains( toU ) ) return false;
00649 
00650   result = value * fromPrefix * areaMap[toU] / (areaMap[fromU] * toPrefix);
00651 
00652   return true;
00653 }
00654 
00655 static bool kspread_convert_speed( const QString& fromUnit,
00656   const QString& toUnit, double value, double& result )
00657 {
00658   static QMap<QString, double> speedMap;
00659 
00660   // first-time initialization
00661   if( speedMap.isEmpty() )
00662   {
00663     speedMap[ "m/s" ] = 1.0; // meters per second (the reference)
00664     speedMap[ "m/h" ] = 3.6e3; // meters per hour
00665     speedMap[ "mph" ] = 2.2369362920544023; // miles per hour
00666     speedMap[ "kn" ]  = 1.9438444924406048; // knot
00667   }
00668 
00669   QString fromU = fromUnit;
00670   QString toU = toUnit;
00671   double fromPrefix = kspread_convert_prefix( speedMap, fromU );
00672   double toPrefix = kspread_convert_prefix( speedMap, toU );
00673   if( fromPrefix == 0.0 ) return false;
00674   if( toPrefix == 0.0 ) return false;
00675   if( !speedMap.contains( fromU ) ) return false;
00676   if( !speedMap.contains( toU ) ) return false;
00677 
00678   result = value * fromPrefix * speedMap[toU] / (speedMap[fromU] * toPrefix);
00679 
00680   return true;
00681 }
00682 
00683 
00684 // Function: CONVERT
00685 Value func_convert (valVector args, ValueCalc *calc, FuncExtra *)
00686 {
00687   // This function won't support arbitrary precision.
00688 
00689   double value = calc->conv()->asFloat (args[0]).asFloat ();
00690   QString fromUnit = calc->conv()->asString (args[1]).asString();
00691   QString toUnit = calc->conv()->asString (args[2]).asString();
00692 
00693   double result = value;
00694 
00695   if( !kspread_convert_mass( fromUnit, toUnit, value, result ) )
00696     if( !kspread_convert_distance( fromUnit, toUnit, value, result ) )
00697       if( !kspread_convert_pressure( fromUnit, toUnit, value, result ) )
00698         if( !kspread_convert_force( fromUnit, toUnit, value, result ) )
00699           if( !kspread_convert_energy( fromUnit, toUnit, value, result ) )
00700             if( !kspread_convert_power( fromUnit, toUnit, value, result ) )
00701               if( !kspread_convert_magnetism( fromUnit, toUnit, value, result ) )
00702                 if( !kspread_convert_temperature( fromUnit, toUnit, value, result ) )
00703                   if( !kspread_convert_volume( fromUnit, toUnit, value, result ) )
00704                     if( !kspread_convert_area( fromUnit, toUnit, value, result ) )
00705                       if( !kspread_convert_speed( fromUnit, toUnit, value, result ) )
00706                         return Value::errorNA();
00707 
00708   return Value (result);
00709 }
00710 
00711 
00712 // functions operating over complex numbers ...
00713 // these may eventually end up being merged into ValueCalc and friends
00714 // then complex numbers will be handled transparently in most functions
00715 
00716 static QString func_create_complex( double real,double imag )
00717 {
00718   QString tmp,tmp2;
00719   if(imag ==0)
00720         {
00721         return KGlobal::locale()->formatNumber( real);
00722         }
00723   if(real!=0)
00724         tmp=KGlobal::locale()->formatNumber(real);
00725   else
00726     return KGlobal::locale()->formatNumber(imag)+"i";
00727   if (imag >0)
00728         tmp=tmp+"+"+KGlobal::locale()->formatNumber(imag)+"i";
00729   else
00730         tmp=tmp+KGlobal::locale()->formatNumber(imag)+"i";
00731   return tmp;
00732 
00733 }
00734 
00735 // Function: COMPLEX
00736 Value func_complex (valVector args, ValueCalc *calc, FuncExtra *)
00737 {
00738   if (calc->isZero (args[1]))
00739     return args[0];
00740   double re = calc->conv()->asFloat (args[0]).asFloat ();
00741   double im = calc->conv()->asFloat (args[1]).asFloat ();
00742   QString tmp=func_create_complex (re, im);
00743   bool ok;
00744   double result = KGlobal::locale()->readNumber(tmp, &ok);
00745   if (ok)
00746     return Value (result);
00747   return Value (tmp);
00748 }
00749 
00750 
00751 static double imag_complexe(QString str, bool &ok)
00752 {
00753 QString tmp=str;
00754 if(tmp.find('i')==-1)
00755         {  //not a complex
00756         ok=true;
00757         return 0;
00758         }
00759 else if( tmp.length()==1)
00760         {
00761         // i
00762         ok=true;
00763         return 1;
00764         }
00765 else  if( tmp.length()==2 )
00766         {
00767         //-i,+i,
00768         int pos1;
00769         if((pos1=tmp.find('+'))!=-1&& pos1==0)
00770                 {
00771                 ok=true;
00772                 return 1;
00773                 }
00774         else if( (pos1=tmp.find('-'))!=-1 && pos1==0 )
00775                 {
00776                 ok=true;
00777                 return -1;
00778                 }
00779         else if(tmp[0].isDigit())
00780                 { //5i
00781                 ok=true;
00782                 return KGlobal::locale()->readNumber(tmp.left(1));
00783                 }
00784         else
00785                 {
00786                 ok=false;
00787                 return 0;
00788                 }
00789         }
00790 else
00791         {//12+12i
00792         int pos1,pos2;
00793         if((pos1=tmp.find('i'))!=-1)
00794                 {
00795                 double val;
00796                 QString tmpStr;
00797 
00798                 if((pos2=tmp.findRev('+'))!=-1 && pos2!=0)
00799                         {
00800                         if((pos1-pos2)==1)
00801                                 {
00802                                  ok=true;
00803                                  return 1;
00804                                 }
00805                         else
00806                                 {
00807                                 tmpStr=tmp.mid(pos2,(pos1-pos2));
00808                                 val=KGlobal::locale()->readNumber(tmpStr, &ok);
00809                                 if(!ok)
00810                                         val=0;
00811                                 return val;
00812                                 }
00813                         }
00814                 else if( (pos2=tmp.findRev('-'))!=-1&& pos2!=0)
00815                         {
00816                         if((pos1-pos2)==1)
00817                                 {
00818                                  ok=true;
00819                                  return -1;
00820                                 }
00821                         else
00822                                 {
00823                                 tmpStr=tmp.mid(pos2,(pos1-pos2));
00824                                 val=KGlobal::locale()->readNumber(tmpStr, &ok);
00825                                 if(!ok)
00826                                         val=0;
00827                                 return val;
00828                                 }
00829                         }
00830                 else
00831                         {//15.55i
00832                         tmpStr=tmp.left(pos1);
00833                         val=KGlobal::locale()->readNumber(tmpStr, &ok);
00834                         if(!ok)
00835                                 val=0;
00836                         return val;
00837                         }
00838                 }
00839         }
00840 ok=false;
00841 return 0;
00842 }
00843 
00844 // Function: IMAGINARY
00845 Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *)
00846 {
00847   QString tmp = calc->conv()->asString (args[0]).asString ();
00848   bool good;
00849   double result=imag_complexe(tmp, good);
00850   if (good)
00851     return Value (result);
00852   return Value::errorVALUE();
00853 }
00854 
00855 
00856 static double real_complexe(QString str, bool &ok)
00857 {
00858 double val;
00859 int pos1,pos2;
00860 QString tmp=str;
00861 QString tmpStr;
00862 if((pos1=tmp.find('i'))==-1)
00863         { //12.5
00864         val=KGlobal::locale()->readNumber(tmp, &ok);
00865         if(!ok)
00866                 val=0;
00867         return val;
00868         }
00869 else
00870         { //15-xi
00871         if((pos2=tmp.findRev('-'))!=-1 && pos2!=0)
00872                 {
00873                 tmpStr=tmp.left(pos2);
00874                 val=KGlobal::locale()->readNumber(tmpStr, &ok);
00875                 if(!ok)
00876                         val=0;
00877                 return val;
00878                 } //15+xi
00879         else if((pos2=tmp.findRev('+'))!=-1)
00880                 {
00881                 tmpStr=tmp.left(pos2);
00882                 val=KGlobal::locale()->readNumber(tmpStr, &ok);
00883                 if(!ok)
00884                         val=0;
00885                 return val;
00886                 }
00887         else
00888                 {
00889                 ok=true;
00890                 return 0;
00891                 }
00892         }
00893 
00894 ok=false;
00895 return 0;
00896 }
00897 
00898 // Function: IMREAL
00899 Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *)
00900 {
00901   QString tmp = calc->conv()->asString (args[0]).asString ();
00902   bool good;
00903   double result=real_complexe(tmp, good);
00904   if (good)
00905     return Value (result);
00906   return Value::errorVALUE();
00907 }
00908 
00909 void ImHelper (ValueCalc *c, Value res, Value val,
00910     double &imag, double &real, double &imag1, double &real1)
00911 {
00912   bool ok;
00913   imag=imag_complexe(res.asString(), ok);
00914   real=real_complexe(res.asString(), ok);
00915   if (val.isString())
00916   {
00917     imag1 = imag_complexe (val.asString(), ok);
00918     real1 = real_complexe (val.asString(), ok);
00919   } else {
00920     imag1=0;
00921     real1=c->conv()->asFloat (val).asFloat();
00922   }
00923 }
00924 
00925 void awImSum (ValueCalc *c, Value &res, Value val, Value)
00926 {
00927   double imag,real,imag1,real1;
00928   ImHelper (c, res, val, imag, real, imag1, real1);
00929   res=func_create_complex(real+real1,imag+imag1);
00930 }
00931 
00932 void awImSub (ValueCalc *c, Value &res, Value val, Value)
00933 {
00934   double imag,real,imag1,real1;
00935   ImHelper (c, res, val, imag, real, imag1, real1);
00936   res=func_create_complex(real-real1,imag-imag1);
00937 }
00938 
00939 void awImMul (ValueCalc *c, Value &res, Value val, Value)
00940 {
00941   double imag,real,imag1,real1;
00942   ImHelper (c, res, val, imag, real, imag1, real1);
00943   res=func_create_complex(real*real1+(imag*imag1)*-1,real*imag1+real1*imag);
00944 }
00945 
00946 void awImDiv (ValueCalc *c, Value &res, Value val, Value)
00947 {
00948   double imag,real,imag1,real1;
00949   ImHelper (c, res, val, imag, real, imag1, real1);
00950   res=func_create_complex((real*real1+imag*imag1)/(real1*real1+imag1*imag1),
00951       (real1*imag-real*imag1)/(real1*real1+imag1*imag1));
00952 }
00953 
00954 // Function: IMSUM
00955 Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *)
00956 {
00957   Value result;
00958   calc->arrayWalk (args, result, awImSum, 0);
00959   
00960   bool ok;
00961   QString res = calc->conv()->asString (result).asString();
00962   double val=KGlobal::locale()->readNumber(res, &ok);
00963   if (ok)
00964     return Value (val);
00965   return Value (result);
00966 }
00967 
00968 // Function: IMSUB
00969 Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *)
00970 {
00971   Value result;
00972   calc->arrayWalk (args, result, awImSub, 0);
00973   
00974   bool ok;
00975   QString res = calc->conv()->asString (result).asString();
00976   double val=KGlobal::locale()->readNumber(res, &ok);
00977   if (ok)
00978     return Value (val);
00979   return Value (result);
00980 }
00981 
00982 // Function: IMPRODUCT
00983 Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *)
00984 {
00985   Value result;
00986   calc->arrayWalk (args, result, awImMul, 0);
00987   
00988   bool ok;
00989   QString res = calc->conv()->asString (result).asString();
00990   double val=KGlobal::locale()->readNumber(res, &ok);
00991   if (ok)
00992     return Value (val);
00993   return Value (result);
00994 }
00995 
00996 // Function: IMDIV
00997 Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *)
00998 {
00999   Value result;
01000   calc->arrayWalk (args, result, awImDiv, 0);
01001   
01002   bool ok;
01003   QString res = calc->conv()->asString (result).asString();
01004   double val=KGlobal::locale()->readNumber(res, &ok);
01005   if (ok)
01006     return Value (val);
01007   return Value (result);
01008 }
01009 
01010 // Function: IMCONJUGATE
01011 Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *)
01012 {
01013   QString tmp = calc->conv()->asString (args[0]).asString();
01014   bool ok;
01015   double real=real_complexe(tmp,ok);
01016   if (!ok)
01017     return Value::errorVALUE();
01018   double imag=imag_complexe(tmp,ok);
01019   if(!ok)
01020     return Value::errorVALUE();
01021 
01022   tmp=func_create_complex(real,-imag);
01023 
01024   double result=KGlobal::locale()->readNumber(tmp, &ok);
01025   if(ok)
01026     return Value (result);
01027   
01028   return Value (tmp);
01029 }
01030 
01031 // Function: IMARGUMENT
01032 Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *)
01033 {
01034   QString tmp = calc->conv()->asString (args[0]).asString();
01035   bool ok;
01036   double real=real_complexe(tmp,ok);
01037   if (!ok)
01038     return Value::errorVALUE();
01039   double imag=imag_complexe(tmp,ok);
01040   if (!ok)
01041     return Value::errorVALUE();
01042   if(imag==0)
01043     return Value::errorDIV0();
01044   double arg=atan2(imag,real);
01045 
01046   return Value (arg);
01047 }
01048 
01049 // Function: IMABS
01050 Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *)
01051 {
01052   QString tmp = calc->conv()->asString (args[0]).asString();
01053   bool ok;
01054   double real=real_complexe(tmp,ok);
01055   if(!ok)
01056     return Value::errorVALUE();
01057   double imag=imag_complexe(tmp,ok);
01058   if(!ok)
01059     return Value::errorVALUE();
01060   double arg=sqrt(pow(imag,2)+pow(real,2));
01061 
01062   return Value (arg);
01063 }
01064 
01065 // Function: IMCOS
01066 Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *)
01067 {
01068   QString tmp = calc->conv()->asString (args[0]).asString();
01069   bool ok;
01070   double real=real_complexe(tmp,ok);
01071   if(!ok)
01072     return Value::errorVALUE();
01073   double imag=imag_complexe(tmp,ok);
01074   if(!ok)
01075     return Value::errorVALUE();
01076   double imag_res=sin(real)*sinh(imag);
01077   double real_res=cos(real)*cosh(imag);
01078 
01079 
01080   tmp=func_create_complex(real_res,-imag_res);
01081 
01082   double result=KGlobal::locale()->readNumber(tmp, &ok);
01083   if(ok)
01084     return Value (result);
01085   
01086   return Value (tmp);
01087 }
01088 
01089 // Function: IMSIN
01090 Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *)
01091 {
01092   QString tmp = calc->conv()->asString (args[0]).asString();
01093   bool ok;
01094   double real=real_complexe(tmp,ok);
01095   if(!ok)
01096     return Value::errorVALUE();
01097   double imag=imag_complexe(tmp,ok);
01098   if(!ok)
01099     return Value::errorVALUE();
01100   double imag_res=cos(real)*sinh(imag);
01101   double real_res=sin(real)*cosh(imag);
01102 
01103 
01104   tmp=func_create_complex(real_res,imag_res);
01105 
01106   double result=KGlobal::locale()->readNumber(tmp, &ok);
01107   if(ok)
01108     return Value (result);
01109   
01110   return Value (tmp);
01111 }
01112 
01113 // Function: IMLN
01114 Value func_imln (valVector args, ValueCalc *calc, FuncExtra *)
01115 {
01116   QString tmp = calc->conv()->asString (args[0]).asString();
01117   bool ok;
01118   double real=real_complexe(tmp,ok);
01119   if(!ok)
01120     return Value::errorVALUE();
01121   double imag=imag_complexe(tmp,ok);
01122   if(!ok)
01123     return Value::errorVALUE();
01124 
01125   double arg=sqrt(pow(imag,2)+pow(real,2));
01126   double real_res=log(arg);
01127   double imag_res=atan(imag/real);
01128   tmp=func_create_complex(real_res,imag_res);
01129 
01130   double result=KGlobal::locale()->readNumber(tmp, &ok);
01131   if(ok)
01132     return Value (result);
01133   
01134   return Value (tmp);
01135 }
01136 
01137 // Function: IMEXP
01138 Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *)
01139 {
01140   QString tmp = calc->conv()->asString (args[0]).asString();
01141   bool ok;
01142   double real=real_complexe(tmp,ok);
01143   if(!ok)
01144     return Value::errorVALUE();
01145   double imag=imag_complexe(tmp,ok);
01146   if(!ok)
01147     return Value::errorVALUE();
01148   double imag_res=exp(real)*sin(imag);
01149   double real_res=exp(real)*cos(imag);
01150 
01151 
01152   tmp=func_create_complex(real_res,imag_res);
01153 
01154   double result=KGlobal::locale()->readNumber(tmp, &ok);
01155   if(ok)
01156     return Value (result);
01157   
01158   return Value (tmp);
01159 }
01160 
01161 // Function: IMSQRT
01162 Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *)
01163 {
01164   QString tmp = calc->conv()->asString (args[0]).asString();
01165   bool ok;
01166   double real=real_complexe(tmp,ok);
01167   if(!ok)
01168     return Value::errorVALUE();
01169   double imag=imag_complexe(tmp,ok);
01170   if(!ok)
01171     return Value::errorVALUE();
01172   double arg=sqrt(sqrt(pow(imag,2)+pow(real,2)));
01173   double angle=atan(imag/real);
01174 
01175   double real_res=arg*cos((angle/2));
01176   double imag_res=arg*sin((angle/2));
01177 
01178   tmp=func_create_complex(real_res,imag_res);
01179 
01180   double result=KGlobal::locale()->readNumber(tmp, &ok);
01181   if(ok)
01182     return Value (result);
01183   
01184   return Value (tmp);
01185 }
01186 
01187 // Function: IMPOWER
01188 Value func_impower (valVector args, ValueCalc *calc, FuncExtra *)
01189 {
01190   QString tmp = calc->conv()->asString (args[0]).asString();
01191   double val2 = calc->conv()->asFloat (args[1]).asFloat();
01192   bool ok;
01193   double real=real_complexe(tmp,ok);
01194   if(!ok)
01195     return Value::errorVALUE();
01196   double imag=imag_complexe(tmp,ok);
01197   if(!ok)
01198     return Value::errorVALUE();
01199 
01200   double arg=::pow(sqrt(pow(imag,2)+pow(real,2)),val2);
01201   double angle=atan(imag/real);
01202 
01203   double real_res=arg*cos(angle*val2);
01204   double imag_res=arg*sin(angle*val2);
01205 
01206   tmp=func_create_complex(real_res,imag_res);
01207 
01208   double result=KGlobal::locale()->readNumber(tmp, &ok);
01209   if(ok)
01210     return Value (result);
01211   
01212   return Value (tmp);
01213 }
01214 
01215 // Function: DELTA
01216 Value func_delta (valVector args, ValueCalc *calc, FuncExtra *)
01217 {
01218   Value val1 = args[0];
01219   Value val2 = 0.0;
01220   if (args.count() == 2)
01221     val2 = args[1];
01222   
01223   return Value (calc->approxEqual (val1, val2) ? 1 : 0);
01224 }
01225 
01226 // Function: ERF
01227 Value func_erf (valVector args, ValueCalc *calc, FuncExtra *)
01228 {
01229   if (args.count() == 2)
01230     return calc->sub (calc->erf (args[1]), calc->erf (args[0]));
01231   return calc->erf (args[0]);
01232 }
01233 
01234 // Function: ERFC
01235 Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *)
01236 {
01237   if (args.count() == 2)
01238     return calc->sub (calc->erfc (args[1]), calc->erfc (args[0]));
01239   return calc->erfc (args[0]);
01240 }
01241 
01242 // Function: GESTEP
01243 Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *)
01244 {
01245   Value x = args[0];
01246   Value y = 0.0;
01247   if (args.count() == 2)
01248     y = args[1];
01249   
01250   int result = 0;
01251   if (calc->greater (x, y) || calc->approxEqual (x, y))
01252     result = 1;
01253 
01254   return Value (result);
01255 }
01256 
KDE Home | KDE Accessibility Home | Description of Access Keys