kspread

kspread_functions_engineering.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998-2002 The KSpread Team
3 www.koffice.org/kspread
4 Copyright (C) 2005 Tomas Mecir <mecirt@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; either
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 "functions.h"
25#include "valuecalc.h"
26#include "valueconverter.h"
27
28// used by the CONVERT function
29#include <tqmap.h>
30
31// these are needed for complex functions, while we handle them in the old way
32#include <tdeglobal.h>
33#include <tdelocale.h>
34#include <math.h>
35
36using namespace KSpread;
37
38// prototypes (sort alphabetically)
39Value func_base (valVector args, ValueCalc *calc, FuncExtra *);
40Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *);
41Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *);
42Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *);
43Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *);
44Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *);
45Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *);
46Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *);
47Value func_complex (valVector args, ValueCalc *calc, FuncExtra *);
48Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *);
49Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *);
50Value func_convert (valVector args, ValueCalc *calc, FuncExtra *);
51Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *);
52Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *);
53Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *);
54Value func_delta (valVector args, ValueCalc *calc, FuncExtra *);
55Value func_erf (valVector args, ValueCalc *calc, FuncExtra *);
56Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *);
57Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *);
58Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *);
59Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *);
60Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *);
61Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *);
62Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *);
63Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *);
64Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *);
65Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *);
66Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *);
67Value func_imln (valVector args, ValueCalc *calc, FuncExtra *);
68Value func_impower (valVector args, ValueCalc *calc, FuncExtra *);
69Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *);
70Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *);
71Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *);
72Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *);
73Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *);
74Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *);
75Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *);
76Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *);
77
78// registers all engineering functions
79void RegisterEngineeringFunctions()
80{
81 FunctionRepository* repo = FunctionRepository::self();
82 Function *f;
83
84 f = new Function ("BASE", func_base); // KSpread-specific, like in Quattro-Pro
85 f->setParamCount (1, 3);
86 repo->add (f);
87 f = new Function ("BESSELI", func_besseli);
88 f->setParamCount (2);
89 repo->add (f);
90 f = new Function ("BESSELJ", func_besselj);
91 f->setParamCount (2);
92 repo->add (f);
93 f = new Function ("BESSELK", func_besselk);
94 f->setParamCount (2);
95 repo->add (f);
96 f = new Function ("BESSELY", func_bessely);
97 f->setParamCount (2);
98 repo->add (f);
99 f = new Function ("BIN2DEC", func_bin2dec);
100 repo->add (f);
101 f = new Function ("BIN2OCT", func_bin2oct);
102 repo->add (f);
103 f = new Function ("BIN2HEX", func_bin2hex);
104 repo->add (f);
105 f = new Function ("COMPLEX", func_complex);
106 f->setParamCount (2);
107 repo->add (f);
108 f = new Function ("CONVERT", func_convert);
109 f->setParamCount (3);
110 repo->add (f);
111 f = new Function ("DEC2HEX", func_dec2hex);
112 repo->add (f);
113 f = new Function ("DEC2BIN", func_dec2bin);
114 repo->add (f);
115 f = new Function ("DEC2OCT", func_dec2oct);
116 repo->add (f);
117 f = new Function ("DELTA", func_delta);
118 f->setParamCount (1, 2);
119 repo->add (f);
120 f = new Function ("ERF", func_erf);
121 f->setParamCount (2);
122 repo->add (f);
123 f = new Function ("ERFC", func_erfc);
124 f->setParamCount (1, 2);
125 repo->add (f);
126 f = new Function ("GESTEP", func_gestep);
127 f->setParamCount (1, 2);
128 repo->add (f);
129 f = new Function ("HEX2BIN", func_hex2bin);
130 repo->add (f);
131 f = new Function ("HEX2DEC", func_hex2dec);
132 repo->add (f);
133 f = new Function ("HEX2OCT", func_hex2oct);
134 repo->add (f);
135 f = new Function ("IMABS", func_imabs);
136 repo->add (f);
137 f = new Function ("IMAGINARY", func_complex_imag);
138 repo->add (f);
139 f = new Function ("IMARGUMENT", func_imargument);
140 repo->add (f);
141 f = new Function ("IMCONJUGATE", func_imconjugate);
142 repo->add (f);
143 f = new Function ("IMCOS", func_imcos);
144 repo->add (f);
145 f = new Function ("IMDIV", func_imdiv);
146 f->setParamCount (1, -1);
147 f->setAcceptArray ();
148 repo->add (f);
149 f = new Function ("IMEXP", func_imexp);
150 repo->add (f);
151 f = new Function ("IMLN", func_imln);
152 repo->add (f);
153 f = new Function ("IMPOWER", func_impower);
154 f->setParamCount (2);
155 repo->add (f);
156 f = new Function ("IMPRODUCT", func_improduct);
157 f->setParamCount (1, -1);
158 f->setAcceptArray ();
159 repo->add (f);
160 f = new Function ("IMREAL", func_complex_real);
161 repo->add (f);
162 f = new Function ("IMSIN", func_imsin);
163 repo->add (f);
164 f = new Function ("IMSQRT", func_imsqrt);
165 repo->add (f);
166 f = new Function ("IMSUB", func_imsub);
167 f->setParamCount (1, -1);
168 f->setAcceptArray ();
169 repo->add (f);
170 f = new Function ("IMSUM", func_imsum);
171 f->setParamCount (1, -1);
172 f->setAcceptArray ();
173 repo->add (f);
174 f = new Function ("OCT2BIN", func_oct2bin);
175 repo->add (f);
176 f = new Function ("OCT2DEC", func_oct2dec);
177 repo->add (f);
178 f = new Function ("OCT2HEX", func_oct2hex);
179 repo->add (f);
180}
181
182// Function: BASE
183Value func_base (valVector args, ValueCalc *calc, FuncExtra *)
184{
185 int base = 10;
186 int prec = 0;
187 if (args.count() > 1)
188 base = calc->conv()->asInteger (args[1]).asInteger();
189 if (args.count() == 3)
190 prec = calc->conv()->asInteger (args[2]).asInteger();
191
192 if ((base < 2) || (base > 36))
193 return Value::errorVALUE();
194 if (prec < 0) prec = 2;
195
196 return calc->base (args[0], base, prec);
197}
198
199// Function: BESSELI
200Value func_besseli (valVector args, ValueCalc *calc, FuncExtra *)
201{
202 Value x = args[0];
203 Value y = args[1];
204 return calc->besseli (y, x);
205}
206
207// Function: BESSELJ
208Value func_besselj (valVector args, ValueCalc *calc, FuncExtra *)
209{
210 Value x = args[0];
211 Value y = args[1];
212 return calc->besselj (y, x);
213}
214
215// Function: BESSELK
216Value func_besselk (valVector args, ValueCalc *calc, FuncExtra *)
217{
218 Value x = args[0];
219 Value y = args[1];
220 return calc->besselk (y, x);
221}
222
223// Function: BESSELY
224Value func_bessely (valVector args, ValueCalc *calc, FuncExtra *)
225{
226 Value x = args[0];
227 Value y = args[1];
228 return calc->besseln (y, x);
229}
230
231// Function: DEC2HEX
232Value func_dec2hex (valVector args, ValueCalc *calc, FuncExtra *)
233{
234 return calc->base (args[0], 16);
235}
236
237// Function: DEC2OCT
238Value func_dec2oct (valVector args, ValueCalc *calc, FuncExtra *)
239{
240 return calc->base (args[0], 8);
241}
242
243// Function: DEC2BIN
244Value func_dec2bin (valVector args, ValueCalc *calc, FuncExtra *)
245{
246 return calc->base (args[0], 2);
247}
248
249// Function: BIN2DEC
250Value func_bin2dec (valVector args, ValueCalc *calc, FuncExtra *)
251{
252 return calc->fromBase (args[0], 2);
253}
254
255// Function: BIN2OCT
256Value func_bin2oct (valVector args, ValueCalc *calc, FuncExtra *)
257{
258 return calc->base (calc->fromBase (args[0], 2), 8);
259}
260
261// Function: BIN2HEX
262Value func_bin2hex (valVector args, ValueCalc *calc, FuncExtra *)
263{
264 return calc->base (calc->fromBase (args[0], 2), 16);
265}
266
267// Function: OCT2DEC
268Value func_oct2dec (valVector args, ValueCalc *calc, FuncExtra *)
269{
270 return calc->fromBase (args[0], 8);
271}
272
273// Function: OCT2BIN
274Value func_oct2bin (valVector args, ValueCalc *calc, FuncExtra *)
275{
276 return calc->base (calc->fromBase (args[0], 8), 2);
277}
278
279// Function: OCT2HEX
280Value func_oct2hex (valVector args, ValueCalc *calc, FuncExtra *)
281{
282 return calc->base (calc->fromBase (args[0], 8), 16);
283}
284
285// Function: HEX2DEC
286Value func_hex2dec (valVector args, ValueCalc *calc, FuncExtra *)
287{
288 return calc->fromBase (args[0], 16);
289}
290
291// Function: HEX2BIN
292Value func_hex2bin (valVector args, ValueCalc *calc, FuncExtra *)
293{
294 return calc->base (calc->fromBase (args[0], 16), 2);
295}
296
297// Function: HEX2OCT
298Value func_hex2oct (valVector args, ValueCalc *calc, FuncExtra *)
299{
300 return calc->base (calc->fromBase (args[0], 16), 8);
301}
302
303
304// check if unit may contain prefix, for example "kPa" is "Pa" with
305// return prefix factor found in unit, or 1.0 for no prefix
306// also modify the unit, i.e stripping the prefix from it
307// example: "kPa" will return 1e3 and change unit into "Pa"
308static double kspread_convert_prefix( TQMap<TQString,double> map, TQString& unit )
309{
310 if( map.contains( unit ) )
311 return 1.0;
312
313 // initialize prefix mapping if necessary
314 static TQMap<char,double> prefixMap;
315 if( prefixMap.isEmpty() )
316 {
317 prefixMap[ 'E' ] = 1e18; // exa
318 prefixMap[ 'P' ] = 1e15; // peta
319 prefixMap[ 'T' ] = 1e12; // tera
320 prefixMap[ 'G' ] = 1e9; // giga
321 prefixMap[ 'M' ] = 1e6; // mega
322 prefixMap[ 'k' ] = 1e3; // kilo
323 prefixMap[ 'h' ] = 1e2; // hecto
324 prefixMap[ 'e' ] = 1e1; // dekao
325 prefixMap[ 'd' ] = 1e1; // deci
326 prefixMap[ 'c' ] = 1e2; // centi
327 prefixMap[ 'm' ] = 1e3; // milli
328 prefixMap[ 'u' ] = 1e6; // micro
329 prefixMap[ 'n' ] = 1e9; // nano
330 prefixMap[ 'p' ] = 1e12; // pico
331 prefixMap[ 'f' ] = 1e15; // femto
332 prefixMap[ 'a' ] = 1e18; // atto
333 }
334
335 // check for possible prefix
336 char prefix = unit[0].latin1();
337 if( prefixMap.contains( prefix ) )
338 {
339 unit.remove( 0, 1 );
340 return prefixMap[ prefix ];
341 }
342
343 // fail miserably
344 return 0.0;
345}
346
347static bool kspread_convert_mass( const TQString& fromUnit,
348 const TQString& toUnit, double value, double& result )
349{
350 static TQMap<TQString, double> massMap;
351
352 // first-time initialization
353 if( massMap.isEmpty() )
354 {
355 massMap[ "g" ] = 1.0; // Gram (the reference )
356 massMap[ "sg" ] = 6.8522050005347800E-05; // Pieces
357 massMap[ "lbm" ] = 2.2046229146913400E-03; // Pound
358 massMap[ "u" ] = 6.0221370000000000E23; // U (atomic mass)
359 massMap[ "ozm" ] = 3.5273971800362700E-02; // Ounce
360 massMap[ "stone" ] = 1.574730e-04; // Stone
361 massMap[ "ton" ] = 1.102311e-06; // Ton
362 massMap[ "grain" ] = 1.543236E01; // Grain
363 massMap[ "pweight" ] = 7.054792E-01; // Pennyweight
364 massMap[ "hweight" ] = 1.968413E-05; // Hundredweight
365 massMap[ "shweight" ] = 2.204623E-05; // Shorthundredweight
366 massMap[ "brton" ] = 9.842065E-07; // Gross Registered Ton
367 }
368
369 TQString fromU = fromUnit;
370 TQString toU = toUnit;
371 double fromPrefix = kspread_convert_prefix( massMap, fromU );
372 double toPrefix = kspread_convert_prefix( massMap, toU );
373 if( fromPrefix == 0.0 ) return false;
374 if( toPrefix == 0.0 ) return false;
375 if( !massMap.contains( fromU ) ) return false;
376 if( !massMap.contains( toU ) ) return false;
377
378 result = value * fromPrefix * massMap[toU] / (massMap[fromU] * toPrefix);
379
380 return true;
381}
382
383
384static bool kspread_convert_distance( const TQString& fromUnit,
385 const TQString& toUnit, double value, double& result )
386{
387 static TQMap<TQString, double> distanceMap;
388
389 // first-time initialization
390 if( distanceMap.isEmpty() )
391 {
392 distanceMap[ "m" ] = 1.0; // meter (the reference)
393 distanceMap[ "in" ] = 1.0 / 0.0254; // inch
394 distanceMap[ "ft" ] = 1.0 / (12.0 * 0.0254); // feet
395 distanceMap[ "yd" ] = 1.0 / (3.0 * 12.0 * 0.0254); // yar
396 distanceMap[ "mi" ] = 6.2137119223733397e-4; // mile
397 distanceMap[ "Nmi" ] = 5.3995680345572354e-04; // nautical mile
398 distanceMap[ "ang" ] = 1e10; // Angstrom
399 distanceMap[ "parsec" ] = 3.240779e-17; // Parsec
400 distanceMap[ "lightyear" ] = 1.057023455773293e-16; // lightyear
401 }
402
403 TQString fromU = fromUnit;
404 TQString toU = toUnit;
405 double fromPrefix = kspread_convert_prefix( distanceMap, fromU );
406 double toPrefix = kspread_convert_prefix( distanceMap, toU );
407 if( fromPrefix == 0.0 ) return false;
408 if( toPrefix == 0.0 ) return false;
409 if( !distanceMap.contains( fromU ) ) return false;
410 if( !distanceMap.contains( toU ) ) return false;
411
412 result = value * fromPrefix * distanceMap[toU] / (distanceMap[fromU] * toPrefix);
413
414 return true;
415}
416
417static bool kspread_convert_pressure( const TQString& fromUnit,
418 const TQString& toUnit, double value, double& result )
419{
420 static TQMap<TQString, double> pressureMap;
421
422 // first-time initialization
423 if( pressureMap.isEmpty() )
424 {
425 pressureMap[ "Pa" ] = 1.0;
426 pressureMap[ "atm" ] = 0.9869233e-5;
427 pressureMap[ "mmHg" ] = 0.00750061708;
428 pressureMap[ "psi" ] = 1 / 6894.754;
429 pressureMap[ "Torr" ] = 1 / 133.32237;
430 }
431
432 TQString fromU = fromUnit;
433 TQString toU = toUnit;
434 double fromPrefix = kspread_convert_prefix( pressureMap, fromU );
435 double toPrefix = kspread_convert_prefix( pressureMap, toU );
436 if( fromPrefix == 0.0 ) return false;
437 if( toPrefix == 0.0 ) return false;
438 if( !pressureMap.contains( fromU ) ) return false;
439 if( !pressureMap.contains( toU ) ) return false;
440
441 result = value * fromPrefix * pressureMap[toU] / (pressureMap[fromU] * toPrefix);
442
443 return true;
444}
445
446static bool kspread_convert_force( const TQString& fromUnit,
447 const TQString& toUnit, double value, double& result )
448{
449 static TQMap<TQString, double> forceMap;
450
451 // first-time initialization
452 if( forceMap.isEmpty() )
453 {
454 forceMap[ "N" ] = 1.0; // Newton (reference)
455 forceMap[ "dyn" ] = 1.0e5; // dyn
456 forceMap[ "pond" ] = 1.019716e2; // pond
457 }
458
459 TQString fromU = fromUnit;
460 TQString toU = toUnit;
461 double fromPrefix = kspread_convert_prefix( forceMap, fromU );
462 double toPrefix = kspread_convert_prefix( forceMap, toU );
463 if( fromPrefix == 0.0 ) return false;
464 if( toPrefix == 0.0 ) return false;
465 if( !forceMap.contains( fromU ) ) return false;
466 if( !forceMap.contains( toU ) ) return false;
467
468 result = value * fromPrefix * forceMap[toU] / (forceMap[fromU] * toPrefix);
469
470 return true;
471}
472
473static bool kspread_convert_energy( const TQString& fromUnit,
474 const TQString& toUnit, double value, double& result )
475{
476 static TQMap<TQString, double> energyMap;
477
478 // first-time initialization
479 if( energyMap.isEmpty() )
480 {
481 energyMap[ "J" ] = 1.0; // Joule (the reference)
482 energyMap[ "e" ] = 1.0e7; //erg
483 energyMap[ "c" ] = 0.239006249473467; // thermodynamical calorie
484 energyMap[ "cal" ] = 0.238846190642017; // calorie
485 energyMap[ "eV" ] = 6.241457e+18; // electronvolt
486 energyMap[ "HPh" ] = 3.72506111e-7; // horsepower-hour
487 energyMap[ "Wh" ] = 0.000277778; // watt-hour
488 energyMap[ "flb" ] = 23.73042222;
489 energyMap[ "BTU" ] = 9.47815067349015e-4; // British Thermal Unit
490 }
491
492 TQString fromU = fromUnit;
493 TQString toU = toUnit;
494 double fromPrefix = kspread_convert_prefix( energyMap, fromU );
495 double toPrefix = kspread_convert_prefix( energyMap, toU );
496 if( fromPrefix == 0.0 ) return false;
497 if( toPrefix == 0.0 ) return false;
498 if( !energyMap.contains( fromU ) ) return false;
499 if( !energyMap.contains( toU ) ) return false;
500
501 result = value * fromPrefix * energyMap[toU] / (energyMap[fromU] * toPrefix);
502
503 return true;
504}
505
506static bool kspread_convert_power( const TQString& fromUnit,
507 const TQString& toUnit, double value, double& result )
508{
509 static TQMap<TQString, double> powerMap;
510
511 // first-time initialization
512 if( powerMap.isEmpty() )
513 {
514 powerMap[ "W" ] = 1.0; // Watt (the reference)
515 powerMap[ "HP" ] = 1.341022e-3; // Horsepower
516 powerMap[ "PS" ] = 1.359622e-3; // Pferdestärke (German)
517 }
518
519 TQString fromU = fromUnit;
520 TQString toU = toUnit;
521 double fromPrefix = kspread_convert_prefix( powerMap, fromU );
522 double toPrefix = kspread_convert_prefix( powerMap, toU );
523 if( fromPrefix == 0.0 ) return false;
524 if( toPrefix == 0.0 ) return false;
525 if( !powerMap.contains( fromU ) ) return false;
526 if( !powerMap.contains( toU ) ) return false;
527
528 result = value * fromPrefix * powerMap[toU] / (powerMap[fromU] * toPrefix);
529
530 return true;
531}
532
533static bool kspread_convert_magnetism( const TQString& fromUnit,
534 const TQString& toUnit, double value, double& result )
535{
536 static TQMap<TQString, double> magnetismMap;
537
538 // first-time initialization
539 if( magnetismMap.isEmpty() )
540 {
541 magnetismMap[ "T" ] = 1.0; // Tesla (the reference)
542 magnetismMap[ "ga" ] = 1.0e4; // Gauss
543 }
544
545 TQString fromU = fromUnit;
546 TQString toU = toUnit;
547 double fromPrefix = kspread_convert_prefix( magnetismMap, fromU );
548 double toPrefix = kspread_convert_prefix( magnetismMap, toU );
549 if( fromPrefix == 0.0 ) return false;
550 if( toPrefix == 0.0 ) return false;
551 if( !magnetismMap.contains( fromU ) ) return false;
552 if( !magnetismMap.contains( toU ) ) return false;
553
554 result = value * fromPrefix * magnetismMap[toU] / (magnetismMap[fromU] * toPrefix);
555
556 return true;
557}
558
559static bool kspread_convert_temperature( const TQString& fromUnit,
560 const TQString& toUnit, double value, double& result )
561{
562 static TQMap<TQString, double> tempFactorMap;
563 static TQMap<TQString, double> tempOffsetMap;
564
565 // first-time initialization
566 if( tempFactorMap.isEmpty() || tempOffsetMap.isEmpty() )
567 {
568 tempFactorMap[ "C" ] = 1.0; tempOffsetMap[ "C" ] = 0.0;
569 tempFactorMap[ "F" ] = 5.0/9.0; tempOffsetMap[ "F" ] = -32.0;
570 tempFactorMap[ "K" ] = 1.0; tempOffsetMap[ "K" ] = -273.15;
571 }
572
573 if( !tempFactorMap.contains( fromUnit ) ) return false;
574 if( !tempOffsetMap.contains( fromUnit ) ) return false;
575 if( !tempFactorMap.contains( toUnit ) ) return false;
576 if( !tempOffsetMap.contains( toUnit ) ) return false;
577
578 result = ( value + tempOffsetMap[ fromUnit ] )* tempFactorMap[ fromUnit ];
579 result = ( result / tempFactorMap[ toUnit ] ) - tempOffsetMap[ toUnit ];
580
581 return true;
582}
583
584static bool kspread_convert_volume( const TQString& fromUnit,
585 const TQString& toUnit, double value, double& result )
586{
587 static TQMap<TQString, double> volumeMap;
588
589 // first-time initialization
590 if( volumeMap.isEmpty() )
591 {
592 volumeMap[ "l" ] = 1.0; // Liter (the reference)
593 volumeMap[ "tsp" ] = 202.84; // teaspoon
594 volumeMap[ "tbs" ] = 67.6133333333333; // sheetspoon
595 volumeMap[ "oz" ] = 33.8066666666667; // ounce liquid
596 volumeMap[ "cup" ] = 4.22583333333333; // cup
597 volumeMap[ "pt" ] = 2.11291666666667; // pint
598 volumeMap[ "qt" ] = 1.05645833333333; // quart
599 volumeMap[ "gal" ] = 0.26411458333333; // gallone
600 volumeMap[ "m3" ] = 1.0e-3; // cubic meter
601 volumeMap[ "mi3" ] = 2.3991275857892772e-13; // cubic mile
602 volumeMap[ "Nmi3" ] = 1.5742621468581148e-13; // cubic Nautical mile
603 volumeMap[ "in3" ] = 6.1023744094732284e1; // cubic inch
604 volumeMap[ "ft3" ] = 3.5314666721488590e-2; // cubic foot
605 volumeMap[ "yd3" ] = 1.3079506193143922; // cubic yard
606 volumeMap[ "barrel" ] = 6.289811E-03; // barrel
607 }
608
609 TQString fromU = fromUnit;
610 TQString toU = toUnit;
611 double fromPrefix = kspread_convert_prefix( volumeMap, fromU );
612 double toPrefix = kspread_convert_prefix( volumeMap, toU );
613 if( fromPrefix == 0.0 ) return false;
614 if( toPrefix == 0.0 ) return false;
615 if( !volumeMap.contains( fromU ) ) return false;
616 if( !volumeMap.contains( toU ) ) return false;
617
618 result = value * fromPrefix * volumeMap[toU] / (volumeMap[fromU] * toPrefix);
619
620 return true;
621}
622
623static bool kspread_convert_area( const TQString& fromUnit,
624 const TQString& toUnit, double value, double& result )
625{
626 static TQMap<TQString, double> areaMap;
627
628 // first-time initialization
629 if( areaMap.isEmpty() )
630 {
631 areaMap[ "m2" ] = 1.0; // square meter (the reference)
632 areaMap[ "mi2" ] = 3.8610215854244585e-7; // square mile
633 areaMap[ "Nmi2" ] = 2.9155334959812286e-7; // square Nautical mile
634 areaMap[ "in2" ] = 1.5500031000062000e3; // square inch
635 areaMap[ "ft2" ] = 1.0763910416709722e1; // square foot
636 areaMap[ "yd2" ] = 1.0936132983377078; // square yard
637 areaMap[ "acre" ] = 4.046856e3; // acre
638 areaMap[ "ha" ] = 1.0e4; // hectare
639 }
640
641 TQString fromU = fromUnit;
642 TQString toU = toUnit;
643 double fromPrefix = kspread_convert_prefix( areaMap, fromU );
644 double toPrefix = kspread_convert_prefix( areaMap, toU );
645 if( fromPrefix == 0.0 ) return false;
646 if( toPrefix == 0.0 ) return false;
647 if( !areaMap.contains( fromU ) ) return false;
648 if( !areaMap.contains( toU ) ) return false;
649
650 result = value * fromPrefix * areaMap[toU] / (areaMap[fromU] * toPrefix);
651
652 return true;
653}
654
655static bool kspread_convert_speed( const TQString& fromUnit,
656 const TQString& toUnit, double value, double& result )
657{
658 static TQMap<TQString, double> speedMap;
659
660 // first-time initialization
661 if( speedMap.isEmpty() )
662 {
663 speedMap[ "m/s" ] = 1.0; // meters per second (the reference)
664 speedMap[ "m/h" ] = 3.6e3; // meters per hour
665 speedMap[ "mph" ] = 2.2369362920544023; // miles per hour
666 speedMap[ "kn" ] = 1.9438444924406048; // knot
667 }
668
669 TQString fromU = fromUnit;
670 TQString toU = toUnit;
671 double fromPrefix = kspread_convert_prefix( speedMap, fromU );
672 double toPrefix = kspread_convert_prefix( speedMap, toU );
673 if( fromPrefix == 0.0 ) return false;
674 if( toPrefix == 0.0 ) return false;
675 if( !speedMap.contains( fromU ) ) return false;
676 if( !speedMap.contains( toU ) ) return false;
677
678 result = value * fromPrefix * speedMap[toU] / (speedMap[fromU] * toPrefix);
679
680 return true;
681}
682
683
684// Function: CONVERT
685Value func_convert (valVector args, ValueCalc *calc, FuncExtra *)
686{
687 // This function won't support arbitrary precision.
688
689 double value = calc->conv()->asFloat (args[0]).asFloat ();
690 TQString fromUnit = calc->conv()->asString (args[1]).asString();
691 TQString toUnit = calc->conv()->asString (args[2]).asString();
692
693 double result = value;
694
695 if( !kspread_convert_mass( fromUnit, toUnit, value, result ) )
696 if( !kspread_convert_distance( fromUnit, toUnit, value, result ) )
697 if( !kspread_convert_pressure( fromUnit, toUnit, value, result ) )
698 if( !kspread_convert_force( fromUnit, toUnit, value, result ) )
699 if( !kspread_convert_energy( fromUnit, toUnit, value, result ) )
700 if( !kspread_convert_power( fromUnit, toUnit, value, result ) )
701 if( !kspread_convert_magnetism( fromUnit, toUnit, value, result ) )
702 if( !kspread_convert_temperature( fromUnit, toUnit, value, result ) )
703 if( !kspread_convert_volume( fromUnit, toUnit, value, result ) )
704 if( !kspread_convert_area( fromUnit, toUnit, value, result ) )
705 if( !kspread_convert_speed( fromUnit, toUnit, value, result ) )
706 return Value::errorNA();
707
708 return Value (result);
709}
710
711
712// functions operating over complex numbers ...
713// these may eventually end up being merged into ValueCalc and friends
714// then complex numbers will be handled transparently in most functions
715
716static TQString func_create_complex( double real,double imag )
717{
718 TQString tmp,tmp2;
719 if(imag ==0)
720 {
721 return TDEGlobal::locale()->formatNumber( real);
722 }
723 if(real!=0)
724 tmp=TDEGlobal::locale()->formatNumber(real);
725 else
726 return TDEGlobal::locale()->formatNumber(imag)+"i";
727 if (imag >0)
728 tmp=tmp+"+"+TDEGlobal::locale()->formatNumber(imag)+"i";
729 else
730 tmp=tmp+TDEGlobal::locale()->formatNumber(imag)+"i";
731 return tmp;
732
733}
734
735// Function: COMPLEX
736Value func_complex (valVector args, ValueCalc *calc, FuncExtra *)
737{
738 if (calc->isZero (args[1]))
739 return args[0];
740 double re = calc->conv()->asFloat (args[0]).asFloat ();
741 double im = calc->conv()->asFloat (args[1]).asFloat ();
742 TQString tmp=func_create_complex (re, im);
743 bool ok;
744 double result = TDEGlobal::locale()->readNumber(tmp, &ok);
745 if (ok)
746 return Value (result);
747 return Value (tmp);
748}
749
750
751static double imag_complexe(TQString str, bool &ok)
752{
753TQString tmp=str;
754if(tmp.find('i')==-1)
755 { //not a complex
756 ok=true;
757 return 0;
758 }
759else if( tmp.length()==1)
760 {
761 // i
762 ok=true;
763 return 1;
764 }
765else if( tmp.length()==2 )
766 {
767 //-i,+i,
768 int pos1;
769 if((pos1=tmp.find('+'))!=-1&& pos1==0)
770 {
771 ok=true;
772 return 1;
773 }
774 else if( (pos1=tmp.find('-'))!=-1 && pos1==0 )
775 {
776 ok=true;
777 return -1;
778 }
779 else if(tmp[0].isDigit())
780 { //5i
781 ok=true;
782 return TDEGlobal::locale()->readNumber(tmp.left(1));
783 }
784 else
785 {
786 ok=false;
787 return 0;
788 }
789 }
790else
791 {//12+12i
792 int pos1,pos2;
793 if((pos1=tmp.find('i'))!=-1)
794 {
795 double val;
796 TQString tmpStr;
797
798 if((pos2=tmp.findRev('+'))!=-1 && pos2!=0)
799 {
800 if((pos1-pos2)==1)
801 {
802 ok=true;
803 return 1;
804 }
805 else
806 {
807 tmpStr=tmp.mid(pos2,(pos1-pos2));
808 val=TDEGlobal::locale()->readNumber(tmpStr, &ok);
809 if(!ok)
810 val=0;
811 return val;
812 }
813 }
814 else if( (pos2=tmp.findRev('-'))!=-1&& pos2!=0)
815 {
816 if((pos1-pos2)==1)
817 {
818 ok=true;
819 return -1;
820 }
821 else
822 {
823 tmpStr=tmp.mid(pos2,(pos1-pos2));
824 val=TDEGlobal::locale()->readNumber(tmpStr, &ok);
825 if(!ok)
826 val=0;
827 return val;
828 }
829 }
830 else
831 {//15.55i
832 tmpStr=tmp.left(pos1);
833 val=TDEGlobal::locale()->readNumber(tmpStr, &ok);
834 if(!ok)
835 val=0;
836 return val;
837 }
838 }
839 }
840ok=false;
841return 0;
842}
843
844// Function: IMAGINARY
845Value func_complex_imag (valVector args, ValueCalc *calc, FuncExtra *)
846{
847 TQString tmp = calc->conv()->asString (args[0]).asString ();
848 bool good;
849 double result=imag_complexe(tmp, good);
850 if (good)
851 return Value (result);
852 return Value::errorVALUE();
853}
854
855
856static double real_complexe(TQString str, bool &ok)
857{
858double val;
859int pos1,pos2;
860TQString tmp=str;
861TQString tmpStr;
862if((pos1=tmp.find('i'))==-1)
863 { //12.5
864 val=TDEGlobal::locale()->readNumber(tmp, &ok);
865 if(!ok)
866 val=0;
867 return val;
868 }
869else
870 { //15-xi
871 if((pos2=tmp.findRev('-'))!=-1 && pos2!=0)
872 {
873 tmpStr=tmp.left(pos2);
874 val=TDEGlobal::locale()->readNumber(tmpStr, &ok);
875 if(!ok)
876 val=0;
877 return val;
878 } //15+xi
879 else if((pos2=tmp.findRev('+'))!=-1)
880 {
881 tmpStr=tmp.left(pos2);
882 val=TDEGlobal::locale()->readNumber(tmpStr, &ok);
883 if(!ok)
884 val=0;
885 return val;
886 }
887 else
888 {
889 ok=true;
890 return 0;
891 }
892 }
893
894ok=false;
895return 0;
896}
897
898// Function: IMREAL
899Value func_complex_real (valVector args, ValueCalc *calc, FuncExtra *)
900{
901 TQString tmp = calc->conv()->asString (args[0]).asString ();
902 bool good;
903 double result=real_complexe(tmp, good);
904 if (good)
905 return Value (result);
906 return Value::errorVALUE();
907}
908
909void ImHelper (ValueCalc *c, Value res, Value val,
910 double &imag, double &real, double &imag1, double &real1)
911{
912 bool ok;
913 imag=imag_complexe(res.asString(), ok);
914 real=real_complexe(res.asString(), ok);
915 if (val.isString())
916 {
917 imag1 = imag_complexe (val.asString(), ok);
918 real1 = real_complexe (val.asString(), ok);
919 } else {
920 imag1=0;
921 real1=c->conv()->asFloat (val).asFloat();
922 }
923}
924
925void awImSum (ValueCalc *c, Value &res, Value val, Value)
926{
927 double imag,real,imag1,real1;
928 ImHelper (c, res, val, imag, real, imag1, real1);
929 res=func_create_complex(real+real1,imag+imag1);
930}
931
932void awImSub (ValueCalc *c, Value &res, Value val, Value)
933{
934 double imag,real,imag1,real1;
935 ImHelper (c, res, val, imag, real, imag1, real1);
936 res=func_create_complex(real-real1,imag-imag1);
937}
938
939void awImMul (ValueCalc *c, Value &res, Value val, Value)
940{
941 double imag,real,imag1,real1;
942 ImHelper (c, res, val, imag, real, imag1, real1);
943 res=func_create_complex(real*real1+(imag*imag1)*-1,real*imag1+real1*imag);
944}
945
946void awImDiv (ValueCalc *c, Value &res, Value val, Value)
947{
948 double imag,real,imag1,real1;
949 ImHelper (c, res, val, imag, real, imag1, real1);
950 res=func_create_complex((real*real1+imag*imag1)/(real1*real1+imag1*imag1),
951 (real1*imag-real*imag1)/(real1*real1+imag1*imag1));
952}
953
954// Function: IMSUM
955Value func_imsum (valVector args, ValueCalc *calc, FuncExtra *)
956{
957 Value result;
958 calc->arrayWalk (args, result, awImSum, 0);
959
960 bool ok;
961 TQString res = calc->conv()->asString (result).asString();
962 double val=TDEGlobal::locale()->readNumber(res, &ok);
963 if (ok)
964 return Value (val);
965 return Value (result);
966}
967
968// Function: IMSUB
969Value func_imsub (valVector args, ValueCalc *calc, FuncExtra *)
970{
971 Value result;
972 calc->arrayWalk (args, result, awImSub, 0);
973
974 bool ok;
975 TQString res = calc->conv()->asString (result).asString();
976 double val=TDEGlobal::locale()->readNumber(res, &ok);
977 if (ok)
978 return Value (val);
979 return Value (result);
980}
981
982// Function: IMPRODUCT
983Value func_improduct (valVector args, ValueCalc *calc, FuncExtra *)
984{
985 Value result;
986 calc->arrayWalk (args, result, awImMul, 0);
987
988 bool ok;
989 TQString res = calc->conv()->asString (result).asString();
990 double val=TDEGlobal::locale()->readNumber(res, &ok);
991 if (ok)
992 return Value (val);
993 return Value (result);
994}
995
996// Function: IMDIV
997Value func_imdiv (valVector args, ValueCalc *calc, FuncExtra *)
998{
999 Value result;
1000 calc->arrayWalk (args, result, awImDiv, 0);
1001
1002 bool ok;
1003 TQString res = calc->conv()->asString (result).asString();
1004 double val=TDEGlobal::locale()->readNumber(res, &ok);
1005 if (ok)
1006 return Value (val);
1007 return Value (result);
1008}
1009
1010// Function: IMCONJUGATE
1011Value func_imconjugate (valVector args, ValueCalc *calc, FuncExtra *)
1012{
1013 TQString tmp = calc->conv()->asString (args[0]).asString();
1014 bool ok;
1015 double real=real_complexe(tmp,ok);
1016 if (!ok)
1017 return Value::errorVALUE();
1018 double imag=imag_complexe(tmp,ok);
1019 if(!ok)
1020 return Value::errorVALUE();
1021
1022 tmp=func_create_complex(real,-imag);
1023
1024 double result=TDEGlobal::locale()->readNumber(tmp, &ok);
1025 if(ok)
1026 return Value (result);
1027
1028 return Value (tmp);
1029}
1030
1031// Function: IMARGUMENT
1032Value func_imargument (valVector args, ValueCalc *calc, FuncExtra *)
1033{
1034 TQString tmp = calc->conv()->asString (args[0]).asString();
1035 bool ok;
1036 double real=real_complexe(tmp,ok);
1037 if (!ok)
1038 return Value::errorVALUE();
1039 double imag=imag_complexe(tmp,ok);
1040 if (!ok)
1041 return Value::errorVALUE();
1042 if(imag==0)
1043 return Value::errorDIV0();
1044 double arg=atan2(imag,real);
1045
1046 return Value (arg);
1047}
1048
1049// Function: IMABS
1050Value func_imabs (valVector args, ValueCalc *calc, FuncExtra *)
1051{
1052 TQString tmp = calc->conv()->asString (args[0]).asString();
1053 bool ok;
1054 double real=real_complexe(tmp,ok);
1055 if(!ok)
1056 return Value::errorVALUE();
1057 double imag=imag_complexe(tmp,ok);
1058 if(!ok)
1059 return Value::errorVALUE();
1060 double arg=sqrt(pow(imag,2)+pow(real,2));
1061
1062 return Value (arg);
1063}
1064
1065// Function: IMCOS
1066Value func_imcos (valVector args, ValueCalc *calc, FuncExtra *)
1067{
1068 TQString tmp = calc->conv()->asString (args[0]).asString();
1069 bool ok;
1070 double real=real_complexe(tmp,ok);
1071 if(!ok)
1072 return Value::errorVALUE();
1073 double imag=imag_complexe(tmp,ok);
1074 if(!ok)
1075 return Value::errorVALUE();
1076 double imag_res=sin(real)*sinh(imag);
1077 double real_res=cos(real)*cosh(imag);
1078
1079
1080 tmp=func_create_complex(real_res,-imag_res);
1081
1082 double result=TDEGlobal::locale()->readNumber(tmp, &ok);
1083 if(ok)
1084 return Value (result);
1085
1086 return Value (tmp);
1087}
1088
1089// Function: IMSIN
1090Value func_imsin (valVector args, ValueCalc *calc, FuncExtra *)
1091{
1092 TQString tmp = calc->conv()->asString (args[0]).asString();
1093 bool ok;
1094 double real=real_complexe(tmp,ok);
1095 if(!ok)
1096 return Value::errorVALUE();
1097 double imag=imag_complexe(tmp,ok);
1098 if(!ok)
1099 return Value::errorVALUE();
1100 double imag_res=cos(real)*sinh(imag);
1101 double real_res=sin(real)*cosh(imag);
1102
1103
1104 tmp=func_create_complex(real_res,imag_res);
1105
1106 double result=TDEGlobal::locale()->readNumber(tmp, &ok);
1107 if(ok)
1108 return Value (result);
1109
1110 return Value (tmp);
1111}
1112
1113// Function: IMLN
1114Value func_imln (valVector args, ValueCalc *calc, FuncExtra *)
1115{
1116 TQString tmp = calc->conv()->asString (args[0]).asString();
1117 bool ok;
1118 double real=real_complexe(tmp,ok);
1119 if(!ok)
1120 return Value::errorVALUE();
1121 double imag=imag_complexe(tmp,ok);
1122 if(!ok)
1123 return Value::errorVALUE();
1124
1125 double arg=sqrt(pow(imag,2)+pow(real,2));
1126 double real_res=log(arg);
1127 double imag_res=atan(imag/real);
1128 tmp=func_create_complex(real_res,imag_res);
1129
1130 double result=TDEGlobal::locale()->readNumber(tmp, &ok);
1131 if(ok)
1132 return Value (result);
1133
1134 return Value (tmp);
1135}
1136
1137// Function: IMEXP
1138Value func_imexp (valVector args, ValueCalc *calc, FuncExtra *)
1139{
1140 TQString tmp = calc->conv()->asString (args[0]).asString();
1141 bool ok;
1142 double real=real_complexe(tmp,ok);
1143 if(!ok)
1144 return Value::errorVALUE();
1145 double imag=imag_complexe(tmp,ok);
1146 if(!ok)
1147 return Value::errorVALUE();
1148 double imag_res=exp(real)*sin(imag);
1149 double real_res=exp(real)*cos(imag);
1150
1151
1152 tmp=func_create_complex(real_res,imag_res);
1153
1154 double result=TDEGlobal::locale()->readNumber(tmp, &ok);
1155 if(ok)
1156 return Value (result);
1157
1158 return Value (tmp);
1159}
1160
1161// Function: IMSQRT
1162Value func_imsqrt (valVector args, ValueCalc *calc, FuncExtra *)
1163{
1164 TQString tmp = calc->conv()->asString (args[0]).asString();
1165 bool ok;
1166 double real=real_complexe(tmp,ok);
1167 if(!ok)
1168 return Value::errorVALUE();
1169 double imag=imag_complexe(tmp,ok);
1170 if(!ok)
1171 return Value::errorVALUE();
1172 double arg=sqrt(sqrt(pow(imag,2)+pow(real,2)));
1173 double angle=atan(imag/real);
1174
1175 double real_res=arg*cos((angle/2));
1176 double imag_res=arg*sin((angle/2));
1177
1178 tmp=func_create_complex(real_res,imag_res);
1179
1180 double result=TDEGlobal::locale()->readNumber(tmp, &ok);
1181 if(ok)
1182 return Value (result);
1183
1184 return Value (tmp);
1185}
1186
1187// Function: IMPOWER
1188Value func_impower (valVector args, ValueCalc *calc, FuncExtra *)
1189{
1190 TQString tmp = calc->conv()->asString (args[0]).asString();
1191 double val2 = calc->conv()->asFloat (args[1]).asFloat();
1192 bool ok;
1193 double real=real_complexe(tmp,ok);
1194 if(!ok)
1195 return Value::errorVALUE();
1196 double imag=imag_complexe(tmp,ok);
1197 if(!ok)
1198 return Value::errorVALUE();
1199
1200 double arg=::pow(sqrt(pow(imag,2)+pow(real,2)),val2);
1201 double angle=atan(imag/real);
1202
1203 double real_res=arg*cos(angle*val2);
1204 double imag_res=arg*sin(angle*val2);
1205
1206 tmp=func_create_complex(real_res,imag_res);
1207
1208 double result=TDEGlobal::locale()->readNumber(tmp, &ok);
1209 if(ok)
1210 return Value (result);
1211
1212 return Value (tmp);
1213}
1214
1215// Function: DELTA
1216Value func_delta (valVector args, ValueCalc *calc, FuncExtra *)
1217{
1218 Value val1 = args[0];
1219 Value val2 = 0.0;
1220 if (args.count() == 2)
1221 val2 = args[1];
1222
1223 return Value (calc->approxEqual (val1, val2) ? 1 : 0);
1224}
1225
1226// Function: ERF
1227Value func_erf (valVector args, ValueCalc *calc, FuncExtra *)
1228{
1229 if (args.count() == 2)
1230 return calc->sub (calc->erf (args[1]), calc->erf (args[0]));
1231 return calc->erf (args[0]);
1232}
1233
1234// Function: ERFC
1235Value func_erfc (valVector args, ValueCalc *calc, FuncExtra *)
1236{
1237 if (args.count() == 2)
1238 return calc->sub (calc->erfc (args[1]), calc->erfc (args[0]));
1239 return calc->erfc (args[0]);
1240}
1241
1242// Function: GESTEP
1243Value func_gestep (valVector args, ValueCalc *calc, FuncExtra *)
1244{
1245 Value x = args[0];
1246 Value y = 0.0;
1247 if (args.count() == 2)
1248 y = args[1];
1249
1250 int result = 0;
1251 if (calc->greater (x, y) || calc->approxEqual (x, y))
1252 result = 1;
1253
1254 return Value (result);
1255}
1256
The ValueCalc class is used to perform all sorts of calculations.
Definition valuecalc.h:69
bool approxEqual(const Value &a, const Value &b)
numerical comparison with a little epsilon tolerance
bool greater(const Value &a, const Value &b)
numerical comparison
Value besseli(Value v, Value x)
bessel functions - may also end up being separated from here
bool isZero(const Value &a)
comparison and related
Value erf(Value x)
error functions (see: man erf)
void arrayWalk(const Value &range, Value &res, arrayWalkFunc func, Value param)
array/range walking
Value fromBase(const Value &val, int base=16)
base conversion base -> 10
Value base(const Value &val, int base=16, int prec=0)
base conversion 10 -> base
Provides a wrapper for cell value.
static const Value & errorDIV0()
Returns constant reference to DIV/0!
double asFloat() const
Returns the floating-point value of this value.
long asInteger() const
Returns the integer value of this value.
TQString asString() const
Returns the string value of this value.
static const Value & errorVALUE()
Returns constant reference to VALUE!
bool isString() const
Returns true if the type of this value is string.
static const Value & errorNA()
Returns constant reference to N/A error.
The KSpread namespace.
Definition commands.h:39