1 /* This file is part of the KDE project
2 Copyright (C) 1998-2002 The KSpread Team <calligra-devel@kde.org>
3 Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
4 Copyright 2007 Sascha Pfau <MrPeacock@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; only
9 version 2 of the License.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20 */
21
22 // built-in engineering functions
23
24 #include "EngineeringModule.h"
25
26 #include "Function.h"
27 #include "FunctionModuleRegistry.h"
28 #include "ValueCalc.h"
29 #include "ValueConverter.h"
30
31 // used by the CONVERT function
32 #include <QMap>
33
34 // these are needed for complex functions, while we handle them in the old way
35 #include <math.h>
36
37 #ifndef M_LN2l
38 #define M_LN2l 0.6931471805599453094172321214581766L
39 #endif
40
41 using namespace Calligra::Sheets;
42
43 // prototypes (sort alphabetically)
44 Value func_base(valVector args, ValueCalc *calc, FuncExtra *);
45 Value func_besseli(valVector args, ValueCalc *calc, FuncExtra *);
46 Value func_besselj(valVector args, ValueCalc *calc, FuncExtra *);
47 Value func_besselk(valVector args, ValueCalc *calc, FuncExtra *);
48 Value func_bessely(valVector args, ValueCalc *calc, FuncExtra *);
49 Value func_bin2dec(valVector args, ValueCalc *calc, FuncExtra *);
50 Value func_bin2oct(valVector args, ValueCalc *calc, FuncExtra *);
51 Value func_bin2hex(valVector args, ValueCalc *calc, FuncExtra *);
52 Value func_complex(valVector args, ValueCalc *calc, FuncExtra *);
53 Value func_complex_imag(valVector args, ValueCalc *calc, FuncExtra *);
54 Value func_complex_real(valVector args, ValueCalc *calc, FuncExtra *);
55 Value func_convert(valVector args, ValueCalc *calc, FuncExtra *);
56 Value func_dec2hex(valVector args, ValueCalc *calc, FuncExtra *);
57 Value func_dec2oct(valVector args, ValueCalc *calc, FuncExtra *);
58 Value func_dec2bin(valVector args, ValueCalc *calc, FuncExtra *);
59 Value func_decimal(valVector args, ValueCalc *calc, FuncExtra *);
60 Value func_delta(valVector args, ValueCalc *calc, FuncExtra *);
61 Value func_erf(valVector args, ValueCalc *calc, FuncExtra *);
62 Value func_erfc(valVector args, ValueCalc *calc, FuncExtra *);
63 Value func_gestep(valVector args, ValueCalc *calc, FuncExtra *);
64 Value func_hex2dec(valVector args, ValueCalc *calc, FuncExtra *);
65 Value func_hex2bin(valVector args, ValueCalc *calc, FuncExtra *);
66 Value func_hex2oct(valVector args, ValueCalc *calc, FuncExtra *);
67 Value func_imabs(valVector args, ValueCalc *calc, FuncExtra *);
68 Value func_imargument(valVector args, ValueCalc *calc, FuncExtra *);
69 Value func_imconjugate(valVector args, ValueCalc *calc, FuncExtra *);
70 Value func_imcos(valVector args, ValueCalc *calc, FuncExtra *);
71 Value func_imcosh(valVector args, ValueCalc *calc, FuncExtra *);
72 Value func_imcot(valVector args, ValueCalc *calc, FuncExtra *);
73 Value func_imcsc(valVector args, ValueCalc *calc, FuncExtra *);
74 Value func_imcsch(valVector args, ValueCalc *calc, FuncExtra *);
75 Value func_imdiv(valVector args, ValueCalc *calc, FuncExtra *);
76 Value func_imexp(valVector args, ValueCalc *calc, FuncExtra *);
77 Value func_imln(valVector args, ValueCalc *calc, FuncExtra *);
78 Value func_imlog2(valVector args, ValueCalc *calc, FuncExtra *);
79 Value func_imlog10(valVector args, ValueCalc *calc, FuncExtra *);
80 Value func_impower(valVector args, ValueCalc *calc, FuncExtra *);
81 Value func_improduct(valVector args, ValueCalc *calc, FuncExtra *);
82 Value func_imsec(valVector args, ValueCalc *calc, FuncExtra *);
83 Value func_imsech(valVector args, ValueCalc *calc, FuncExtra *);
84 Value func_imsin(valVector args, ValueCalc *calc, FuncExtra *);
85 Value func_imsinh(valVector args, ValueCalc *calc, FuncExtra *);
86 Value func_imsqrt(valVector args, ValueCalc *calc, FuncExtra *);
87 Value func_imsub(valVector args, ValueCalc *calc, FuncExtra *);
88 Value func_imsum(valVector args, ValueCalc *calc, FuncExtra *);
89 Value func_imtan(valVector args, ValueCalc *calc, FuncExtra *);
90 Value func_imtanh(valVector args, ValueCalc *calc, FuncExtra *);
91 Value func_oct2dec(valVector args, ValueCalc *calc, FuncExtra *);
92 Value func_oct2bin(valVector args, ValueCalc *calc, FuncExtra *);
93 Value func_oct2hex(valVector args, ValueCalc *calc, FuncExtra *);
94
95
96 CALLIGRA_SHEETS_EXPORT_FUNCTION_MODULE("kspreadengineeringmodule.json", EngineeringModule)
97
98
EngineeringModule(QObject * parent,const QVariantList &)99 EngineeringModule::EngineeringModule(QObject* parent, const QVariantList&)
100 : FunctionModule(parent)
101 {
102 Function *f;
103
104 f = new Function("BASE", func_base); // Calligra Sheets-specific, like in Quattro-Pro
105 f->setParamCount(1, 3);
106 add(f);
107 f = new Function("BESSELI", func_besseli);
108 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELI");
109 f->setParamCount(2);
110 add(f);
111 f = new Function("BESSELJ", func_besselj);
112 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELJ");
113 f->setParamCount(2);
114 add(f);
115 f = new Function("BESSELK", func_besselk);
116 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELK");
117 f->setParamCount(2);
118 add(f);
119 f = new Function("BESSELY", func_bessely);
120 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBESSELY");
121 f->setParamCount(2);
122 add(f);
123 f = new Function("BIN2DEC", func_bin2dec);
124 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBIN2DEC");
125 add(f);
126 f = new Function("BIN2OCT", func_bin2oct);
127 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBIN2OCT");
128 f->setParamCount(1, 2);
129 add(f);
130 f = new Function("BIN2HEX", func_bin2hex);
131 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETBIN2HEX");
132 f->setParamCount(1, 2);
133 add(f);
134 f = new Function("COMPLEX", func_complex);
135 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETCOMPLEX");
136 f->setParamCount(2, 3);
137 add(f);
138 f = new Function("CONVERT", func_convert);
139 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETCONVERT");
140 f->setParamCount(3);
141 add(f);
142 f = new Function("DEC2HEX", func_dec2hex);
143 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDEC2HEX");
144 f->setParamCount(1, 2);
145 add(f);
146 f = new Function("DEC2BIN", func_dec2bin);
147 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDEC2BIN");
148 f->setParamCount(1, 2);
149 add(f);
150 f = new Function("DEC2OCT", func_dec2oct);
151 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDEC2OCT");
152 f->setParamCount(1, 2);
153 add(f);
154 f = new Function("DECIMAL", func_decimal);
155 f->setParamCount(2);
156 add(f);
157 f = new Function("DELTA", func_delta);
158 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETDELTA");
159 f->setParamCount(1, 2);
160 add(f);
161 f = new Function("ERF", func_erf);
162 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETERF");
163 f->setParamCount(1, 2);
164 add(f);
165 f = new Function("ERFC", func_erfc);
166 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETERFC");
167 f->setParamCount(1, 2);
168 add(f);
169 f = new Function("GESTEP", func_gestep);
170 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETGESTEP");
171 f->setParamCount(1, 2);
172 add(f);
173 f = new Function("HEX2BIN", func_hex2bin);
174 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETHEX2BIN");
175 f->setParamCount(1, 2);
176 add(f);
177 f = new Function("HEX2DEC", func_hex2dec);
178 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETHEX2DEC");
179 add(f);
180 f = new Function("HEX2OCT", func_hex2oct);
181 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETHEX2OCT");
182 f->setParamCount(1, 2);
183 add(f);
184 f = new Function("IMABS", func_imabs);
185 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMABS");
186 add(f);
187 f = new Function("IMAGINARY", func_complex_imag);
188 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMAGINARY");
189 add(f);
190 f = new Function("IMARGUMENT", func_imargument);
191 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMARGUMENT");
192 add(f);
193 f = new Function("IMCONJUGATE", func_imconjugate);
194 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMCONJUGATE");
195 add(f);
196 f = new Function("IMCOS", func_imcos);
197 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMCOS");
198 add(f);
199 f = new Function("IMCOSH", func_imcosh);
200 add(f);
201 f = new Function("IMCOT", func_imcot);
202 add(f);
203 f = new Function("IMCSC", func_imcsc);
204 add(f);
205 f = new Function("IMCSCH", func_imcsch);
206 add(f);
207 f = new Function("IMDIV", func_imdiv);
208 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMDIV");
209 f->setParamCount(2);
210 f->setAcceptArray();
211 add(f);
212 f = new Function("IMEXP", func_imexp);
213 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMEXP");
214 add(f);
215 f = new Function("IMLN", func_imln);
216 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMLN");
217 add(f);
218 f = new Function("IMLOG2", func_imlog2);
219 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMLOG2");
220 add(f);
221 f = new Function("IMLOG10", func_imlog10);
222 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMLOG10");
223 add(f);
224 f = new Function("IMPOWER", func_impower);
225 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMPOWER");
226 f->setParamCount(2);
227 add(f);
228 f = new Function("IMPRODUCT", func_improduct);
229 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMPRODUCT");
230 f->setParamCount(1, -1);
231 f->setAcceptArray();
232 add(f);
233 f = new Function("IMREAL", func_complex_real);
234 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMREAL");
235 add(f);
236 f = new Function("IMSEC", func_imsec);
237 add(f);
238 f = new Function("IMSECH", func_imsech);
239 add(f);
240 f = new Function("IMSIN", func_imsin);
241 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSIN");
242 add(f);
243 f = new Function("IMSINH", func_imsinh);
244 add(f);
245 f = new Function("IMSQRT", func_imsqrt);
246 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSQRT");
247 add(f);
248 f = new Function("IMSUB", func_imsub);
249 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSUB");
250 f->setParamCount(2);
251 f->setAcceptArray();
252 add(f);
253 f = new Function("IMSUM", func_imsum);
254 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETIMSUM");
255 f->setParamCount(1, -1);
256 f->setAcceptArray();
257 add(f);
258 f = new Function("IMTAN", func_imtan);
259 add(f);
260 f = new Function("IMTANH", func_imtanh);
261 add(f);
262 f = new Function("OCT2BIN", func_oct2bin);
263 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETOCT2BIN");
264 f->setParamCount(1, 2);
265 add(f);
266 f = new Function("OCT2DEC", func_oct2dec);
267 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETOCT2DEC");
268 add(f);
269 f = new Function("OCT2HEX", func_oct2hex);
270 f->setAlternateName("COM.SUN.STAR.SHEET.ADDIN.ANALYSIS.GETOCT2HEX");
271 f->setParamCount(1, 2);
272 add(f);
273 }
274
descriptionFileName() const275 QString EngineeringModule::descriptionFileName() const
276 {
277 return QString("engineering.xml");
278 }
279
280
281 //
282 // Function: BASE
283 //
func_base(valVector args,ValueCalc * calc,FuncExtra *)284 Value func_base(valVector args, ValueCalc *calc, FuncExtra *)
285 {
286 int base = 10;
287 int minLength = 0;
288 if (args.count() > 1)
289 base = calc->conv()->asInteger(args[1]).asInteger();
290 if (args.count() == 3)
291 minLength = calc->conv()->asInteger(args[2]).asInteger();
292
293 if ((base < 2) || (base > 36))
294 return Value::errorVALUE();
295 if (minLength < 0) minLength = 2;
296
297 return calc->base(args[0], base, 0, minLength);
298 }
299
300
301 //
302 // Function: BESSELI
303 //
func_besseli(valVector args,ValueCalc * calc,FuncExtra *)304 Value func_besseli(valVector args, ValueCalc *calc, FuncExtra *)
305 {
306 Value x = args[0];
307 Value y = args[1];
308 return calc->besseli(y, x);
309 }
310
311
312 //
313 // Function: BESSELJ
314 //
func_besselj(valVector args,ValueCalc * calc,FuncExtra *)315 Value func_besselj(valVector args, ValueCalc *calc, FuncExtra *)
316 {
317 Value x = args[0];
318 Value y = args[1];
319 return calc->besselj(y, x);
320 }
321
322
323 //
324 // Function: BESSELK
325 //
func_besselk(valVector args,ValueCalc * calc,FuncExtra *)326 Value func_besselk(valVector args, ValueCalc *calc, FuncExtra *)
327 {
328 Value x = args[0];
329 Value y = args[1];
330 return calc->besselk(y, x);
331 }
332
333
334 //
335 // Function: BESSELY
336 //
func_bessely(valVector args,ValueCalc * calc,FuncExtra *)337 Value func_bessely(valVector args, ValueCalc *calc, FuncExtra *)
338 {
339 Value x = args[0];
340 Value y = args[1];
341 return calc->besseln(y, x);
342 }
343
344
345 //
346 // Function: DEC2HEX
347 //
func_dec2hex(valVector args,ValueCalc * calc,FuncExtra *)348 Value func_dec2hex(valVector args, ValueCalc *calc, FuncExtra *)
349 {
350 QRegExp rx("[0-9]+");
351 int minLength = 0;
352 if (args.count() > 1)
353 // we have the optional "minimum length" argument
354 minLength = calc->conv()->asInteger(args[1]).asInteger();
355
356 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
357 // this only contains decimal digits.
358 return calc->base(args[0], 16, 0, minLength);
359 } else {
360 return Value::errorVALUE();
361 }
362 }
363
364
365 //
366 // Function: DEC2OCT
367 //
func_dec2oct(valVector args,ValueCalc * calc,FuncExtra *)368 Value func_dec2oct(valVector args, ValueCalc *calc, FuncExtra *)
369 {
370 QRegExp rx("[0-9]+");
371 int minLength = 0;
372 if (args.count() > 1)
373 // we have the optional "minimum length" argument
374 minLength = calc->conv()->asInteger(args[1]).asInteger();
375
376 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
377 // this only contains decimal digits.
378 return calc->base(args[0], 8, 0, minLength);
379 } else {
380 return Value::errorVALUE();
381 }
382 }
383
384
385 //
386 // Function: DEC2BIN
387 //
func_dec2bin(valVector args,ValueCalc * calc,FuncExtra *)388 Value func_dec2bin(valVector args, ValueCalc *calc, FuncExtra *)
389 {
390 QRegExp rx("[0-9]+");
391 int minLength = 0;
392 if (args.count() > 1)
393 // we have the optional "minimum length" argument
394 minLength = calc->conv()->asInteger(args[1]).asInteger();
395
396 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
397 // this only contains decimal digits.
398 return calc->base(args[0], 2, 0, minLength);
399 } else {
400 return Value::errorVALUE();
401 }
402 }
403
404
405 //
406 // Function: BIN2DEC
407 //
func_bin2dec(valVector args,ValueCalc * calc,FuncExtra *)408 Value func_bin2dec(valVector args, ValueCalc *calc, FuncExtra *)
409 {
410 return calc->fromBase(args[0], 2);
411 }
412
413
414 //
415 // Function: BIN2OCT
416 //
func_bin2oct(valVector args,ValueCalc * calc,FuncExtra *)417 Value func_bin2oct(valVector args, ValueCalc *calc, FuncExtra *)
418 {
419 QRegExp rx("[01]+");
420 int minLength = 0;
421 if (args.count() > 1)
422 // we have the optional "minimum length" argument
423 minLength = calc->conv()->asInteger(args[1]).asInteger();
424
425 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
426 // this only contains 0s and 1s.
427 return calc->base(calc->fromBase(args[0], 2), 8, 0, minLength);
428 } else {
429 return Value::errorVALUE();
430 }
431 }
432
433
434 //
435 // Function: BIN2HEX
436 //
func_bin2hex(valVector args,ValueCalc * calc,FuncExtra *)437 Value func_bin2hex(valVector args, ValueCalc *calc, FuncExtra *)
438 {
439 QRegExp rx("[01]+");
440 int minLength = 0;
441 if (args.count() > 1)
442 // we have the optional "minimum length" argument
443 minLength = calc->conv()->asInteger(args[1]).asInteger();
444
445 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
446 // this only contains 0s and 1s.
447 return calc->base(calc->fromBase(args[0], 2), 16, 0, minLength);
448 } else {
449 return Value::errorVALUE();
450 }
451
452 }
453
454
455 //
456 // Function: OCT2DEC
457 //
func_oct2dec(valVector args,ValueCalc * calc,FuncExtra *)458 Value func_oct2dec(valVector args, ValueCalc *calc, FuncExtra *)
459 {
460 return calc->fromBase(args[0], 8);
461 }
462
463
464 //
465 // Function: OCT2BIN
466 //
func_oct2bin(valVector args,ValueCalc * calc,FuncExtra *)467 Value func_oct2bin(valVector args, ValueCalc *calc, FuncExtra *)
468 {
469 QRegExp rx("[01234567]+");
470 int minLength = 0;
471 if (args.count() > 1)
472 // we have the optional "minimum length" argument
473 minLength = calc->conv()->asInteger(args[1]).asInteger();
474
475 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
476 // this only contains decimal digits.
477 return calc->base(calc->fromBase(args[0], 8), 2, 0, minLength);
478 } else {
479 return Value::errorVALUE();
480 }
481 }
482
483
484 //
485 // Function: OCT2HEX
486 //
func_oct2hex(valVector args,ValueCalc * calc,FuncExtra *)487 Value func_oct2hex(valVector args, ValueCalc *calc, FuncExtra *)
488 {
489 QRegExp rx("[01234567]+");
490 int minLength = 0;
491 if (args.count() > 1)
492 // we have the optional "minimum length" argument
493 minLength = calc->conv()->asInteger(args[1]).asInteger();
494
495 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
496 // this only contains decimal digits.
497 return calc->base(calc->fromBase(args[0], 8), 16, 0, minLength);
498 } else {
499 return Value::errorVALUE();
500 }
501 }
502
503
504 //
505 // Function: HEX2DEC
506 //
func_hex2dec(valVector args,ValueCalc * calc,FuncExtra *)507 Value func_hex2dec(valVector args, ValueCalc *calc, FuncExtra *)
508 {
509 return calc->fromBase(args[0], 16);
510 }
511
512
513 //
514 // Function: HEX2BIN
515 //
func_hex2bin(valVector args,ValueCalc * calc,FuncExtra *)516 Value func_hex2bin(valVector args, ValueCalc *calc, FuncExtra *)
517 {
518 QRegExp rx("[0123456789ABCDEFabcdef]+");
519 int minLength = 0;
520 if (args.count() > 1)
521 // we have the optional "minimum length" argument
522 minLength = calc->conv()->asInteger(args[1]).asInteger();
523
524 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
525 // this only contains decimal digits.
526 return calc->base(calc->fromBase(args[0], 16), 2, 0, minLength);
527 } else {
528 return Value::errorVALUE();
529 }
530 }
531
532
533 //
534 // Function: HEX2OCT
535 //
func_hex2oct(valVector args,ValueCalc * calc,FuncExtra *)536 Value func_hex2oct(valVector args, ValueCalc *calc, FuncExtra *)
537 {
538 QRegExp rx("[0123456789ABCDEFabcdef]+");
539 int minLength = 0;
540 if (args.count() > 1)
541 // we have the optional "minimum length" argument
542 minLength = calc->conv()->asInteger(args[1]).asInteger();
543
544 if (rx.exactMatch(calc->conv()->asString(args[0]).asString())) {
545 // this only contains decimal digits.
546 return calc->base(calc->fromBase(args[0], 16), 8, 0, minLength);
547 } else {
548 return Value::errorVALUE();
549 }
550 }
551
552
553 //
554 // Function: DECIMAL
555 //
func_decimal(valVector args,ValueCalc * calc,FuncExtra *)556 Value func_decimal(valVector args, ValueCalc *calc, FuncExtra *)
557 {
558 QString text = calc->conv()->asString(args[0]).asString();
559 text.remove(QLatin1Char(' '));
560 text.remove(QLatin1Char('\t'));
561 int radix = calc->conv()->asInteger(args[1]).asInteger();
562 if (radix == 16) {
563 if (text.startsWith(QLatin1String("0x"), Qt::CaseInsensitive)) {
564 text.remove(0, 2);
565 }
566 if (text.endsWith(QLatin1Char('h'), Qt::CaseInsensitive)) {
567 text.chop(1); // all but the last char
568 }
569 }
570 if (radix == 2) {
571 if (text.endsWith(QLatin1Char('b'), Qt::CaseInsensitive)) {
572 text.chop(1); // all but the last char
573 }
574 }
575
576 return calc->fromBase(Value(text), radix);
577 }
578
579 //
580 // convert prefix
581 //
582
583 // check if unit may contain prefix, for example "kPa" is "Pa" with
584 // return prefix factor found in unit, or 1.0 for no prefix
585 // also modify the unit, i.e stripping the prefix from it
586 // example: "kPa" will return 1e3 and change unit into "Pa"
kspread_convert_prefix(QMap<QString,double> map,QString & unit)587 static double kspread_convert_prefix(QMap<QString, double> map, QString& unit)
588 {
589 if (map.contains(unit))
590 return 1.0;
591
592 // initialize prefix mapping if necessary
593 static QMap<QString, double> prefixMap;
594 if (prefixMap.isEmpty()) {
595 prefixMap[ "Y" ] = 1e24; // yotta
596 prefixMap[ "Z" ] = 1e21; // zetta
597 prefixMap[ "E" ] = 1e18; // exa
598 prefixMap[ "P" ] = 1e15; // peta
599 prefixMap[ "T" ] = 1e12; // tera
600 prefixMap[ "G" ] = 1e9; // giga
601 prefixMap[ "M" ] = 1e6; // mega
602 prefixMap[ "k" ] = 1e3; // kilo
603 prefixMap[ "h" ] = 1e2; // hecto
604 prefixMap[ "e" ] = 1e1; // deka
605 prefixMap[ "da" ] = 1e1; // deka
606 prefixMap[ "d" ] = 1e-1; // deci
607 prefixMap[ "c" ] = 1e-2; // centi
608 prefixMap[ "m" ] = 1e-3; // milli
609 prefixMap[ "u" ] = 1e-6; // micro
610 prefixMap[ "n" ] = 1e-9; // nano
611 prefixMap[ "p" ] = 1e-12; // pico
612 prefixMap[ "f" ] = 1e-15; // femto
613 prefixMap[ "a" ] = 1e-18; // atto
614 prefixMap[ "z" ] = 1e-21; // zepto
615 prefixMap[ "y" ] = 1e-24; // yocto
616
617 // binary prefixes
618 prefixMap[ "ki" ] = 1024.0 ; // kibi
619 prefixMap[ "Mi" ] = 1048576.0 ; // mebi
620 prefixMap[ "Gi" ] = 1073741824.0 ; // gibi
621 prefixMap[ "Ti" ] = 1099511627776.0 ; // tebi
622 prefixMap[ "Pi" ] = 1125899906842624.0 ; // pebi
623 prefixMap[ "Ei" ] = 1152921504606846976.0 ; // exbi
624 prefixMap[ "Zi" ] = 1180591620717411303424.0 ; // zebi
625 prefixMap[ "Yi" ] = 1208925819614629174706176.0 ; // yobi
626 }
627
628 // check for possible prefix
629 QString prefix = unit.left(2).toLatin1();
630
631 if (prefixMap.contains(prefix)) {
632 unit.remove(0, 2);
633 return prefixMap[prefix];
634 } else if (prefixMap.contains(prefix.left(1))) {
635 unit.remove(0, 1);
636 return prefixMap[prefix.left(1)];
637 }
638 // fail miserably
639 return 0.0;
640 }
641
642
643 //
644 // convert masses
645 //
kspread_convert_mass(const QString & fromUnit,const QString & toUnit,double value,double & result)646 static bool kspread_convert_mass(const QString& fromUnit,
647 const QString& toUnit, double value, double& result)
648 {
649 static QMap<QString, double> massMap;
650
651 // first-time initialization
652 if (massMap.isEmpty()) {
653 massMap[ "g" ] = 1.0; // Gram (the reference )
654
655 massMap[ "sg" ] = 6.8522050005347800E-05; // Pieces
656 massMap[ "lbm" ] = 2.2046229146913400E-03; // Pound
657 massMap[ "u" ] = 6.0221370000000000E23; // U (atomic mass)
658 massMap[ "ozm" ] = 3.5273971800362700E-02; // Ounce
659 massMap[ "stone" ] = 1.574730e-04; // Stone
660 massMap[ "ton" ] = 1.102311e-06; // Ton
661 massMap[ "grain" ] = 1.543236E01; // Grain
662 massMap[ "pweight" ] = 7.054792E-01; // Pennyweight
663 massMap[ "hweight" ] = 1.968413E-05; // Hundredweight
664 massMap[ "shweight" ] = 2.204623E-05; // Shorthundredweight
665 massMap[ "uk_ton" ] = 1.0 / 2240 * 2.2046229146913400E-03; // It's long ton or Imperial ton, 2240 lbm.
666 }
667
668 QString fromU = fromUnit;
669 QString toU = toUnit;
670 double fromPrefix = kspread_convert_prefix(massMap, fromU);
671 double toPrefix = kspread_convert_prefix(massMap, toU);
672 if (fromPrefix == 0.0) return false;
673 if (toPrefix == 0.0) return false;
674 if (!massMap.contains(fromU)) return false;
675 if (!massMap.contains(toU)) return false;
676
677 result = value * fromPrefix * massMap[toU] / (massMap[fromU] * toPrefix);
678
679 return true;
680 }
681
682
683 //
684 // convert distances
685 //
kspread_convert_distance(const QString & fromUnit,const QString & toUnit,double value,double & result)686 static bool kspread_convert_distance(const QString& fromUnit,
687 const QString& toUnit, double value, double& result)
688 {
689 static QMap<QString, double> distanceMap;
690
691 // first-time initialization
692 if (distanceMap.isEmpty()) {
693 distanceMap[ "m" ] = 1.0; // meter (the reference)
694
695 distanceMap[ "ang" ] = 1e10; // Angstrom
696 distanceMap[ "ell" ] = 1.0 / (45.0 * 0.0254); // Ell, exactly 45 international inches
697 distanceMap[ "ft" ] = 1.0 / (12.0 * 0.0254); // feet
698 distanceMap[ "in" ] = 1.0 / 0.0254; // inch
699 distanceMap[ "lightyear" ] = 1.057023455773293e-16; // lightyear
700 distanceMap[ "ly" ] = 1.057023455773293e-16; // lightyear
701 distanceMap[ "mi" ] = 6.2137119223733397e-4; // mile
702 distanceMap[ "Nmi" ] = 5.3995680345572354e-04; // nautical mile
703 distanceMap[ "parsec" ] = 3.240779e-17; // Parsec
704 distanceMap[ "pc" ] = 3.240779e-17; // Parsec
705 distanceMap[ "Pica" ] = 1.0 * 72 / 0.0254; // Pica (1/72) inch
706 distanceMap[ "statute_mi" ] = 1.0 / (6336000.0 / 3937.0); // U.S. survey mile aka U.S. statute mile
707 distanceMap[ "yd" ] = 1.0 / (3.0 * 12.0 * 0.0254); // yard
708 }
709
710 QString fromU = fromUnit;
711 QString toU = toUnit;
712 double fromPrefix = kspread_convert_prefix(distanceMap, fromU);
713 double toPrefix = kspread_convert_prefix(distanceMap, toU);
714 if (fromPrefix == 0.0) return false;
715 if (toPrefix == 0.0) return false;
716 if (!distanceMap.contains(fromU)) return false;
717 if (!distanceMap.contains(toU)) return false;
718
719 result = value * fromPrefix * distanceMap[toU] / (distanceMap[fromU] * toPrefix);
720
721 return true;
722 }
723
724
725 //
726 // convert pressures
727 //
kspread_convert_pressure(const QString & fromUnit,const QString & toUnit,double value,double & result)728 static bool kspread_convert_pressure(const QString& fromUnit,
729 const QString& toUnit, double value, double& result)
730 {
731 static QMap<QString, double> pressureMap;
732
733 // first-time initialization
734 if (pressureMap.isEmpty()) {
735 pressureMap[ "Pa" ] = 1.0;
736
737 pressureMap[ "atm" ] = 0.9869233e-5; // Atmosphere
738 pressureMap[ "atm" ] = 0.9869233e-5; // Atmosphere
739 pressureMap[ "mmHg" ] = 0.00750061708; // mm of Mercury
740 pressureMap[ "psi" ] = 1 / 6894.754; // Pounds per square inch
741 pressureMap[ "Torr" ] = 1 / 133.32237; // Torr, exactly 101325/760 Pa
742 }
743
744 QString fromU = fromUnit;
745 QString toU = toUnit;
746 double fromPrefix = kspread_convert_prefix(pressureMap, fromU);
747 double toPrefix = kspread_convert_prefix(pressureMap, toU);
748 if (fromPrefix == 0.0) return false;
749 if (toPrefix == 0.0) return false;
750 if (!pressureMap.contains(fromU)) return false;
751 if (!pressureMap.contains(toU)) return false;
752
753 result = value * fromPrefix * pressureMap[toU] / (pressureMap[fromU] * toPrefix);
754
755 return true;
756 }
757
758
759 //
760 // convert forces
761 //
kspread_convert_force(const QString & fromUnit,const QString & toUnit,double value,double & result)762 static bool kspread_convert_force(const QString& fromUnit,
763 const QString& toUnit, double value, double& result)
764 {
765 static QMap<QString, double> forceMap;
766
767 // first-time initialization
768 if (forceMap.isEmpty()) {
769 forceMap[ "N" ] = 1.0; // Newton (reference)
770
771 forceMap[ "dy" ] = 1.0e5; // dyne
772 forceMap[ "dyn" ] = 1.0e5; // dyne
773 forceMap[ "lbf" ] = 1.0 / 4.448222; // Pound force (see "lbm" for pound mass)
774 forceMap[ "pond" ] = 1.019716e2; // pond
775 }
776
777 QString fromU = fromUnit;
778 QString toU = toUnit;
779 double fromPrefix = kspread_convert_prefix(forceMap, fromU);
780 double toPrefix = kspread_convert_prefix(forceMap, toU);
781 if (fromPrefix == 0.0) return false;
782 if (toPrefix == 0.0) return false;
783 if (!forceMap.contains(fromU)) return false;
784 if (!forceMap.contains(toU)) return false;
785
786 result = value * fromPrefix * forceMap[toU] / (forceMap[fromU] * toPrefix);
787
788 return true;
789 }
790
791
792 //
793 // convert energies
794 //
kspread_convert_energy(const QString & fromUnit,const QString & toUnit,double value,double & result)795 static bool kspread_convert_energy(const QString& fromUnit,
796 const QString& toUnit, double value, double& result)
797 {
798 static QMap<QString, double> energyMap;
799
800 // first-time initialization
801 if (energyMap.isEmpty()) {
802 energyMap[ "J" ] = 1.0; // Joule (the reference)
803
804 energyMap[ "e" ] = 1.0e7; // erg
805 energyMap[ "c" ] = 0.239006249473467; // thermodynamical calorie
806 energyMap[ "cal" ] = 0.238846190642017; // calorie
807 energyMap[ "eV" ] = 6.241457e+18; // electronvolt
808 energyMap[ "HPh" ] = 3.72506111e-7; // horsepower-hour
809 energyMap[ "Wh" ] = 0.000277778; // watt-hour
810 energyMap[ "flb" ] = 23.73042222;
811 energyMap[ "BTU" ] = 9.47815067349015e-4; // British Thermal Unit
812 }
813
814 QString fromU = fromUnit;
815 QString toU = toUnit;
816 double fromPrefix = kspread_convert_prefix(energyMap, fromU);
817 double toPrefix = kspread_convert_prefix(energyMap, toU);
818 if (fromPrefix == 0.0) return false;
819 if (toPrefix == 0.0) return false;
820 if (!energyMap.contains(fromU)) return false;
821 if (!energyMap.contains(toU)) return false;
822
823 result = value * fromPrefix * energyMap[toU] / (energyMap[fromU] * toPrefix);
824
825 return true;
826 }
827
828
829 //
830 // convert powers
831 //
kspread_convert_power(const QString & fromUnit,const QString & toUnit,double value,double & result)832 static bool kspread_convert_power(const QString& fromUnit,
833 const QString& toUnit, double value, double& result)
834 {
835 static QMap<QString, double> powerMap;
836
837 // first-time initialization
838 if (powerMap.isEmpty()) {
839 powerMap[ "W" ] = 1.0; // Watt (the reference)
840
841 // powerMap[ "HP" ] = 1.341022e-3; // Horsepower
842 powerMap[ "HP" ] = 1.0 / 745.701; // Horsepower (UK)
843 powerMap[ "PS" ] = 1.359622e-3; // Pferdestaerke (German)
844 }
845
846 QString fromU = fromUnit;
847 QString toU = toUnit;
848 double fromPrefix = kspread_convert_prefix(powerMap, fromU);
849 double toPrefix = kspread_convert_prefix(powerMap, toU);
850 if (fromPrefix == 0.0) return false;
851 if (toPrefix == 0.0) return false;
852 if (!powerMap.contains(fromU)) return false;
853 if (!powerMap.contains(toU)) return false;
854
855 result = value * fromPrefix * powerMap[toU] / (powerMap[fromU] * toPrefix);
856
857 return true;
858 }
859
860
861 //
862 // convert magnetism
863 //
kspread_convert_magnetism(const QString & fromUnit,const QString & toUnit,double value,double & result)864 static bool kspread_convert_magnetism(const QString& fromUnit,
865 const QString& toUnit, double value, double& result)
866 {
867 static QMap<QString, double> magnetismMap;
868
869 // first-time initialization
870 if (magnetismMap.isEmpty()) {
871 magnetismMap[ "T" ] = 1.0; // Tesla (the reference)
872
873 magnetismMap[ "ga" ] = 1.0e4; // Gauss
874 }
875
876 QString fromU = fromUnit;
877 QString toU = toUnit;
878 double fromPrefix = kspread_convert_prefix(magnetismMap, fromU);
879 double toPrefix = kspread_convert_prefix(magnetismMap, toU);
880 if (fromPrefix == 0.0) return false;
881 if (toPrefix == 0.0) return false;
882 if (!magnetismMap.contains(fromU)) return false;
883 if (!magnetismMap.contains(toU)) return false;
884
885 result = value * fromPrefix * magnetismMap[toU] / (magnetismMap[fromU] * toPrefix);
886
887 return true;
888 }
889
890
891 //
892 // convert temperatures
893 //
kspread_convert_temperature(const QString & fromUnit,const QString & toUnit,double value,double & result)894 static bool kspread_convert_temperature(const QString& fromUnit,
895 const QString& toUnit, double value, double& result)
896 {
897 static QMap<QString, double> tempFactorMap;
898 static QMap<QString, double> tempOffsetMap;
899
900 // first-time initialization
901 if (tempFactorMap.isEmpty() || tempOffsetMap.isEmpty()) {
902 tempFactorMap[ "C" ] = 1.0; tempOffsetMap[ "C" ] = 0.0;
903 tempFactorMap[ "F" ] = 5.0 / 9.0; tempOffsetMap[ "F" ] = -32.0;
904 tempFactorMap[ "K" ] = 1.0; tempOffsetMap[ "K" ] = -273.15;
905 }
906
907 if (!tempFactorMap.contains(fromUnit)) return false;
908 if (!tempOffsetMap.contains(fromUnit)) return false;
909 if (!tempFactorMap.contains(toUnit)) return false;
910 if (!tempOffsetMap.contains(toUnit)) return false;
911
912 result = (value + tempOffsetMap[ fromUnit ]) * tempFactorMap[ fromUnit ];
913 result = (result / tempFactorMap[ toUnit ]) - tempOffsetMap[ toUnit ];
914
915 return true;
916 }
917
918
919 //
920 // convert volumes
921 //
kspread_convert_volume(const QString & fromUnit,const QString & toUnit,double value,double & result)922 static bool kspread_convert_volume(const QString& fromUnit,
923 const QString& toUnit, double value, double& result)
924 {
925 static QMap<QString, double> volumeMap;
926
927 // first-time initialization
928 if (volumeMap.isEmpty()) {
929 volumeMap[ "l" ] = 1.0; // Liter (the reference)
930
931 //TODO ang3
932 volumeMap[ "barrel" ] = 6.289811E-03; // barrel
933 //TODO bushel
934 volumeMap[ "cup" ] = 4.22583333333333; // cup
935 volumeMap[ "ft3" ] = 3.5314666721488590e-2; // cubic foot
936 volumeMap[ "gal" ] = 0.26411458333333; // gallone
937 volumeMap[ "in3" ] = 6.1023744094732284e1; // cubic inch
938 volumeMap[ "m3" ] = 1.0e-3; // cubic meter
939 volumeMap[ "mi3" ] = 2.3991275857892772e-13; // cubic mile
940 //TODO MTON
941 volumeMap[ "Nmi3" ] = 1.5742621468581148e-13; // cubic Nautical mile
942 volumeMap[ "oz" ] = 33.8066666666667; // ounce liquid
943 //TODO Pica3
944 volumeMap[ "pt" ] = 2.11291666666667; // pint
945 volumeMap[ "qt" ] = 1.05645833333333; // quart
946 volumeMap[ "GRT" ] = 2831.6846592; // Gross Register Ton
947 volumeMap[ "regton" ] = volumeMap[ "GRT" ];
948 volumeMap[ "tbs" ] = 67.6133333333333; // sheetspoon
949 volumeMap[ "tsp" ] = 202.84; // teaspoon
950 //TODO tspm
951 //TODO uk_pt
952 volumeMap[ "yd3" ] = 1.3079506193143922; // cubic yard
953
954 }
955
956 QString fromU = fromUnit;
957 QString toU = toUnit;
958 double fromPrefix = kspread_convert_prefix(volumeMap, fromU);
959 double toPrefix = kspread_convert_prefix(volumeMap, toU);
960 if (fromPrefix == 0.0) return false;
961 if (toPrefix == 0.0) return false;
962 if (!volumeMap.contains(fromU)) return false;
963 if (!volumeMap.contains(toU)) return false;
964
965 result = value * fromPrefix * volumeMap[toU] / (volumeMap[fromU] * toPrefix);
966
967 return true;
968 }
969
970
971 //
972 // convert areas
973 //
kspread_convert_area(const QString & fromUnit,const QString & toUnit,double value,double & result)974 static bool kspread_convert_area(const QString& fromUnit,
975 const QString& toUnit, double value, double& result)
976 {
977 static QMap<QString, double> areaMap;
978
979 // first-time initialization
980 if (areaMap.isEmpty()) {
981 areaMap[ "m2" ] = 1.0; // square meter (the reference)
982 areaMap[ "m^2" ] = 1.0; // square meter (the reference)
983
984 areaMap[ "acre" ] = 4.046856e3; // acre
985 areaMap[ "ar" ] = 1.0 / 100; // are
986 areaMap[ "ft2" ] = 1.0763910416709722e1; // square foot
987 areaMap[ "ft^2" ] = 1.0763910416709722e1; // square foot
988 areaMap[ "ha" ] = 1.0e4; // hectare
989 areaMap[ "in2" ] = 1.5500031000062000e3; // square inch
990 areaMap[ "in^2" ] = 1.5500031000062000e3; // square inch
991 areaMap[ "mi2" ] = 3.8610215854244585e-7; // square mile
992 areaMap[ "mi^2" ] = 3.8610215854244585e-7; // square mile
993 areaMap[ "Nmi2" ] = 2.9155334959812286e-7; // square Nautical mile
994 areaMap[ "Nmi^2" ] = 2.9155334959812286e-7; // square Nautical mile
995 areaMap[ "yd2" ] = 1.0936132983377078; // square yard
996 areaMap[ "yd^2" ] = 1.0936132983377078; // square yard
997 }
998
999 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 //
kspread_convert_speed(const QString & fromUnit,const QString & toUnit,double value,double & result)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 //
kspread_convert_time(const QString & fromUnit,const QString & toUnit,double value,double & result)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 //
kspread_convert_info(const QString & fromUnit,const QString & toUnit,double value,double & result)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 //
func_convert(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_complex(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_complex_imag(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_complex_real(valVector args,ValueCalc * calc,FuncExtra *)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 //
awImSum(ValueCalc * c,Value & res,Value val,Value)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 //
awImSub(ValueCalc * c,Value & res,Value val,Value)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 //
awImMul(ValueCalc * c,Value & res,Value val,Value)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 //
awImDiv(ValueCalc * c,Value & res,Value val,Value)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 //
func_imsum(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imsub(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_improduct(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imdiv(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imconjugate(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imargument(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imabs(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imcos(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imcot(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imcsc(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imsec(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imsin(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imtan(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imcosh(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imcsch(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imsech(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imsinh(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imtanh(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imln(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imlog2(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imlog10(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imexp(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_imsqrt(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_impower(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_delta(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_erf(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_erfc(valVector args,ValueCalc * calc,FuncExtra *)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 //
func_gestep(valVector args,ValueCalc * calc,FuncExtra *)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"
1522