diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kspread/kspread_functions_engineering.cc | |
download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kspread/kspread_functions_engineering.cc')
-rw-r--r-- | kspread/kspread_functions_engineering.cc | 1256 |
1 files changed, 1256 insertions, 0 deletions
diff --git a/kspread/kspread_functions_engineering.cc b/kspread/kspread_functions_engineering.cc new file mode 100644 index 00000000..3f2e8bd2 --- /dev/null +++ b/kspread/kspread_functions_engineering.cc @@ -0,0 +1,1256 @@ +/* This file is part of the KDE project + Copyright (C) 1998-2002 The KSpread Team + www.koffice.org/kspread + Copyright (C) 2005 Tomas Mecir <[email protected]> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +// built-in engineering functions + +#include "functions.h" +#include "valuecalc.h" +#include "valueconverter.h" + +// used by the CONVERT function +#include <qmap.h> + +// these are needed for complex functions, while we handle them in the old way +#include <kglobal.h> +#include <klocale.h> +#include <math.h> + +using namespace KSpread; + +// prototypes (sort alphabetically) +Value func_base (valVector args, ValueCalc *calc, FuncExtra *); +Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *); +Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *); +Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *); +Value func_complex (valVector args, ValueCalc *calc, FuncExtra *); +Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *); +Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *); +Value func_convert (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_delta (valVector args, ValueCalc *calc, FuncExtra *); +Value func_erf (valVector args, ValueCalc *calc, FuncExtra *); +Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *); +Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imln (valVector args, ValueCalc *calc, FuncExtra *); +Value func_impower (valVector args, ValueCalc *calc, FuncExtra *); +Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *); +Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *); +Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *); +Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *); +Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *); + +// registers all engineering functions +void RegisterEngineeringFunctions() +{ + FunctionRepository* repo = FunctionRepository::self(); + Function *f; + + f = new Function ("BASE", func_base); // KSpread-specific, like in Quattro-Pro + f->setParamCount (1, 3); + repo->add (f); + f = new Function ("BESSELI", func_besseli); + f->setParamCount (2); + repo->add (f); + f = new Function ("BESSELJ", func_besselj); + f->setParamCount (2); + repo->add (f); + f = new Function ("BESSELK", func_besselk); + f->setParamCount (2); + repo->add (f); + f = new Function ("BESSELY", func_bessely); + f->setParamCount (2); + repo->add (f); + f = new Function ("BIN2DEC", func_bin2dec); + repo->add (f); + f = new Function ("BIN2OCT", func_bin2oct); + repo->add (f); + f = new Function ("BIN2HEX", func_bin2hex); + repo->add (f); + f = new Function ("COMPLEX", func_complex); + f->setParamCount (2); + repo->add (f); + f = new Function ("CONVERT", func_convert); + f->setParamCount (3); + repo->add (f); + f = new Function ("DEC2HEX", func_dec2hex); + repo->add (f); + f = new Function ("DEC2BIN", func_dec2bin); + repo->add (f); + f = new Function ("DEC2OCT", func_dec2oct); + repo->add (f); + f = new Function ("DELTA", func_delta); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("ERF", func_erf); + f->setParamCount (2); + repo->add (f); + f = new Function ("ERFC", func_erfc); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("GESTEP", func_gestep); + f->setParamCount (1, 2); + repo->add (f); + f = new Function ("HEX2BIN", func_hex2bin); + repo->add (f); + f = new Function ("HEX2DEC", func_hex2dec); + repo->add (f); + f = new Function ("HEX2OCT", func_hex2oct); + repo->add (f); + f = new Function ("IMABS", func_imabs); + repo->add (f); + f = new Function ("IMAGINARY", func_complex_imag); + repo->add (f); + f = new Function ("IMARGUMENT", func_imargument); + repo->add (f); + f = new Function ("IMCONJUGATE", func_imconjugate); + repo->add (f); + f = new Function ("IMCOS", func_imcos); + repo->add (f); + f = new Function ("IMDIV", func_imdiv); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("IMEXP", func_imexp); + repo->add (f); + f = new Function ("IMLN", func_imln); + repo->add (f); + f = new Function ("IMPOWER", func_impower); + f->setParamCount (2); + repo->add (f); + f = new Function ("IMPRODUCT", func_improduct); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("IMREAL", func_complex_real); + repo->add (f); + f = new Function ("IMSIN", func_imsin); + repo->add (f); + f = new Function ("IMSQRT", func_imsqrt); + repo->add (f); + f = new Function ("IMSUB", func_imsub); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("IMSUM", func_imsum); + f->setParamCount (1, -1); + f->setAcceptArray (); + repo->add (f); + f = new Function ("OCT2BIN", func_oct2bin); + repo->add (f); + f = new Function ("OCT2DEC", func_oct2dec); + repo->add (f); + f = new Function ("OCT2HEX", func_oct2hex); + repo->add (f); +} + +// Function: BASE +Value func_base (valVector args, ValueCalc *calc, FuncExtra *) +{ + int base = 10; + int prec = 0; + if (args.count() > 1) + base = calc->conv()->asInteger (args[1]).asInteger(); + if (args.count() == 3) + prec = calc->conv()->asInteger (args[2]).asInteger(); + + if ((base < 2) || (base > 36)) + return Value::errorVALUE(); + if (prec < 0) prec = 2; + + return calc->base (args[0], base, prec); +} + +// Function: BESSELI +Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besseli (y, x); +} + +// Function: BESSELJ +Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besselj (y, x); +} + +// Function: BESSELK +Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besselk (y, x); +} + +// Function: BESSELY +Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = args[1]; + return calc->besseln (y, x); +} + +// Function: DEC2HEX +Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (args[0], 16); +} + +// Function: DEC2OCT +Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (args[0], 8); +} + +// Function: DEC2BIN +Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (args[0], 2); +} + +// Function: BIN2DEC +Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->fromBase (args[0], 2); +} + +// Function: BIN2OCT +Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 2), 8); +} + +// Function: BIN2HEX +Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 2), 16); +} + +// Function: OCT2DEC +Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->fromBase (args[0], 8); +} + +// Function: OCT2BIN +Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 8), 2); +} + +// Function: OCT2HEX +Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 8), 16); +} + +// Function: HEX2DEC +Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->fromBase (args[0], 16); +} + +// Function: HEX2BIN +Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 16), 2); +} + +// Function: HEX2OCT +Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *) +{ + return calc->base (calc->fromBase (args[0], 16), 8); +} + + +// check if unit may contain prefix, for example "kPa" is "Pa" with +// return prefix factor found in unit, or 1.0 for no prefix +// also modify the unit, i.e stripping the prefix from it +// example: "kPa" will return 1e3 and change unit into "Pa" +static double kspread_convert_prefix( QMap<QString,double> map, QString& unit ) +{ + if( map.contains( unit ) ) + return 1.0; + + // initialize prefix mapping if necessary + static QMap<char,double> prefixMap; + if( prefixMap.isEmpty() ) + { + prefixMap[ 'E' ] = 1e18; // exa + prefixMap[ 'P' ] = 1e15; // peta + prefixMap[ 'T' ] = 1e12; // tera + prefixMap[ 'G' ] = 1e9; // giga + prefixMap[ 'M' ] = 1e6; // mega + prefixMap[ 'k' ] = 1e3; // kilo + prefixMap[ 'h' ] = 1e2; // hecto + prefixMap[ 'e' ] = 1e1; // dekao + prefixMap[ 'd' ] = 1e1; // deci + prefixMap[ 'c' ] = 1e2; // centi + prefixMap[ 'm' ] = 1e3; // milli + prefixMap[ 'u' ] = 1e6; // micro + prefixMap[ 'n' ] = 1e9; // nano + prefixMap[ 'p' ] = 1e12; // pico + prefixMap[ 'f' ] = 1e15; // femto + prefixMap[ 'a' ] = 1e18; // atto + } + + // check for possible prefix + char prefix = unit[0].latin1(); + if( prefixMap.contains( prefix ) ) + { + unit.remove( 0, 1 ); + return prefixMap[ prefix ]; + } + + // fail miserably + return 0.0; +} + +static bool kspread_convert_mass( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> massMap; + + // first-time initialization + if( massMap.isEmpty() ) + { + massMap[ "g" ] = 1.0; // Gram (the reference ) + massMap[ "sg" ] = 6.8522050005347800E-05; // Pieces + massMap[ "lbm" ] = 2.2046229146913400E-03; // Pound + massMap[ "u" ] = 6.0221370000000000E23; // U (atomic mass) + massMap[ "ozm" ] = 3.5273971800362700E-02; // Ounce + massMap[ "stone" ] = 1.574730e-04; // Stone + massMap[ "ton" ] = 1.102311e-06; // Ton + massMap[ "grain" ] = 1.543236E01; // Grain + massMap[ "pweight" ] = 7.054792E-01; // Pennyweight + massMap[ "hweight" ] = 1.968413E-05; // Hundredweight + massMap[ "shweight" ] = 2.204623E-05; // Shorthundredweight + massMap[ "brton" ] = 9.842065E-07; // Gross Registered Ton + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( massMap, fromU ); + double toPrefix = kspread_convert_prefix( massMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !massMap.contains( fromU ) ) return false; + if( !massMap.contains( toU ) ) return false; + + result = value * fromPrefix * massMap[toU] / (massMap[fromU] * toPrefix); + + return true; +} + + +static bool kspread_convert_distance( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> distanceMap; + + // first-time initialization + if( distanceMap.isEmpty() ) + { + distanceMap[ "m" ] = 1.0; // meter (the reference) + distanceMap[ "in" ] = 1.0 / 0.0254; // inch + distanceMap[ "ft" ] = 1.0 / (12.0 * 0.0254); // feet + distanceMap[ "yd" ] = 1.0 / (3.0 * 12.0 * 0.0254); // yar + distanceMap[ "mi" ] = 6.2137119223733397e-4; // mile + distanceMap[ "Nmi" ] = 5.3995680345572354e-04; // nautical mile + distanceMap[ "ang" ] = 1e10; // Angstrom + distanceMap[ "parsec" ] = 3.240779e-17; // Parsec + distanceMap[ "lightyear" ] = 1.057023455773293e-16; // lightyear + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( distanceMap, fromU ); + double toPrefix = kspread_convert_prefix( distanceMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !distanceMap.contains( fromU ) ) return false; + if( !distanceMap.contains( toU ) ) return false; + + result = value * fromPrefix * distanceMap[toU] / (distanceMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_pressure( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> pressureMap; + + // first-time initialization + if( pressureMap.isEmpty() ) + { + pressureMap[ "Pa" ] = 1.0; + pressureMap[ "atm" ] = 0.9869233e-5; + pressureMap[ "mmHg" ] = 0.00750061708; + pressureMap[ "psi" ] = 1 / 6894.754; + pressureMap[ "Torr" ] = 1 / 133.32237; + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( pressureMap, fromU ); + double toPrefix = kspread_convert_prefix( pressureMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !pressureMap.contains( fromU ) ) return false; + if( !pressureMap.contains( toU ) ) return false; + + result = value * fromPrefix * pressureMap[toU] / (pressureMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_force( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> forceMap; + + // first-time initialization + if( forceMap.isEmpty() ) + { + forceMap[ "N" ] = 1.0; // Newton (reference) + forceMap[ "dyn" ] = 1.0e5; // dyn + forceMap[ "pond" ] = 1.019716e2; // pond + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( forceMap, fromU ); + double toPrefix = kspread_convert_prefix( forceMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !forceMap.contains( fromU ) ) return false; + if( !forceMap.contains( toU ) ) return false; + + result = value * fromPrefix * forceMap[toU] / (forceMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_energy( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> energyMap; + + // first-time initialization + if( energyMap.isEmpty() ) + { + energyMap[ "J" ] = 1.0; // Joule (the reference) + energyMap[ "e" ] = 1.0e7; //erg + energyMap[ "c" ] = 0.239006249473467; // thermodynamical calorie + energyMap[ "cal" ] = 0.238846190642017; // calorie + energyMap[ "eV" ] = 6.241457e+18; // electronvolt + energyMap[ "HPh" ] = 3.72506111e-7; // horsepower-hour + energyMap[ "Wh" ] = 0.000277778; // watt-hour + energyMap[ "flb" ] = 23.73042222; + energyMap[ "BTU" ] = 9.47815067349015e-4; // British Thermal Unit + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( energyMap, fromU ); + double toPrefix = kspread_convert_prefix( energyMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !energyMap.contains( fromU ) ) return false; + if( !energyMap.contains( toU ) ) return false; + + result = value * fromPrefix * energyMap[toU] / (energyMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_power( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> powerMap; + + // first-time initialization + if( powerMap.isEmpty() ) + { + powerMap[ "W" ] = 1.0; // Watt (the reference) + powerMap[ "HP" ] = 1.341022e-3; // Horsepower + powerMap[ "PS" ] = 1.359622e-3; // Pferdest�rke (German) + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( powerMap, fromU ); + double toPrefix = kspread_convert_prefix( powerMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !powerMap.contains( fromU ) ) return false; + if( !powerMap.contains( toU ) ) return false; + + result = value * fromPrefix * powerMap[toU] / (powerMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_magnetism( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> magnetismMap; + + // first-time initialization + if( magnetismMap.isEmpty() ) + { + magnetismMap[ "T" ] = 1.0; // Tesla (the reference) + magnetismMap[ "ga" ] = 1.0e4; // Gauss + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( magnetismMap, fromU ); + double toPrefix = kspread_convert_prefix( magnetismMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !magnetismMap.contains( fromU ) ) return false; + if( !magnetismMap.contains( toU ) ) return false; + + result = value * fromPrefix * magnetismMap[toU] / (magnetismMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_temperature( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> tempFactorMap; + static QMap<QString, double> tempOffsetMap; + + // first-time initialization + if( tempFactorMap.isEmpty() || tempOffsetMap.isEmpty() ) + { + tempFactorMap[ "C" ] = 1.0; tempOffsetMap[ "C" ] = 0.0; + tempFactorMap[ "F" ] = 5.0/9.0; tempOffsetMap[ "F" ] = -32.0; + tempFactorMap[ "K" ] = 1.0; tempOffsetMap[ "K" ] = -273.15; + } + + if( !tempFactorMap.contains( fromUnit ) ) return false; + if( !tempOffsetMap.contains( fromUnit ) ) return false; + if( !tempFactorMap.contains( toUnit ) ) return false; + if( !tempOffsetMap.contains( toUnit ) ) return false; + + result = ( value + tempOffsetMap[ fromUnit ] )* tempFactorMap[ fromUnit ]; + result = ( result / tempFactorMap[ toUnit ] ) - tempOffsetMap[ toUnit ]; + + return true; +} + +static bool kspread_convert_volume( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> volumeMap; + + // first-time initialization + if( volumeMap.isEmpty() ) + { + volumeMap[ "l" ] = 1.0; // Liter (the reference) + volumeMap[ "tsp" ] = 202.84; // teaspoon + volumeMap[ "tbs" ] = 67.6133333333333; // sheetspoon + volumeMap[ "oz" ] = 33.8066666666667; // ounce liquid + volumeMap[ "cup" ] = 4.22583333333333; // cup + volumeMap[ "pt" ] = 2.11291666666667; // pint + volumeMap[ "qt" ] = 1.05645833333333; // quart + volumeMap[ "gal" ] = 0.26411458333333; // gallone + volumeMap[ "m3" ] = 1.0e-3; // cubic meter + volumeMap[ "mi3" ] = 2.3991275857892772e-13; // cubic mile + volumeMap[ "Nmi3" ] = 1.5742621468581148e-13; // cubic Nautical mile + volumeMap[ "in3" ] = 6.1023744094732284e1; // cubic inch + volumeMap[ "ft3" ] = 3.5314666721488590e-2; // cubic foot + volumeMap[ "yd3" ] = 1.3079506193143922; // cubic yard + volumeMap[ "barrel" ] = 6.289811E-03; // barrel + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( volumeMap, fromU ); + double toPrefix = kspread_convert_prefix( volumeMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !volumeMap.contains( fromU ) ) return false; + if( !volumeMap.contains( toU ) ) return false; + + result = value * fromPrefix * volumeMap[toU] / (volumeMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_area( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> areaMap; + + // first-time initialization + if( areaMap.isEmpty() ) + { + areaMap[ "m2" ] = 1.0; // square meter (the reference) + areaMap[ "mi2" ] = 3.8610215854244585e-7; // square mile + areaMap[ "Nmi2" ] = 2.9155334959812286e-7; // square Nautical mile + areaMap[ "in2" ] = 1.5500031000062000e3; // square inch + areaMap[ "ft2" ] = 1.0763910416709722e1; // square foot + areaMap[ "yd2" ] = 1.0936132983377078; // square yard + areaMap[ "acre" ] = 4.046856e3; // acre + areaMap[ "ha" ] = 1.0e4; // hectare + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( areaMap, fromU ); + double toPrefix = kspread_convert_prefix( areaMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !areaMap.contains( fromU ) ) return false; + if( !areaMap.contains( toU ) ) return false; + + result = value * fromPrefix * areaMap[toU] / (areaMap[fromU] * toPrefix); + + return true; +} + +static bool kspread_convert_speed( const QString& fromUnit, + const QString& toUnit, double value, double& result ) +{ + static QMap<QString, double> speedMap; + + // first-time initialization + if( speedMap.isEmpty() ) + { + speedMap[ "m/s" ] = 1.0; // meters per second (the reference) + speedMap[ "m/h" ] = 3.6e3; // meters per hour + speedMap[ "mph" ] = 2.2369362920544023; // miles per hour + speedMap[ "kn" ] = 1.9438444924406048; // knot + } + + QString fromU = fromUnit; + QString toU = toUnit; + double fromPrefix = kspread_convert_prefix( speedMap, fromU ); + double toPrefix = kspread_convert_prefix( speedMap, toU ); + if( fromPrefix == 0.0 ) return false; + if( toPrefix == 0.0 ) return false; + if( !speedMap.contains( fromU ) ) return false; + if( !speedMap.contains( toU ) ) return false; + + result = value * fromPrefix * speedMap[toU] / (speedMap[fromU] * toPrefix); + + return true; +} + + +// Function: CONVERT +Value func_convert (valVector args, ValueCalc *calc, FuncExtra *) +{ + // This function won't support arbitrary precision. + + double value = calc->conv()->asFloat (args[0]).asFloat (); + QString fromUnit = calc->conv()->asString (args[1]).asString(); + QString toUnit = calc->conv()->asString (args[2]).asString(); + + double result = value; + + if( !kspread_convert_mass( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_distance( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_pressure( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_force( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_energy( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_power( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_magnetism( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_temperature( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_volume( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_area( fromUnit, toUnit, value, result ) ) + if( !kspread_convert_speed( fromUnit, toUnit, value, result ) ) + return Value::errorNA(); + + return Value (result); +} + + +// functions operating over complex numbers ... +// these may eventually end up being merged into ValueCalc and friends +// then complex numbers will be handled transparently in most functions + +static QString func_create_complex( double real,double imag ) +{ + QString tmp,tmp2; + if(imag ==0) + { + return KGlobal::locale()->formatNumber( real); + } + if(real!=0) + tmp=KGlobal::locale()->formatNumber(real); + else + return KGlobal::locale()->formatNumber(imag)+"i"; + if (imag >0) + tmp=tmp+"+"+KGlobal::locale()->formatNumber(imag)+"i"; + else + tmp=tmp+KGlobal::locale()->formatNumber(imag)+"i"; + return tmp; + +} + +// Function: COMPLEX +Value func_complex (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (calc->isZero (args[1])) + return args[0]; + double re = calc->conv()->asFloat (args[0]).asFloat (); + double im = calc->conv()->asFloat (args[1]).asFloat (); + QString tmp=func_create_complex (re, im); + bool ok; + double result = KGlobal::locale()->readNumber(tmp, &ok); + if (ok) + return Value (result); + return Value (tmp); +} + + +static double imag_complexe(QString str, bool &ok) +{ +QString tmp=str; +if(tmp.find('i')==-1) + { //not a complex + ok=true; + return 0; + } +else if( tmp.length()==1) + { + // i + ok=true; + return 1; + } +else if( tmp.length()==2 ) + { + //-i,+i, + int pos1; + if((pos1=tmp.find('+'))!=-1&& pos1==0) + { + ok=true; + return 1; + } + else if( (pos1=tmp.find('-'))!=-1 && pos1==0 ) + { + ok=true; + return -1; + } + else if(tmp[0].isDigit()) + { //5i + ok=true; + return KGlobal::locale()->readNumber(tmp.left(1)); + } + else + { + ok=false; + return 0; + } + } +else + {//12+12i + int pos1,pos2; + if((pos1=tmp.find('i'))!=-1) + { + double val; + QString tmpStr; + + if((pos2=tmp.findRev('+'))!=-1 && pos2!=0) + { + if((pos1-pos2)==1) + { + ok=true; + return 1; + } + else + { + tmpStr=tmp.mid(pos2,(pos1-pos2)); + val=KGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + } + else if( (pos2=tmp.findRev('-'))!=-1&& pos2!=0) + { + if((pos1-pos2)==1) + { + ok=true; + return -1; + } + else + { + tmpStr=tmp.mid(pos2,(pos1-pos2)); + val=KGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + } + else + {//15.55i + tmpStr=tmp.left(pos1); + val=KGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + } + } +ok=false; +return 0; +} + +// Function: IMAGINARY +Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString (); + bool good; + double result=imag_complexe(tmp, good); + if (good) + return Value (result); + return Value::errorVALUE(); +} + + +static double real_complexe(QString str, bool &ok) +{ +double val; +int pos1,pos2; +QString tmp=str; +QString tmpStr; +if((pos1=tmp.find('i'))==-1) + { //12.5 + val=KGlobal::locale()->readNumber(tmp, &ok); + if(!ok) + val=0; + return val; + } +else + { //15-xi + if((pos2=tmp.findRev('-'))!=-1 && pos2!=0) + { + tmpStr=tmp.left(pos2); + val=KGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } //15+xi + else if((pos2=tmp.findRev('+'))!=-1) + { + tmpStr=tmp.left(pos2); + val=KGlobal::locale()->readNumber(tmpStr, &ok); + if(!ok) + val=0; + return val; + } + else + { + ok=true; + return 0; + } + } + +ok=false; +return 0; +} + +// Function: IMREAL +Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString (); + bool good; + double result=real_complexe(tmp, good); + if (good) + return Value (result); + return Value::errorVALUE(); +} + +void ImHelper (ValueCalc *c, Value res, Value val, + double &imag, double &real, double &imag1, double &real1) +{ + bool ok; + imag=imag_complexe(res.asString(), ok); + real=real_complexe(res.asString(), ok); + if (val.isString()) + { + imag1 = imag_complexe (val.asString(), ok); + real1 = real_complexe (val.asString(), ok); + } else { + imag1=0; + real1=c->conv()->asFloat (val).asFloat(); + } +} + +void awImSum (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex(real+real1,imag+imag1); +} + +void awImSub (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex(real-real1,imag-imag1); +} + +void awImMul (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex(real*real1+(imag*imag1)*-1,real*imag1+real1*imag); +} + +void awImDiv (ValueCalc *c, Value &res, Value val, Value) +{ + double imag,real,imag1,real1; + ImHelper (c, res, val, imag, real, imag1, real1); + res=func_create_complex((real*real1+imag*imag1)/(real1*real1+imag1*imag1), + (real1*imag-real*imag1)/(real1*real1+imag1*imag1)); +} + +// Function: IMSUM +Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImSum, 0); + + bool ok; + QString res = calc->conv()->asString (result).asString(); + double val=KGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMSUB +Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImSub, 0); + + bool ok; + QString res = calc->conv()->asString (result).asString(); + double val=KGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMPRODUCT +Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImMul, 0); + + bool ok; + QString res = calc->conv()->asString (result).asString(); + double val=KGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMDIV +Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value result; + calc->arrayWalk (args, result, awImDiv, 0); + + bool ok; + QString res = calc->conv()->asString (result).asString(); + double val=KGlobal::locale()->readNumber(res, &ok); + if (ok) + return Value (val); + return Value (result); +} + +// Function: IMCONJUGATE +Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if (!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + + tmp=func_create_complex(real,-imag); + + double result=KGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMARGUMENT +Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if (!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if (!ok) + return Value::errorVALUE(); + if(imag==0) + return Value::errorDIV0(); + double arg=atan2(imag,real); + + return Value (arg); +} + +// Function: IMABS +Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double arg=sqrt(pow(imag,2)+pow(real,2)); + + return Value (arg); +} + +// Function: IMCOS +Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag_res=sin(real)*sinh(imag); + double real_res=cos(real)*cosh(imag); + + + tmp=func_create_complex(real_res,-imag_res); + + double result=KGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMSIN +Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag_res=cos(real)*sinh(imag); + double real_res=sin(real)*cosh(imag); + + + tmp=func_create_complex(real_res,imag_res); + + double result=KGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMLN +Value func_imln (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + + double arg=sqrt(pow(imag,2)+pow(real,2)); + double real_res=log(arg); + double imag_res=atan(imag/real); + tmp=func_create_complex(real_res,imag_res); + + double result=KGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMEXP +Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag_res=exp(real)*sin(imag); + double real_res=exp(real)*cos(imag); + + + tmp=func_create_complex(real_res,imag_res); + + double result=KGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMSQRT +Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double arg=sqrt(sqrt(pow(imag,2)+pow(real,2))); + double angle=atan(imag/real); + + double real_res=arg*cos((angle/2)); + double imag_res=arg*sin((angle/2)); + + tmp=func_create_complex(real_res,imag_res); + + double result=KGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: IMPOWER +Value func_impower (valVector args, ValueCalc *calc, FuncExtra *) +{ + QString tmp = calc->conv()->asString (args[0]).asString(); + double val2 = calc->conv()->asFloat (args[1]).asFloat(); + bool ok; + double real=real_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + double imag=imag_complexe(tmp,ok); + if(!ok) + return Value::errorVALUE(); + + double arg=::pow(sqrt(pow(imag,2)+pow(real,2)),val2); + double angle=atan(imag/real); + + double real_res=arg*cos(angle*val2); + double imag_res=arg*sin(angle*val2); + + tmp=func_create_complex(real_res,imag_res); + + double result=KGlobal::locale()->readNumber(tmp, &ok); + if(ok) + return Value (result); + + return Value (tmp); +} + +// Function: DELTA +Value func_delta (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value val1 = args[0]; + Value val2 = 0.0; + if (args.count() == 2) + val2 = args[1]; + + return Value (calc->approxEqual (val1, val2) ? 1 : 0); +} + +// Function: ERF +Value func_erf (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 2) + return calc->sub (calc->erf (args[1]), calc->erf (args[0])); + return calc->erf (args[0]); +} + +// Function: ERFC +Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *) +{ + if (args.count() == 2) + return calc->sub (calc->erfc (args[1]), calc->erfc (args[0])); + return calc->erfc (args[0]); +} + +// Function: GESTEP +Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *) +{ + Value x = args[0]; + Value y = 0.0; + if (args.count() == 2) + y = args[1]; + + int result = 0; + if (calc->greater (x, y) || calc->approxEqual (x, y)) + result = 1; + + return Value (result); +} + |