File indexing completed on 2024-05-12 16:35:29
0001 /* This file is part of the KDE project 0002 Copyright (C) 1998-2002 The KSpread Team <calligra-devel@kde.org> 0003 Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com> 0004 Copyright 2007 Sascha Pfau <MrPeacock@gmail.com> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; only 0009 version 2 of the License. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 // built-in engineering functions 0023 0024 #include "EngineeringModule.h" 0025 0026 #include "Function.h" 0027 #include "FunctionModuleRegistry.h" 0028 #include "ValueCalc.h" 0029 #include "ValueConverter.h" 0030 0031 // used by the CONVERT function 0032 #include <QMap> 0033 0034 // these are needed for complex functions, while we handle them in the old way 0035 #include <math.h> 0036 0037 #ifndef M_LN2l 0038 #define M_LN2l 0.6931471805599453094172321214581766L 0039 #endif 0040 0041 using namespace Calligra::Sheets; 0042 0043 // prototypes (sort alphabetically) 0044 Value func_base(valVector args, ValueCalc *calc, FuncExtra *); 0045 Value func_besseli(valVector args, ValueCalc *calc, FuncExtra *); 0046 Value func_besselj(valVector args, ValueCalc *calc, FuncExtra *); 0047 Value func_besselk(valVector args, ValueCalc *calc, FuncExtra *); 0048 Value func_bessely(valVector args, ValueCalc *calc, FuncExtra *); 0049 Value func_bin2dec(valVector args, ValueCalc *calc, FuncExtra *); 0050 Value func_bin2oct(valVector args, ValueCalc *calc, FuncExtra *); 0051 Value func_bin2hex(valVector args, ValueCalc *calc, FuncExtra *); 0052 Value func_complex(valVector args, ValueCalc *calc, FuncExtra *); 0053 Value func_complex_imag(valVector args, ValueCalc *calc, FuncExtra *); 0054 Value func_complex_real(valVector args, ValueCalc *calc, FuncExtra *); 0055 Value func_convert(valVector args, ValueCalc *calc, FuncExtra *); 0056 Value func_dec2hex(valVector args, ValueCalc *calc, FuncExtra *); 0057 Value func_dec2oct(valVector args, ValueCalc *calc, FuncExtra *); 0058 Value func_dec2bin(valVector args, ValueCalc *calc, FuncExtra *); 0059 Value func_decimal(valVector args, ValueCalc *calc, FuncExtra *); 0060 Value func_delta(valVector args, ValueCalc *calc, FuncExtra *); 0061 Value func_erf(valVector args, ValueCalc *calc, FuncExtra *); 0062 Value func_erfc(valVector args, ValueCalc *calc, FuncExtra *); 0063 Value func_gestep(valVector args, ValueCalc *calc, FuncExtra *); 0064 Value func_hex2dec(valVector args, ValueCalc *calc, FuncExtra *); 0065 Value func_hex2bin(valVector args, ValueCalc *calc, FuncExtra *); 0066 Value func_hex2oct(valVector args, ValueCalc *calc, FuncExtra *); 0067 Value func_imabs(valVector args, ValueCalc *calc, FuncExtra *); 0068 Value func_imargument(valVector args, ValueCalc *calc, FuncExtra *); 0069 Value func_imconjugate(valVector args, ValueCalc *calc, FuncExtra *); 0070 Value func_imcos(valVector args, ValueCalc *calc, FuncExtra *); 0071 Value func_imcosh(valVector args, ValueCalc *calc, FuncExtra *); 0072 Value func_imcot(valVector args, ValueCalc *calc, FuncExtra *); 0073 Value func_imcsc(valVector args, ValueCalc *calc, FuncExtra *); 0074 Value func_imcsch(valVector args, ValueCalc *calc, FuncExtra *); 0075 Value func_imdiv(valVector args, ValueCalc *calc, FuncExtra *); 0076 Value func_imexp(valVector args, ValueCalc *calc, FuncExtra *); 0077 Value func_imln(valVector args, ValueCalc *calc, FuncExtra *); 0078 Value func_imlog2(valVector args, ValueCalc *calc, FuncExtra *); 0079 Value func_imlog10(valVector args, ValueCalc *calc, FuncExtra *); 0080 Value func_impower(valVector args, ValueCalc *calc, FuncExtra *); 0081 Value func_improduct(valVector args, ValueCalc *calc, FuncExtra *); 0082 Value func_imsec(valVector args, ValueCalc *calc, FuncExtra *); 0083 Value func_imsech(valVector args, ValueCalc *calc, FuncExtra *); 0084 Value func_imsin(valVector args, ValueCalc *calc, FuncExtra *); 0085 Value func_imsinh(valVector args, ValueCalc *calc, FuncExtra *); 0086 Value func_imsqrt(valVector args, ValueCalc *calc, FuncExtra *); 0087 Value func_imsub(valVector args, ValueCalc *calc, FuncExtra *); 0088 Value func_imsum(valVector args, ValueCalc *calc, FuncExtra *); 0089 Value func_imtan(valVector args, ValueCalc *calc, FuncExtra *); 0090 Value func_imtanh(valVector args, ValueCalc *calc, FuncExtra *); 0091 Value func_oct2dec(valVector args, ValueCalc *calc, FuncExtra *); 0092 Value func_oct2bin(valVector args, ValueCalc *calc, FuncExtra *); 0093 Value func_oct2hex(valVector args, ValueCalc *calc, FuncExtra *); 0094 0095 0096 CALLIGRA_SHEETS_EXPORT_FUNCTION_MODULE("kspreadengineeringmodule.json", EngineeringModule) 0097 0098 0099 EngineeringModule::EngineeringModule(QObject* parent, const QVariantList&) 0100 : FunctionModule(parent) 0101 { 0102 Function *f; 0103 0104 f = new Function("BASE", func_base); // Calligra Sheets-specific, like in Quattro-Pro 0105 f->setParamCount(1, 3); 0106 add(f); 0107 f = new Function("BESSELI", func_besseli); 0108 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELI"); 0109 f->setParamCount(2); 0110 add(f); 0111 f = new Function("BESSELJ", func_besselj); 0112 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELJ"); 0113 f->setParamCount(2); 0114 add(f); 0115 f = new Function("BESSELK", func_besselk); 0116 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELK"); 0117 f->setParamCount(2); 0118 add(f); 0119 f = new Function("BESSELY", func_bessely); 0120 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELY"); 0121 f->setParamCount(2); 0122 add(f); 0123 f = new Function("BIN2DEC", func_bin2dec); 0124 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBIN2DEC"); 0125 add(f); 0126 f = new Function("BIN2OCT", func_bin2oct); 0127 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBIN2OCT"); 0128 f->setParamCount(1, 2); 0129 add(f); 0130 f = new Function("BIN2HEX", func_bin2hex); 0131 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBIN2HEX"); 0132 f->setParamCount(1, 2); 0133 add(f); 0134 f = new Function("COMPLEX", func_complex); 0135 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETCOMPLEX"); 0136 f->setParamCount(2, 3); 0137 add(f); 0138 f = new Function("CONVERT", func_convert); 0139 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETCONVERT"); 0140 f->setParamCount(3); 0141 add(f); 0142 f = new Function("DEC2HEX", func_dec2hex); 0143 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDEC2HEX"); 0144 f->setParamCount(1, 2); 0145 add(f); 0146 f = new Function("DEC2BIN", func_dec2bin); 0147 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDEC2BIN"); 0148 f->setParamCount(1, 2); 0149 add(f); 0150 f = new Function("DEC2OCT", func_dec2oct); 0151 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDEC2OCT"); 0152 f->setParamCount(1, 2); 0153 add(f); 0154 f = new Function("DECIMAL", func_decimal); 0155 f->setParamCount(2); 0156 add(f); 0157 f = new Function("DELTA", func_delta); 0158 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDELTA"); 0159 f->setParamCount(1, 2); 0160 add(f); 0161 f = new Function("ERF", func_erf); 0162 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETERF"); 0163 f->setParamCount(1, 2); 0164 add(f); 0165 f = new Function("ERFC", func_erfc); 0166 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETERFC"); 0167 f->setParamCount(1, 2); 0168 add(f); 0169 f = new Function("GESTEP", func_gestep); 0170 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETGESTEP"); 0171 f->setParamCount(1, 2); 0172 add(f); 0173 f = new Function("HEX2BIN", func_hex2bin); 0174 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETHEX2BIN"); 0175 f->setParamCount(1, 2); 0176 add(f); 0177 f = new Function("HEX2DEC", func_hex2dec); 0178 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETHEX2DEC"); 0179 add(f); 0180 f = new Function("HEX2OCT", func_hex2oct); 0181 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETHEX2OCT"); 0182 f->setParamCount(1, 2); 0183 add(f); 0184 f = new Function("IMABS", func_imabs); 0185 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMABS"); 0186 add(f); 0187 f = new Function("IMAGINARY", func_complex_imag); 0188 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMAGINARY"); 0189 add(f); 0190 f = new Function("IMARGUMENT", func_imargument); 0191 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMARGUMENT"); 0192 add(f); 0193 f = new Function("IMCONJUGATE", func_imconjugate); 0194 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMCONJUGATE"); 0195 add(f); 0196 f = new Function("IMCOS", func_imcos); 0197 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMCOS"); 0198 add(f); 0199 f = new Function("IMCOSH", func_imcosh); 0200 add(f); 0201 f = new Function("IMCOT", func_imcot); 0202 add(f); 0203 f = new Function("IMCSC", func_imcsc); 0204 add(f); 0205 f = new Function("IMCSCH", func_imcsch); 0206 add(f); 0207 f = new Function("IMDIV", func_imdiv); 0208 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMDIV"); 0209 f->setParamCount(2); 0210 f->setAcceptArray(); 0211 add(f); 0212 f = new Function("IMEXP", func_imexp); 0213 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMEXP"); 0214 add(f); 0215 f = new Function("IMLN", func_imln); 0216 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMLN"); 0217 add(f); 0218 f = new Function("IMLOG2", func_imlog2); 0219 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMLOG2"); 0220 add(f); 0221 f = new Function("IMLOG10", func_imlog10); 0222 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMLOG10"); 0223 add(f); 0224 f = new Function("IMPOWER", func_impower); 0225 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMPOWER"); 0226 f->setParamCount(2); 0227 add(f); 0228 f = new Function("IMPRODUCT", func_improduct); 0229 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMPRODUCT"); 0230 f->setParamCount(1, -1); 0231 f->setAcceptArray(); 0232 add(f); 0233 f = new Function("IMREAL", func_complex_real); 0234 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMREAL"); 0235 add(f); 0236 f = new Function("IMSEC", func_imsec); 0237 add(f); 0238 f = new Function("IMSECH", func_imsech); 0239 add(f); 0240 f = new Function("IMSIN", func_imsin); 0241 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSIN"); 0242 add(f); 0243 f = new Function("IMSINH", func_imsinh); 0244 add(f); 0245 f = new Function("IMSQRT", func_imsqrt); 0246 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSQRT"); 0247 add(f); 0248 f = new Function("IMSUB", func_imsub); 0249 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSUB"); 0250 f->setParamCount(2); 0251 f->setAcceptArray(); 0252 add(f); 0253 f = new Function("IMSUM", func_imsum); 0254 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSUM"); 0255 f->setParamCount(1, -1); 0256 f->setAcceptArray(); 0257 add(f); 0258 f = new Function("IMTAN", func_imtan); 0259 add(f); 0260 f = new Function("IMTANH", func_imtanh); 0261 add(f); 0262 f = new Function("OCT2BIN", func_oct2bin); 0263 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETOCT2BIN"); 0264 f->setParamCount(1, 2); 0265 add(f); 0266 f = new Function("OCT2DEC", func_oct2dec); 0267 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETOCT2DEC"); 0268 add(f); 0269 f = new Function("OCT2HEX", func_oct2hex); 0270 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETOCT2HEX"); 0271 f->setParamCount(1, 2); 0272 add(f); 0273 } 0274 0275 QString EngineeringModule::descriptionFileName() const 0276 { 0277 return QString("engineering.xml"); 0278 } 0279 0280 0281 // 0282 // Function: BASE 0283 // 0284 Value func_base(valVector args, ValueCalc *calc, FuncExtra *) 0285 { 0286 int base = 10; 0287 int minLength = 0; 0288 if (args.count() > 1) 0289 base = calc->conv()->asInteger(args[1]).asInteger(); 0290 if (args.count() == 3) 0291 minLength = calc->conv()->asInteger(args[2]).asInteger(); 0292 0293 if ((base < 2) || (base > 36)) 0294 return Value::errorVALUE(); 0295 if (minLength < 0) minLength = 2; 0296 0297 return calc->base(args[0], base, 0, minLength); 0298 } 0299 0300 0301 // 0302 // Function: BESSELI 0303 // 0304 Value func_besseli(valVector args, ValueCalc *calc, FuncExtra *) 0305 { 0306 Value x = args[0]; 0307 Value y = args[1]; 0308 return calc->besseli(y, x); 0309 } 0310 0311 0312 // 0313 // Function: BESSELJ 0314 // 0315 Value func_besselj(valVector args, ValueCalc *calc, FuncExtra *) 0316 { 0317 Value x = args[0]; 0318 Value y = args[1]; 0319 return calc->besselj(y, x); 0320 } 0321 0322 0323 // 0324 // Function: BESSELK 0325 // 0326 Value func_besselk(valVector args, ValueCalc *calc, FuncExtra *) 0327 { 0328 Value x = args[0]; 0329 Value y = args[1]; 0330 return calc->besselk(y, x); 0331 } 0332 0333 0334 // 0335 // Function: BESSELY 0336 // 0337 Value func_bessely(valVector args, ValueCalc *calc, FuncExtra *) 0338 { 0339 Value x = args[0]; 0340 Value y = args[1]; 0341 return calc->besseln(y, x); 0342 } 0343 0344 0345 // 0346 // Function: DEC2HEX 0347 // 0348 Value func_dec2hex(valVector args, ValueCalc *calc, FuncExtra *) 0349 { 0350 QRegExp rx("[0-9]+"); 0351 int minLength = 0; 0352 if (args.count() > 1) 0353 // we have the optional "minimum length" argument 0354 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0355 0356 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0357 // this only contains decimal digits. 0358 return calc->base(args[0], 16, 0, minLength); 0359 } else { 0360 return Value::errorVALUE(); 0361 } 0362 } 0363 0364 0365 // 0366 // Function: DEC2OCT 0367 // 0368 Value func_dec2oct(valVector args, ValueCalc *calc, FuncExtra *) 0369 { 0370 QRegExp rx("[0-9]+"); 0371 int minLength = 0; 0372 if (args.count() > 1) 0373 // we have the optional "minimum length" argument 0374 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0375 0376 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0377 // this only contains decimal digits. 0378 return calc->base(args[0], 8, 0, minLength); 0379 } else { 0380 return Value::errorVALUE(); 0381 } 0382 } 0383 0384 0385 // 0386 // Function: DEC2BIN 0387 // 0388 Value func_dec2bin(valVector args, ValueCalc *calc, FuncExtra *) 0389 { 0390 QRegExp rx("[0-9]+"); 0391 int minLength = 0; 0392 if (args.count() > 1) 0393 // we have the optional "minimum length" argument 0394 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0395 0396 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0397 // this only contains decimal digits. 0398 return calc->base(args[0], 2, 0, minLength); 0399 } else { 0400 return Value::errorVALUE(); 0401 } 0402 } 0403 0404 0405 // 0406 // Function: BIN2DEC 0407 // 0408 Value func_bin2dec(valVector args, ValueCalc *calc, FuncExtra *) 0409 { 0410 return calc->fromBase(args[0], 2); 0411 } 0412 0413 0414 // 0415 // Function: BIN2OCT 0416 // 0417 Value func_bin2oct(valVector args, ValueCalc *calc, FuncExtra *) 0418 { 0419 QRegExp rx("[01]+"); 0420 int minLength = 0; 0421 if (args.count() > 1) 0422 // we have the optional "minimum length" argument 0423 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0424 0425 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0426 // this only contains 0s and 1s. 0427 return calc->base(calc->fromBase(args[0], 2), 8, 0, minLength); 0428 } else { 0429 return Value::errorVALUE(); 0430 } 0431 } 0432 0433 0434 // 0435 // Function: BIN2HEX 0436 // 0437 Value func_bin2hex(valVector args, ValueCalc *calc, FuncExtra *) 0438 { 0439 QRegExp rx("[01]+"); 0440 int minLength = 0; 0441 if (args.count() > 1) 0442 // we have the optional "minimum length" argument 0443 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0444 0445 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0446 // this only contains 0s and 1s. 0447 return calc->base(calc->fromBase(args[0], 2), 16, 0, minLength); 0448 } else { 0449 return Value::errorVALUE(); 0450 } 0451 0452 } 0453 0454 0455 // 0456 // Function: OCT2DEC 0457 // 0458 Value func_oct2dec(valVector args, ValueCalc *calc, FuncExtra *) 0459 { 0460 return calc->fromBase(args[0], 8); 0461 } 0462 0463 0464 // 0465 // Function: OCT2BIN 0466 // 0467 Value func_oct2bin(valVector args, ValueCalc *calc, FuncExtra *) 0468 { 0469 QRegExp rx("[01234567]+"); 0470 int minLength = 0; 0471 if (args.count() > 1) 0472 // we have the optional "minimum length" argument 0473 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0474 0475 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0476 // this only contains decimal digits. 0477 return calc->base(calc->fromBase(args[0], 8), 2, 0, minLength); 0478 } else { 0479 return Value::errorVALUE(); 0480 } 0481 } 0482 0483 0484 // 0485 // Function: OCT2HEX 0486 // 0487 Value func_oct2hex(valVector args, ValueCalc *calc, FuncExtra *) 0488 { 0489 QRegExp rx("[01234567]+"); 0490 int minLength = 0; 0491 if (args.count() > 1) 0492 // we have the optional "minimum length" argument 0493 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0494 0495 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0496 // this only contains decimal digits. 0497 return calc->base(calc->fromBase(args[0], 8), 16, 0, minLength); 0498 } else { 0499 return Value::errorVALUE(); 0500 } 0501 } 0502 0503 0504 // 0505 // Function: HEX2DEC 0506 // 0507 Value func_hex2dec(valVector args, ValueCalc *calc, FuncExtra *) 0508 { 0509 return calc->fromBase(args[0], 16); 0510 } 0511 0512 0513 // 0514 // Function: HEX2BIN 0515 // 0516 Value func_hex2bin(valVector args, ValueCalc *calc, FuncExtra *) 0517 { 0518 QRegExp rx("[0123456789ABCDEFabcdef]+"); 0519 int minLength = 0; 0520 if (args.count() > 1) 0521 // we have the optional "minimum length" argument 0522 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0523 0524 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0525 // this only contains decimal digits. 0526 return calc->base(calc->fromBase(args[0], 16), 2, 0, minLength); 0527 } else { 0528 return Value::errorVALUE(); 0529 } 0530 } 0531 0532 0533 // 0534 // Function: HEX2OCT 0535 // 0536 Value func_hex2oct(valVector args, ValueCalc *calc, FuncExtra *) 0537 { 0538 QRegExp rx("[0123456789ABCDEFabcdef]+"); 0539 int minLength = 0; 0540 if (args.count() > 1) 0541 // we have the optional "minimum length" argument 0542 minLength = calc->conv()->asInteger(args[1]).asInteger(); 0543 0544 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) { 0545 // this only contains decimal digits. 0546 return calc->base(calc->fromBase(args[0], 16), 8, 0, minLength); 0547 } else { 0548 return Value::errorVALUE(); 0549 } 0550 } 0551 0552 0553 // 0554 // Function: DECIMAL 0555 // 0556 Value func_decimal(valVector args, ValueCalc *calc, FuncExtra *) 0557 { 0558 QString text = calc->conv()->asString(args[0]).asString(); 0559 text.remove(QLatin1Char(' ')); 0560 text.remove(QLatin1Char('\t')); 0561 int radix = calc->conv()->asInteger(args[1]).asInteger(); 0562 if (radix == 16) { 0563 if (text.startsWith(QLatin1String("0x"), Qt::CaseInsensitive)) { 0564 text.remove(0, 2); 0565 } 0566 if (text.endsWith(QLatin1Char('h'), Qt::CaseInsensitive)) { 0567 text.chop(1); // all but the last char 0568 } 0569 } 0570 if (radix == 2) { 0571 if (text.endsWith(QLatin1Char('b'), Qt::CaseInsensitive)) { 0572 text.chop(1); // all but the last char 0573 } 0574 } 0575 0576 return calc->fromBase(Value(text), radix); 0577 } 0578 0579 // 0580 // convert prefix 0581 // 0582 0583 // check if unit may contain prefix, for example "kPa" is "Pa" with 0584 // return prefix factor found in unit, or 1.0 for no prefix 0585 // also modify the unit, i.e stripping the prefix from it 0586 // example: "kPa" will return 1e3 and change unit into "Pa" 0587 static double kspread_convert_prefix(QMap<QString, double> map, QString& unit) 0588 { 0589 if (map.contains(unit)) 0590 return 1.0; 0591 0592 // initialize prefix mapping if necessary 0593 static QMap<QString, double> prefixMap; 0594 if (prefixMap.isEmpty()) { 0595 prefixMap[ "Y" ] = 1e24; // yotta 0596 prefixMap[ "Z" ] = 1e21; // zetta 0597 prefixMap[ "E" ] = 1e18; // exa 0598 prefixMap[ "P" ] = 1e15; // peta 0599 prefixMap[ "T" ] = 1e12; // tera 0600 prefixMap[ "G" ] = 1e9; // giga 0601 prefixMap[ "M" ] = 1e6; // mega 0602 prefixMap[ "k" ] = 1e3; // kilo 0603 prefixMap[ "h" ] = 1e2; // hecto 0604 prefixMap[ "e" ] = 1e1; // deka 0605 prefixMap[ "da" ] = 1e1; // deka 0606 prefixMap[ "d" ] = 1e-1; // deci 0607 prefixMap[ "c" ] = 1e-2; // centi 0608 prefixMap[ "m" ] = 1e-3; // milli 0609 prefixMap[ "u" ] = 1e-6; // micro 0610 prefixMap[ "n" ] = 1e-9; // nano 0611 prefixMap[ "p" ] = 1e-12; // pico 0612 prefixMap[ "f" ] = 1e-15; // femto 0613 prefixMap[ "a" ] = 1e-18; // atto 0614 prefixMap[ "z" ] = 1e-21; // zepto 0615 prefixMap[ "y" ] = 1e-24; // yocto 0616 0617 // binary prefixes 0618 prefixMap[ "ki" ] = 1024.0 ; // kibi 0619 prefixMap[ "Mi" ] = 1048576.0 ; // mebi 0620 prefixMap[ "Gi" ] = 1073741824.0 ; // gibi 0621 prefixMap[ "Ti" ] = 1099511627776.0 ; // tebi 0622 prefixMap[ "Pi" ] = 1125899906842624.0 ; // pebi 0623 prefixMap[ "Ei" ] = 1152921504606846976.0 ; // exbi 0624 prefixMap[ "Zi" ] = 1180591620717411303424.0 ; // zebi 0625 prefixMap[ "Yi" ] = 1208925819614629174706176.0 ; // yobi 0626 } 0627 0628 // check for possible prefix 0629 QString prefix = unit.left(2).toLatin1(); 0630 0631 if (prefixMap.contains(prefix)) { 0632 unit.remove(0, 2); 0633 return prefixMap[prefix]; 0634 } else if (prefixMap.contains(prefix.left(1))) { 0635 unit.remove(0, 1); 0636 return prefixMap[prefix.left(1)]; 0637 } 0638 // fail miserably 0639 return 0.0; 0640 } 0641 0642 0643 // 0644 // convert masses 0645 // 0646 static bool kspread_convert_mass(const QString& fromUnit, 0647 const QString& toUnit, double value, double& result) 0648 { 0649 static QMap<QString, double> massMap; 0650 0651 // first-time initialization 0652 if (massMap.isEmpty()) { 0653 massMap[ "g" ] = 1.0; // Gram (the reference ) 0654 0655 massMap[ "sg" ] = 6.8522050005347800E-05; // Pieces 0656 massMap[ "lbm" ] = 2.2046229146913400E-03; // Pound 0657 massMap[ "u" ] = 6.0221370000000000E23; // U (atomic mass) 0658 massMap[ "ozm" ] = 3.5273971800362700E-02; // Ounce 0659 massMap[ "stone" ] = 1.574730e-04; // Stone 0660 massMap[ "ton" ] = 1.102311e-06; // Ton 0661 massMap[ "grain" ] = 1.543236E01; // Grain 0662 massMap[ "pweight" ] = 7.054792E-01; // Pennyweight 0663 massMap[ "hweight" ] = 1.968413E-05; // Hundredweight 0664 massMap[ "shweight" ] = 2.204623E-05; // Shorthundredweight 0665 massMap[ "uk_ton" ] = 1.0 / 2240 * 2.2046229146913400E-03; // It's long ton or Imperial ton, 2240 lbm. 0666 } 0667 0668 QString fromU = fromUnit; 0669 QString toU = toUnit; 0670 double fromPrefix = kspread_convert_prefix(massMap, fromU); 0671 double toPrefix = kspread_convert_prefix(massMap, toU); 0672 if (fromPrefix == 0.0) return false; 0673 if (toPrefix == 0.0) return false; 0674 if (!massMap.contains(fromU)) return false; 0675 if (!massMap.contains(toU)) return false; 0676 0677 result = value * fromPrefix * massMap[toU] / (massMap[fromU] * toPrefix); 0678 0679 return true; 0680 } 0681 0682 0683 // 0684 // convert distances 0685 // 0686 static bool kspread_convert_distance(const QString& fromUnit, 0687 const QString& toUnit, double value, double& result) 0688 { 0689 static QMap<QString, double> distanceMap; 0690 0691 // first-time initialization 0692 if (distanceMap.isEmpty()) { 0693 distanceMap[ "m" ] = 1.0; // meter (the reference) 0694 0695 distanceMap[ "ang" ] = 1e10; // Angstrom 0696 distanceMap[ "ell" ] = 1.0 / (45.0 * 0.0254); // Ell, exactly 45 international inches 0697 distanceMap[ "ft" ] = 1.0 / (12.0 * 0.0254); // feet 0698 distanceMap[ "in" ] = 1.0 / 0.0254; // inch 0699 distanceMap[ "lightyear" ] = 1.057023455773293e-16; // lightyear 0700 distanceMap[ "ly" ] = 1.057023455773293e-16; // lightyear 0701 distanceMap[ "mi" ] = 6.2137119223733397e-4; // mile 0702 distanceMap[ "Nmi" ] = 5.3995680345572354e-04; // nautical mile 0703 distanceMap[ "parsec" ] = 3.240779e-17; // Parsec 0704 distanceMap[ "pc" ] = 3.240779e-17; // Parsec 0705 distanceMap[ "Pica" ] = 1.0 * 72 / 0.0254; // Pica (1/72) inch 0706 distanceMap[ "statute_mi" ] = 1.0 / (6336000.0 / 3937.0); // U.S. survey mile aka U.S. statute mile 0707 distanceMap[ "yd" ] = 1.0 / (3.0 * 12.0 * 0.0254); // yard 0708 } 0709 0710 QString fromU = fromUnit; 0711 QString toU = toUnit; 0712 double fromPrefix = kspread_convert_prefix(distanceMap, fromU); 0713 double toPrefix = kspread_convert_prefix(distanceMap, toU); 0714 if (fromPrefix == 0.0) return false; 0715 if (toPrefix == 0.0) return false; 0716 if (!distanceMap.contains(fromU)) return false; 0717 if (!distanceMap.contains(toU)) return false; 0718 0719 result = value * fromPrefix * distanceMap[toU] / (distanceMap[fromU] * toPrefix); 0720 0721 return true; 0722 } 0723 0724 0725 // 0726 // convert pressures 0727 // 0728 static bool kspread_convert_pressure(const QString& fromUnit, 0729 const QString& toUnit, double value, double& result) 0730 { 0731 static QMap<QString, double> pressureMap; 0732 0733 // first-time initialization 0734 if (pressureMap.isEmpty()) { 0735 pressureMap[ "Pa" ] = 1.0; 0736 0737 pressureMap[ "atm" ] = 0.9869233e-5; // Atmosphere 0738 pressureMap[ "atm" ] = 0.9869233e-5; // Atmosphere 0739 pressureMap[ "mmHg" ] = 0.00750061708; // mm of Mercury 0740 pressureMap[ "psi" ] = 1 / 6894.754; // Pounds per square inch 0741 pressureMap[ "Torr" ] = 1 / 133.32237; // Torr, exactly 101325/760 Pa 0742 } 0743 0744 QString fromU = fromUnit; 0745 QString toU = toUnit; 0746 double fromPrefix = kspread_convert_prefix(pressureMap, fromU); 0747 double toPrefix = kspread_convert_prefix(pressureMap, toU); 0748 if (fromPrefix == 0.0) return false; 0749 if (toPrefix == 0.0) return false; 0750 if (!pressureMap.contains(fromU)) return false; 0751 if (!pressureMap.contains(toU)) return false; 0752 0753 result = value * fromPrefix * pressureMap[toU] / (pressureMap[fromU] * toPrefix); 0754 0755 return true; 0756 } 0757 0758 0759 // 0760 // convert forces 0761 // 0762 static bool kspread_convert_force(const QString& fromUnit, 0763 const QString& toUnit, double value, double& result) 0764 { 0765 static QMap<QString, double> forceMap; 0766 0767 // first-time initialization 0768 if (forceMap.isEmpty()) { 0769 forceMap[ "N" ] = 1.0; // Newton (reference) 0770 0771 forceMap[ "dy" ] = 1.0e5; // dyne 0772 forceMap[ "dyn" ] = 1.0e5; // dyne 0773 forceMap[ "lbf" ] = 1.0 / 4.448222; // Pound force (see "lbm" for pound mass) 0774 forceMap[ "pond" ] = 1.019716e2; // pond 0775 } 0776 0777 QString fromU = fromUnit; 0778 QString toU = toUnit; 0779 double fromPrefix = kspread_convert_prefix(forceMap, fromU); 0780 double toPrefix = kspread_convert_prefix(forceMap, toU); 0781 if (fromPrefix == 0.0) return false; 0782 if (toPrefix == 0.0) return false; 0783 if (!forceMap.contains(fromU)) return false; 0784 if (!forceMap.contains(toU)) return false; 0785 0786 result = value * fromPrefix * forceMap[toU] / (forceMap[fromU] * toPrefix); 0787 0788 return true; 0789 } 0790 0791 0792 // 0793 // convert energies 0794 // 0795 static bool kspread_convert_energy(const QString& fromUnit, 0796 const QString& toUnit, double value, double& result) 0797 { 0798 static QMap<QString, double> energyMap; 0799 0800 // first-time initialization 0801 if (energyMap.isEmpty()) { 0802 energyMap[ "J" ] = 1.0; // Joule (the reference) 0803 0804 energyMap[ "e" ] = 1.0e7; // erg 0805 energyMap[ "c" ] = 0.239006249473467; // thermodynamical calorie 0806 energyMap[ "cal" ] = 0.238846190642017; // calorie 0807 energyMap[ "eV" ] = 6.241457e+18; // electronvolt 0808 energyMap[ "HPh" ] = 3.72506111e-7; // horsepower-hour 0809 energyMap[ "Wh" ] = 0.000277778; // watt-hour 0810 energyMap[ "flb" ] = 23.73042222; 0811 energyMap[ "BTU" ] = 9.47815067349015e-4; // British Thermal Unit 0812 } 0813 0814 QString fromU = fromUnit; 0815 QString toU = toUnit; 0816 double fromPrefix = kspread_convert_prefix(energyMap, fromU); 0817 double toPrefix = kspread_convert_prefix(energyMap, toU); 0818 if (fromPrefix == 0.0) return false; 0819 if (toPrefix == 0.0) return false; 0820 if (!energyMap.contains(fromU)) return false; 0821 if (!energyMap.contains(toU)) return false; 0822 0823 result = value * fromPrefix * energyMap[toU] / (energyMap[fromU] * toPrefix); 0824 0825 return true; 0826 } 0827 0828 0829 // 0830 // convert powers 0831 // 0832 static bool kspread_convert_power(const QString& fromUnit, 0833 const QString& toUnit, double value, double& result) 0834 { 0835 static QMap<QString, double> powerMap; 0836 0837 // first-time initialization 0838 if (powerMap.isEmpty()) { 0839 powerMap[ "W" ] = 1.0; // Watt (the reference) 0840 0841 // powerMap[ "HP" ] = 1.341022e-3; // Horsepower 0842 powerMap[ "HP" ] = 1.0 / 745.701; // Horsepower (UK) 0843 powerMap[ "PS" ] = 1.359622e-3; // Pferdestaerke (German) 0844 } 0845 0846 QString fromU = fromUnit; 0847 QString toU = toUnit; 0848 double fromPrefix = kspread_convert_prefix(powerMap, fromU); 0849 double toPrefix = kspread_convert_prefix(powerMap, toU); 0850 if (fromPrefix == 0.0) return false; 0851 if (toPrefix == 0.0) return false; 0852 if (!powerMap.contains(fromU)) return false; 0853 if (!powerMap.contains(toU)) return false; 0854 0855 result = value * fromPrefix * powerMap[toU] / (powerMap[fromU] * toPrefix); 0856 0857 return true; 0858 } 0859 0860 0861 // 0862 // convert magnetism 0863 // 0864 static bool kspread_convert_magnetism(const QString& fromUnit, 0865 const QString& toUnit, double value, double& result) 0866 { 0867 static QMap<QString, double> magnetismMap; 0868 0869 // first-time initialization 0870 if (magnetismMap.isEmpty()) { 0871 magnetismMap[ "T" ] = 1.0; // Tesla (the reference) 0872 0873 magnetismMap[ "ga" ] = 1.0e4; // Gauss 0874 } 0875 0876 QString fromU = fromUnit; 0877 QString toU = toUnit; 0878 double fromPrefix = kspread_convert_prefix(magnetismMap, fromU); 0879 double toPrefix = kspread_convert_prefix(magnetismMap, toU); 0880 if (fromPrefix == 0.0) return false; 0881 if (toPrefix == 0.0) return false; 0882 if (!magnetismMap.contains(fromU)) return false; 0883 if (!magnetismMap.contains(toU)) return false; 0884 0885 result = value * fromPrefix * magnetismMap[toU] / (magnetismMap[fromU] * toPrefix); 0886 0887 return true; 0888 } 0889 0890 0891 // 0892 // convert temperatures 0893 // 0894 static bool kspread_convert_temperature(const QString& fromUnit, 0895 const QString& toUnit, double value, double& result) 0896 { 0897 static QMap<QString, double> tempFactorMap; 0898 static QMap<QString, double> tempOffsetMap; 0899 0900 // first-time initialization 0901 if (tempFactorMap.isEmpty() || tempOffsetMap.isEmpty()) { 0902 tempFactorMap[ "C" ] = 1.0; tempOffsetMap[ "C" ] = 0.0; 0903 tempFactorMap[ "F" ] = 5.0 / 9.0; tempOffsetMap[ "F" ] = -32.0; 0904 tempFactorMap[ "K" ] = 1.0; tempOffsetMap[ "K" ] = -273.15; 0905 } 0906 0907 if (!tempFactorMap.contains(fromUnit)) return false; 0908 if (!tempOffsetMap.contains(fromUnit)) return false; 0909 if (!tempFactorMap.contains(toUnit)) return false; 0910 if (!tempOffsetMap.contains(toUnit)) return false; 0911 0912 result = (value + tempOffsetMap[ fromUnit ]) * tempFactorMap[ fromUnit ]; 0913 result = (result / tempFactorMap[ toUnit ]) - tempOffsetMap[ toUnit ]; 0914 0915 return true; 0916 } 0917 0918 0919 // 0920 // convert volumes 0921 // 0922 static bool kspread_convert_volume(const QString& fromUnit, 0923 const QString& toUnit, double value, double& result) 0924 { 0925 static QMap<QString, double> volumeMap; 0926 0927 // first-time initialization 0928 if (volumeMap.isEmpty()) { 0929 volumeMap[ "l" ] = 1.0; // Liter (the reference) 0930 0931 //TODO ang3 0932 volumeMap[ "barrel" ] = 6.289811E-03; // barrel 0933 //TODO bushel 0934 volumeMap[ "cup" ] = 4.22583333333333; // cup 0935 volumeMap[ "ft3" ] = 3.5314666721488590e-2; // cubic foot 0936 volumeMap[ "gal" ] = 0.26411458333333; // gallone 0937 volumeMap[ "in3" ] = 6.1023744094732284e1; // cubic inch 0938 volumeMap[ "m3" ] = 1.0e-3; // cubic meter 0939 volumeMap[ "mi3" ] = 2.3991275857892772e-13; // cubic mile 0940 //TODO MTON 0941 volumeMap[ "Nmi3" ] = 1.5742621468581148e-13; // cubic Nautical mile 0942 volumeMap[ "oz" ] = 33.8066666666667; // ounce liquid 0943 //TODO Pica3 0944 volumeMap[ "pt" ] = 2.11291666666667; // pint 0945 volumeMap[ "qt" ] = 1.05645833333333; // quart 0946 volumeMap[ "GRT" ] = 2831.6846592; // Gross Register Ton 0947 volumeMap[ "regton" ] = volumeMap[ "GRT" ]; 0948 volumeMap[ "tbs" ] = 67.6133333333333; // sheetspoon 0949 volumeMap[ "tsp" ] = 202.84; // teaspoon 0950 //TODO tspm 0951 //TODO uk_pt 0952 volumeMap[ "yd3" ] = 1.3079506193143922; // cubic yard 0953 0954 } 0955 0956 QString fromU = fromUnit; 0957 QString toU = toUnit; 0958 double fromPrefix = kspread_convert_prefix(volumeMap, fromU); 0959 double toPrefix = kspread_convert_prefix(volumeMap, toU); 0960 if (fromPrefix == 0.0) return false; 0961 if (toPrefix == 0.0) return false; 0962 if (!volumeMap.contains(fromU)) return false; 0963 if (!volumeMap.contains(toU)) return false; 0964 0965 result = value * fromPrefix * volumeMap[toU] / (volumeMap[fromU] * toPrefix); 0966 0967 return true; 0968 } 0969 0970 0971 // 0972 // convert areas 0973 // 0974 static bool kspread_convert_area(const QString& fromUnit, 0975 const QString& toUnit, double value, double& result) 0976 { 0977 static QMap<QString, double> areaMap; 0978 0979 // first-time initialization 0980 if (areaMap.isEmpty()) { 0981 areaMap[ "m2" ] = 1.0; // square meter (the reference) 0982 areaMap[ "m^2" ] = 1.0; // square meter (the reference) 0983 0984 areaMap[ "acre" ] = 4.046856e3; // acre 0985 areaMap[ "ar" ] = 1.0 / 100; // are 0986 areaMap[ "ft2" ] = 1.0763910416709722e1; // square foot 0987 areaMap[ "ft^2" ] = 1.0763910416709722e1; // square foot 0988 areaMap[ "ha" ] = 1.0e4; // hectare 0989 areaMap[ "in2" ] = 1.5500031000062000e3; // square inch 0990 areaMap[ "in^2" ] = 1.5500031000062000e3; // square inch 0991 areaMap[ "mi2" ] = 3.8610215854244585e-7; // square mile 0992 areaMap[ "mi^2" ] = 3.8610215854244585e-7; // square mile 0993 areaMap[ "Nmi2" ] = 2.9155334959812286e-7; // square Nautical mile 0994 areaMap[ "Nmi^2" ] = 2.9155334959812286e-7; // square Nautical mile 0995 areaMap[ "yd2" ] = 1.0936132983377078; // square yard 0996 areaMap[ "yd^2" ] = 1.0936132983377078; // square yard 0997 } 0998 0999 QString fromU = fromUnit; 1000 QString toU = toUnit; 1001 double fromPrefix = kspread_convert_prefix(areaMap, fromU); 1002 double toPrefix = kspread_convert_prefix(areaMap, toU); 1003 if (fromPrefix == 0.0) return false; 1004 if (toPrefix == 0.0) return false; 1005 if (!areaMap.contains(fromU)) return false; 1006 if (!areaMap.contains(toU)) return false; 1007 1008 result = value * fromPrefix * areaMap[toU] / (areaMap[fromU] * toPrefix); 1009 1010 return true; 1011 } 1012 1013 1014 // 1015 // convert speeds 1016 // 1017 static bool kspread_convert_speed(const QString& fromUnit, 1018 const QString& toUnit, double value, double& result) 1019 { 1020 static QMap<QString, double> speedMap; 1021 1022 // first-time initialization 1023 if (speedMap.isEmpty()) { 1024 speedMap[ "m/s" ] = 1.0; // meters per second (the reference) 1025 1026 speedMap[ "m/h" ] = 3.6e3; // meters per hour 1027 speedMap[ "mph" ] = 2.2369362920544023; // miles per hour 1028 speedMap[ "kn" ] = 1.9438444924406048; // knot 1029 } 1030 1031 QString fromU = fromUnit; 1032 QString toU = toUnit; 1033 double fromPrefix = kspread_convert_prefix(speedMap, fromU); 1034 double toPrefix = kspread_convert_prefix(speedMap, toU); 1035 if (fromPrefix == 0.0) return false; 1036 if (toPrefix == 0.0) return false; 1037 if (!speedMap.contains(fromU)) return false; 1038 if (!speedMap.contains(toU)) return false; 1039 1040 result = value * fromPrefix * speedMap[toU] / (speedMap[fromU] * toPrefix); 1041 1042 return true; 1043 } 1044 1045 1046 // 1047 // convert times 1048 // 1049 static bool kspread_convert_time(const QString& fromUnit, 1050 const QString& toUnit, double value, double& result) 1051 { 1052 static QMap<QString, double> timeMap; 1053 1054 // first-time initialization 1055 if (timeMap.isEmpty()) { 1056 timeMap[ "s" ] = 1.0; // second (the reference) 1057 timeMap[ "sec" ] = 1.0; // second (the reference) 1058 1059 timeMap[ "mn" ] = 1.0 / 60; // 24 hour per day 1060 timeMap[ "min" ] = 1.0 / 60; // 24 hour per day 1061 timeMap[ "hr" ] = 1.0 / 3600; // 3600 seconds per hour 1062 timeMap[ "d" ] = 1.0 / (3600 * 24); // 24 hour per day 1063 timeMap[ "day" ] = 1.0 / (3600 * 24); // 24 hour per day 1064 timeMap[ "yr" ] = 1.0 / (3600 * 24 * 365.25); // 24 hour per day 1065 } 1066 1067 QString fromU = fromUnit; 1068 QString toU = toUnit; 1069 double fromPrefix = kspread_convert_prefix(timeMap, fromU); 1070 double toPrefix = kspread_convert_prefix(timeMap, toU); 1071 if (fromPrefix == 0.0) return false; 1072 if (toPrefix == 0.0) return false; 1073 if (!timeMap.contains(fromU)) return false; 1074 if (!timeMap.contains(toU)) return false; 1075 1076 result = value * fromPrefix * timeMap[toU] / (timeMap[fromU] * toPrefix); 1077 1078 return true; 1079 } 1080 1081 1082 // 1083 // convert IT 1084 // 1085 static bool kspread_convert_info(const QString& fromUnit, 1086 const QString& toUnit, double value, double& result) 1087 { 1088 static QMap<QString, double> infoMap; 1089 1090 // first-time initialization 1091 if (infoMap.isEmpty()) { 1092 infoMap[ "bit" ] = 1.0; // bit (the reference) 1093 infoMap[ "byte" ] = 1.0 / 8; // 8 bit per byte 1094 } 1095 1096 QString fromU = fromUnit; 1097 QString toU = toUnit; 1098 double fromPrefix = kspread_convert_prefix(infoMap, fromU); 1099 double toPrefix = kspread_convert_prefix(infoMap, toU); 1100 if (fromPrefix == 0.0) return false; 1101 if (toPrefix == 0.0) return false; 1102 if (!infoMap.contains(fromU)) return false; 1103 if (!infoMap.contains(toU)) return false; 1104 1105 result = value * fromPrefix * infoMap[toU] / (infoMap[fromU] * toPrefix); 1106 1107 return true; 1108 } 1109 1110 // 1111 // Function: CONVERT 1112 // 1113 Value func_convert(valVector args, ValueCalc *calc, FuncExtra *) 1114 { 1115 // This function won't support arbitrary precision. 1116 1117 double value = numToDouble(calc->conv()->toFloat(args[0])); 1118 QString fromUnit = calc->conv()->toString(args[1]); 1119 QString toUnit = calc->conv()->toString(args[2]); 1120 1121 double result = value; 1122 1123 if (!kspread_convert_mass(fromUnit, toUnit, value, result)) 1124 if (!kspread_convert_distance(fromUnit, toUnit, value, result)) 1125 if (!kspread_convert_pressure(fromUnit, toUnit, value, result)) 1126 if (!kspread_convert_force(fromUnit, toUnit, value, result)) 1127 if (!kspread_convert_energy(fromUnit, toUnit, value, result)) 1128 if (!kspread_convert_power(fromUnit, toUnit, value, result)) 1129 if (!kspread_convert_magnetism(fromUnit, toUnit, value, result)) 1130 if (!kspread_convert_temperature(fromUnit, toUnit, value, result)) 1131 if (!kspread_convert_volume(fromUnit, toUnit, value, result)) 1132 if (!kspread_convert_area(fromUnit, toUnit, value, result)) 1133 if (!kspread_convert_speed(fromUnit, toUnit, value, result)) 1134 if (!kspread_convert_time(fromUnit, toUnit, value, result)) 1135 if (!kspread_convert_info(fromUnit, toUnit, value, result)) 1136 return Value::errorNA(); 1137 1138 return Value(result); 1139 } 1140 1141 1142 // functions operating over complex numbers ... 1143 // these may eventually end up being merged into ValueCalc and friends 1144 // then complex numbers will be handled transparently in most functions 1145 1146 1147 // 1148 // Function: COMPLEX 1149 // 1150 Value func_complex(valVector args, ValueCalc *calc, FuncExtra *) 1151 { 1152 const double real = numToDouble(calc->conv()->toFloat(args[0])); 1153 const double imag = numToDouble(calc->conv()->toFloat(args[1])); 1154 return Value(complex<Number>(real, imag)); 1155 } 1156 1157 1158 // 1159 // Function: IMAGINARY 1160 // 1161 Value func_complex_imag(valVector args, ValueCalc *calc, FuncExtra *) 1162 { 1163 return Value(calc->conv()->toComplex(args[0]).imag()); 1164 } 1165 1166 1167 // 1168 // Function: IMREAL 1169 // 1170 Value func_complex_real(valVector args, ValueCalc *calc, FuncExtra *) 1171 { 1172 return Value(calc->conv()->toComplex(args[0]).real()); 1173 } 1174 1175 1176 // 1177 // 1178 // 1179 void awImSum(ValueCalc *c, Value &res, Value val, Value) 1180 { 1181 const complex<Number> c1 = c->conv()->toComplex(res); 1182 const complex<Number> c2 = c->conv()->toComplex(val); 1183 res = Value(c1 + c2); 1184 } 1185 1186 1187 // 1188 // 1189 // 1190 void awImSub(ValueCalc *c, Value &res, Value val, Value) 1191 { 1192 const complex<Number> c1 = c->conv()->toComplex(res); 1193 const complex<Number> c2 = c->conv()->toComplex(val); 1194 res = Value(c1 - c2); 1195 } 1196 1197 1198 // 1199 // 1200 // 1201 void awImMul(ValueCalc *c, Value &res, Value val, Value) 1202 { 1203 const complex<Number> c1 = c->conv()->toComplex(res); 1204 const complex<Number> c2 = c->conv()->toComplex(val); 1205 res = Value(c1 * c2); 1206 } 1207 1208 1209 // 1210 // 1211 // 1212 void awImDiv(ValueCalc *c, Value &res, Value val, Value) 1213 { 1214 const complex<Number> c1 = c->conv()->toComplex(res); 1215 const complex<Number> c2 = c->conv()->toComplex(val); 1216 res = Value(c1 / c2); 1217 } 1218 1219 // 1220 // Function: IMSUM 1221 // 1222 Value func_imsum(valVector args, ValueCalc *calc, FuncExtra *) 1223 { 1224 Value result; 1225 calc->arrayWalk(args, result, awImSum, Value(0)); 1226 return result; 1227 } 1228 1229 1230 // 1231 // Function: IMSUB 1232 // 1233 Value func_imsub(valVector args, ValueCalc *calc, FuncExtra *) 1234 { 1235 Value result; 1236 if (args.count() == 1) 1237 awImSub(calc, result, args[0], Value(0)); 1238 else { 1239 result = args[0]; 1240 valVector vector = args.mid(1); 1241 calc->arrayWalk(vector, result, awImSub, Value(0)); 1242 } 1243 return result; 1244 } 1245 1246 1247 // 1248 // Function: IMPRODUCT 1249 // 1250 Value func_improduct(valVector args, ValueCalc *calc, FuncExtra *) 1251 { 1252 Value result; 1253 if (args.count() == 1) { 1254 result = Value(complex<double>(1.0, 0.0)); 1255 awImMul(calc, result, args[0], Value(0)); 1256 } else { 1257 result = args[0]; 1258 valVector vector = args.mid(1); 1259 calc->arrayWalk(vector, result, awImMul, Value(0)); 1260 } 1261 return result; 1262 } 1263 1264 1265 // 1266 // Function: IMDIV 1267 // 1268 Value func_imdiv(valVector args, ValueCalc *calc, FuncExtra *) 1269 { 1270 Value result; 1271 if (args.count() == 1) { 1272 result = Value(complex<double>(1.0, 0.0)); 1273 awImDiv(calc, result, args[0], Value(0)); 1274 } else { 1275 result = args[0]; 1276 valVector vector = args.mid(1); 1277 calc->arrayWalk(vector, result, awImDiv, Value(0)); 1278 } 1279 return result; 1280 } 1281 1282 1283 // 1284 // Function: IMCONJUGATE 1285 // 1286 Value func_imconjugate(valVector args, ValueCalc *calc, FuncExtra *) 1287 { 1288 return Value(std::conj(calc->conv()->asComplex(args[0]).asComplex())); 1289 } 1290 1291 1292 // 1293 // Function: IMARGUMENT 1294 // 1295 Value func_imargument(valVector args, ValueCalc *calc, FuncExtra *) 1296 { 1297 return Value(std::arg(calc->conv()->asComplex(args[0]).asComplex())); 1298 } 1299 1300 1301 // 1302 // Function: IMABS 1303 // 1304 Value func_imabs(valVector args, ValueCalc *calc, FuncExtra *) 1305 { 1306 return Value(std::abs(calc->conv()->asComplex(args[0]).asComplex())); 1307 } 1308 1309 1310 // 1311 // Function: IMCOS 1312 // 1313 Value func_imcos(valVector args, ValueCalc *calc, FuncExtra *) 1314 { 1315 return Value(std::cos(calc->conv()->asComplex(args[0]).asComplex())); 1316 } 1317 1318 1319 // 1320 // Function: IMCOT 1321 // 1322 Value func_imcot(valVector args, ValueCalc *calc, FuncExtra*) 1323 { 1324 return Value(std::cos(calc->conv()->asComplex(args[0]).asComplex()) 1325 /std::sin(calc->conv()->asComplex(args[0]).asComplex())); 1326 } 1327 1328 1329 // 1330 // Function: IMCSC 1331 // 1332 Value func_imcsc(valVector args, ValueCalc *calc, FuncExtra *) 1333 { 1334 return Value(complex<Number>(1)/std::sin(calc->conv()->asComplex(args[0]).asComplex())); 1335 } 1336 1337 1338 // 1339 // Function: IMSEC 1340 // 1341 Value func_imsec(valVector args, ValueCalc *calc, FuncExtra *) 1342 { 1343 return Value(complex<Number>(1)/std::cos(calc->conv()->asComplex(args[0]).asComplex())); 1344 } 1345 1346 1347 // 1348 // Function: IMSIN 1349 // 1350 Value func_imsin(valVector args, ValueCalc *calc, FuncExtra *) 1351 { 1352 return Value(std::sin(calc->conv()->asComplex(args[0]).asComplex())); 1353 } 1354 1355 1356 // 1357 // Function: IMTAN 1358 // 1359 Value func_imtan(valVector args, ValueCalc *calc, FuncExtra*) 1360 { 1361 return Value(std::tan(calc->conv()->asComplex(args[0]).asComplex())); 1362 } 1363 1364 1365 // 1366 // Function: IMCOSH 1367 // 1368 Value func_imcosh(valVector args, ValueCalc *calc, FuncExtra*) 1369 { 1370 return Value(std::cosh(calc->conv()->asComplex(args[0]).asComplex())); 1371 } 1372 1373 1374 // 1375 // Function: IMCSCH 1376 // 1377 Value func_imcsch(valVector args, ValueCalc *calc, FuncExtra*) 1378 { 1379 return Value(complex<Number>(1)/std::sinh(calc->conv()->asComplex(args[0]).asComplex())); 1380 } 1381 1382 1383 // 1384 // Function: IMSECH 1385 // 1386 Value func_imsech(valVector args, ValueCalc *calc, FuncExtra *) 1387 { 1388 return Value(complex<Number>(1)/std::cosh(calc->conv()->asComplex(args[0]).asComplex())); 1389 } 1390 1391 1392 // 1393 // Function: IMSINH 1394 // 1395 Value func_imsinh(valVector args, ValueCalc *calc, FuncExtra*) 1396 { 1397 return Value(std::sinh(calc->conv()->asComplex(args[0]).asComplex())); 1398 } 1399 1400 1401 // 1402 // Function: IMTANH 1403 // 1404 Value func_imtanh(valVector args, ValueCalc *calc, FuncExtra*) 1405 { 1406 return Value(std::tanh(calc->conv()->asComplex(args[0]).asComplex())); 1407 } 1408 1409 1410 // 1411 // Function: IMLN 1412 // 1413 Value func_imln(valVector args, ValueCalc *calc, FuncExtra *) 1414 { 1415 return Value(std::log(calc->conv()->asComplex(args[0]).asComplex())); 1416 } 1417 1418 1419 // 1420 // Function: IMLOG2 1421 // 1422 Value func_imlog2(valVector args, ValueCalc *calc, FuncExtra *) 1423 { 1424 return Value(std::log(calc->conv()->toComplex(args[0])) / static_cast<Number>(double(M_LN2l))); 1425 } 1426 1427 1428 // 1429 // Function: IMLOG10 1430 // 1431 Value func_imlog10(valVector args, ValueCalc *calc, FuncExtra *) 1432 { 1433 return Value(std::log10(calc->conv()->toComplex(args[0]))); 1434 } 1435 1436 1437 // 1438 // Function: IMEXP 1439 // 1440 Value func_imexp(valVector args, ValueCalc *calc, FuncExtra *) 1441 { 1442 return Value(std::exp(calc->conv()->toComplex(args[0]))); 1443 } 1444 1445 1446 // 1447 // Function: IMSQRT 1448 // 1449 Value func_imsqrt(valVector args, ValueCalc *calc, FuncExtra *) 1450 { 1451 return Value(std::sqrt(calc->conv()->toComplex(args[0]))); 1452 } 1453 1454 1455 // 1456 // Function: IMPOWER 1457 // 1458 Value func_impower(valVector args, ValueCalc *calc, FuncExtra *) 1459 { 1460 return Value(std::pow(calc->conv()->toComplex(args[0]), 1461 calc->conv()->toComplex(args[1]))); 1462 } 1463 1464 1465 // 1466 // Function: DELTA 1467 // 1468 Value func_delta(valVector args, ValueCalc *calc, FuncExtra *) 1469 { 1470 Value val1 = args[0]; 1471 Value val2 = Value(0.0); 1472 if (args.count() == 2) 1473 val2 = args[1]; 1474 1475 return Value(calc->approxEqual(val1, val2) ? 1 : 0); 1476 } 1477 1478 1479 // 1480 // Function: ERF 1481 // 1482 Value func_erf(valVector args, ValueCalc *calc, FuncExtra *) 1483 { 1484 if (args.count() == 2) 1485 return calc->sub(calc->erf(args[1]), calc->erf(args[0])); 1486 return calc->erf(args[0]); 1487 } 1488 1489 1490 // 1491 // Function: ERFC 1492 // 1493 Value func_erfc(valVector args, ValueCalc *calc, FuncExtra *) 1494 { 1495 if (args.count() == 2) 1496 return calc->sub(calc->erfc(args[1]), calc->erfc(args[0])); 1497 return calc->erfc(args[0]); 1498 } 1499 1500 1501 // 1502 // Function: GESTEP 1503 // 1504 Value func_gestep(valVector args, ValueCalc *calc, FuncExtra *) 1505 { 1506 Value x = args[0]; 1507 Value y = Value(0.0); 1508 if (args.count() == 2) 1509 y = args[1]; 1510 1511 if (x.isString() || y.isString()) 1512 return Value::errorNUM(); 1513 1514 int result = 0; 1515 if (calc->greater(x, y) || calc->approxEqual(x, y)) 1516 result = 1; 1517 1518 return Value(result); 1519 } 1520 1521 #include "engineering.moc"