GnmFunc: make this a GObject.
[gnumeric.git] / plugins / fn-eng / functions.c
blobe307bc81791058d7e8d05119e0a056193f1086a6
1 /*
2 * fn-eng.c: Built in engineering functions and functions registration
4 * Authors:
5 * Michael Meeks <michael@ximian.com>
6 * Jukka-Pekka Iivonen <iivonen@iki.fi>
7 * Morten Welinder <terra@gnome.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <https://www.gnu.org/licenses/>.
22 #include <gnumeric-config.h>
23 #include <gnumeric.h>
24 #include <func.h>
25 #include <gnm-i18n.h>
27 #include <parse-util.h>
28 #include <value.h>
29 #include <mathfunc.h>
30 #include <sf-bessel.h>
31 #include <sf-dpq.h>
32 #include <collect.h>
33 #include <number-match.h>
34 #include <workbook.h>
35 #include <sheet.h>
37 #include <goffice/goffice.h>
38 #include <gsf/gsf-utils.h>
39 #include <gnm-plugin.h>
41 #include <math.h>
42 #include <limits.h>
43 #include <string.h>
44 #include <stdlib.h>
46 GNM_PLUGIN_MODULE_HEADER;
49 typedef enum {
50 V2B_STRINGS_GENERAL = 1, /* Allow "1/1/2000" as number. */
51 V2B_STRINGS_0XH = 2, /* Allow "4444h" and "0xABCD". */
52 V2B_STRINGS_MAXLEN = 4, /* Impose 10 character input length. */
53 V2B_STRINGS_BLANK_ZERO = 8, /* Treat "" as "0". */
54 V2B_NUMBER = 16, /* Wants a number, not a string. */
55 V2B_KILLME
56 } Val2BaseFlags;
60 /**
61 * FIXME: In the long term this needs optimising.
62 **/
63 static GnmValue *
64 val_to_base (GnmFuncEvalInfo *ei,
65 GnmValue const *value,
66 GnmValue const *aplaces,
67 int src_base, int dest_base,
68 gnm_float min_value, gnm_float max_value,
69 Val2BaseFlags flags)
71 int digit, min, max, places;
72 gnm_float v;
73 GString *buffer;
74 GnmValue *vstring = NULL;
76 g_return_val_if_fail (src_base > 1 && src_base <= 36,
77 value_new_error_VALUE (ei->pos));
78 g_return_val_if_fail (dest_base > 1 && dest_base <= 36,
79 value_new_error_VALUE (ei->pos));
81 /* func.c ought to take care of this. */
82 if (VALUE_IS_BOOLEAN (value))
83 return value_new_error_VALUE (ei->pos);
84 if (aplaces && VALUE_IS_BOOLEAN (aplaces))
85 return value_new_error_VALUE (ei->pos);
87 switch (value->v_any.type) {
88 default:
89 return value_new_error_NUM (ei->pos);
91 case VALUE_STRING:
92 if (flags & V2B_STRINGS_GENERAL) {
93 vstring = format_match_number
94 (value_peek_string (value), NULL,
95 sheet_date_conv (ei->pos->sheet));
96 if (!vstring || !VALUE_IS_FLOAT (vstring)) {
97 value_release (vstring);
98 return value_new_error_VALUE (ei->pos);
100 } else {
101 char const *str = value_peek_string (value);
102 size_t len;
103 gboolean hsuffix = FALSE;
104 char *err;
106 if ((flags & V2B_STRINGS_BLANK_ZERO) && *str == 0)
107 str = "0";
109 /* This prevents leading spaces, signs, etc, and "". */
110 if (!g_ascii_isalnum (*str))
111 return value_new_error_NUM (ei->pos);
113 len = strlen (str);
114 /* We check length in bytes. Since we are going to
115 require nothing but digits, that is fine. */
116 if ((flags & V2B_STRINGS_MAXLEN) && len > 10)
117 return value_new_error_NUM (ei->pos);
119 if (flags & V2B_STRINGS_0XH) {
120 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
121 str += 2;
122 else if (str[len - 1] == 'h' || str[len - 1] == 'H')
123 hsuffix = TRUE;
126 v = g_ascii_strtoll (str, &err, src_base);
127 if (err == str || err[hsuffix] != 0)
128 return value_new_error_NUM (ei->pos);
130 if (v < min_value || v > max_value)
131 return value_new_error_NUM (ei->pos);
133 break;
135 /* Fall through. */
137 case VALUE_FLOAT: {
138 gnm_float val = gnm_fake_trunc (value_get_as_float (vstring ? vstring : value));
139 char buf[GNM_MANT_DIG + 10];
140 char *err;
142 value_release (vstring);
144 if (val < min_value || val > max_value)
145 return value_new_error_NUM (ei->pos);
147 g_ascii_formatd (buf, sizeof (buf) - 1,
148 "%.0" GNM_FORMAT_f,
149 val);
151 v = g_ascii_strtoll (buf, &err, src_base);
152 if (*err != 0)
153 return value_new_error_NUM (ei->pos);
154 break;
158 if (src_base != 10) {
159 gnm_float b10 = gnm_pow (src_base, 10);
160 if (v >= b10 / 2) /* N's complement */
161 v = v - b10;
164 if (flags & V2B_NUMBER)
165 return value_new_float (v);
167 if (v < 0) {
168 min = 1;
169 max = 10;
170 v += gnm_pow (dest_base, max);
171 } else {
172 if (v == 0)
173 min = max = 1;
174 else
175 min = max = (int)(gnm_log (v + 0.5) /
176 gnm_log (dest_base)) + 1;
179 if (aplaces) {
180 gnm_float fplaces = value_get_as_float (aplaces);
181 if (fplaces < min || fplaces > 10)
182 return value_new_error_NUM (ei->pos);
183 places = (int)fplaces;
184 if (v >= 0 && places > max)
185 max = places;
186 } else
187 places = 1;
189 buffer = g_string_sized_new (max);
190 g_string_set_size (buffer, max);
192 for (digit = max - 1; digit >= 0; digit--) {
193 int thisdigit = gnm_fmod (v + 0.5, dest_base);
194 v = gnm_floor ((v + 0.5) / dest_base);
195 buffer->str[digit] =
196 thisdigit["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
199 return value_new_string_nocopy (g_string_free (buffer, FALSE));
202 /***************************************************************************/
204 static GnmFuncHelp const help_base[] = {
205 { GNM_FUNC_HELP_NAME, F_("BASE:string of digits representing the number @{n} in base @{b}") },
206 { GNM_FUNC_HELP_ARG, F_("n:integer") },
207 { GNM_FUNC_HELP_ARG, F_("b:base (2 \xe2\x89\xa4 @{b} \xe2\x89\xa4 36)") },
208 { GNM_FUNC_HELP_ARG, F_("length:minimum length of the resulting string") },
209 { GNM_FUNC_HELP_DESCRIPTION, F_("BASE converts @{n} to its string representation in base @{b}. "
210 "Leading zeroes will be added to reach the minimum length given by @{length}.") },
211 { GNM_FUNC_HELP_ODF, F_("This function is OpenFormula compatible.") },
212 { GNM_FUNC_HELP_EXAMPLES, "=BASE(255,16,4)" },
213 { GNM_FUNC_HELP_SEEALSO, "DECIMAL" },
214 { GNM_FUNC_HELP_END}
217 static GnmValue *
218 gnumeric_base (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
220 static const gnm_float max = 1 / GNM_EPSILON;
221 gnm_float base = value_get_as_float (argv[1]);
223 if (base < 2 || base >= 37)
224 return value_new_error_NUM (ei->pos);
226 return val_to_base (ei, argv[0], argv[2], 10, (int)base,
227 -max, +max,
228 V2B_STRINGS_GENERAL | V2B_STRINGS_0XH);
231 /***************************************************************************/
233 static GnmFuncHelp const help_bin2dec[] = {
234 { GNM_FUNC_HELP_NAME, F_("BIN2DEC:decimal representation of the binary number @{x}") },
235 { GNM_FUNC_HELP_ARG, F_("x:a binary number, either as a string or as a number involving only the digits 0 and 1") },
236 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
237 { GNM_FUNC_HELP_EXAMPLES, "=BIN2DEC(101)" },
238 { GNM_FUNC_HELP_SEEALSO, "DEC2BIN,BIN2OCT,BIN2HEX" },
239 { GNM_FUNC_HELP_END}
242 static GnmValue *
243 gnumeric_bin2dec (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
245 return val_to_base (ei, argv[0], NULL,
246 2, 10,
247 0, GNM_const(1111111111.0),
248 V2B_STRINGS_MAXLEN |
249 V2B_STRINGS_BLANK_ZERO |
250 V2B_NUMBER);
253 /***************************************************************************/
255 static GnmFuncHelp const help_bin2oct[] = {
256 { GNM_FUNC_HELP_NAME, F_("BIN2OCT:octal representation of the binary number @{x}") },
257 { GNM_FUNC_HELP_ARG, F_("x:a binary number, either as a string or as a number involving only the digits 0 and 1") },
258 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
259 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, BIN2OCT pads the result with zeros to achieve "
260 "exactly @{places} digits. If this is not possible, BIN2OCT returns #NUM!") },
261 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
262 { GNM_FUNC_HELP_EXAMPLES, "=BIN2OCT(110111)" },
263 { GNM_FUNC_HELP_EXAMPLES, "=BIN2OCT(110111,4)" },
264 { GNM_FUNC_HELP_SEEALSO, ("OCT2BIN,BIN2DEC,BIN2HEX") },
265 { GNM_FUNC_HELP_END}
268 static GnmValue *
269 gnumeric_bin2oct (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
271 return val_to_base (ei, argv[0], argv[1],
272 2, 8,
273 0, GNM_const(1111111111.0),
274 V2B_STRINGS_MAXLEN | V2B_STRINGS_BLANK_ZERO);
277 /***************************************************************************/
279 static GnmFuncHelp const help_bin2hex[] = {
280 { GNM_FUNC_HELP_NAME, F_("BIN2HEX:hexadecimal representation of the binary number @{x}") },
281 { GNM_FUNC_HELP_ARG, F_("x:a binary number, either as a string or as a number involving only the digits 0 and 1") },
282 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
283 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, BIN2HEX pads the result with zeros to achieve "
284 "exactly @{places} digits. If this is not possible, BIN2HEX returns #NUM!") },
285 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
286 { GNM_FUNC_HELP_EXAMPLES, "=BIN2HEX(100111)" },
287 { GNM_FUNC_HELP_EXAMPLES, "=BIN2HEX(110111,4)" },
288 { GNM_FUNC_HELP_SEEALSO, ("HEX2BIN,BIN2OCT,BIN2DEC") },
289 { GNM_FUNC_HELP_END}
293 static GnmValue *
294 gnumeric_bin2hex (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
296 return val_to_base (ei, argv[0], argv[1],
297 2, 16,
298 0, GNM_const(1111111111.0),
299 V2B_STRINGS_MAXLEN | V2B_STRINGS_BLANK_ZERO);
302 /***************************************************************************/
304 static GnmFuncHelp const help_dec2bin[] = {
305 { GNM_FUNC_HELP_NAME, F_("DEC2BIN:binary representation of the decimal number @{x}") },
306 { GNM_FUNC_HELP_ARG, F_("x:integer (\xe2\x88\x92 513 < @{x} < 512)") },
307 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
308 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given and @{x} is non-negative, "
309 "DEC2BIN pads the result with zeros to achieve "
310 "exactly @{places} digits. If this is not possible, "
311 "DEC2BIN returns #NUM!")},
312 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given and @{x} is negative, @{places} is ignored.") },
313 { GNM_FUNC_HELP_NOTE, F_("If @{x} < \xe2\x88\x92 512 or @{x} > 511, DEC2BIN returns #NUM!") },
314 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
315 { GNM_FUNC_HELP_ODF, F_("This function is OpenFormula compatible.") },
316 { GNM_FUNC_HELP_EXAMPLES, "=DEC2BIN(42,6)" },
317 { GNM_FUNC_HELP_EXAMPLES, "=DEC2BIN(-42,6)" },
318 { GNM_FUNC_HELP_SEEALSO, ("BIN2DEC,DEC2OCT,DEC2HEX") },
319 { GNM_FUNC_HELP_END}
323 static GnmValue *
324 gnumeric_dec2bin (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
326 return val_to_base (ei, argv[0], argv[1],
327 10, 2,
328 -512, 511,
329 V2B_STRINGS_GENERAL);
332 /***************************************************************************/
334 static GnmFuncHelp const help_dec2oct[] = {
335 { GNM_FUNC_HELP_NAME, F_("DEC2OCT:octal representation of the decimal number @{x}") },
336 { GNM_FUNC_HELP_ARG, F_("x:integer") },
337 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
338 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, DEC2OCT pads the result with zeros to achieve "
339 "exactly @{places} digits. If this is not possible, DEC2OCT returns #NUM!") },
340 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
341 { GNM_FUNC_HELP_EXAMPLES, "=DEC2OCT(42)" },
342 { GNM_FUNC_HELP_SEEALSO, ("OCT2DEC,DEC2BIN,DEC2HEX") },
343 { GNM_FUNC_HELP_END}
346 static GnmValue *
347 gnumeric_dec2oct (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
349 return val_to_base (ei, argv[0], argv[1],
350 10, 8,
351 -536870912, 536870911,
352 V2B_STRINGS_GENERAL);
355 /***************************************************************************/
357 static GnmFuncHelp const help_dec2hex[] = {
358 { GNM_FUNC_HELP_NAME, F_("DEC2HEX:hexadecimal representation of the decimal number @{x}") },
359 { GNM_FUNC_HELP_ARG, F_("x:integer") },
360 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
361 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, DEC2HEX pads the result with zeros to achieve "
362 "exactly @{places} digits. If this is not possible, DEC2HEX returns #NUM!") },
363 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
364 { GNM_FUNC_HELP_EXAMPLES, "=DEC2HEX(42)" },
365 { GNM_FUNC_HELP_SEEALSO, ("HEX2DEC,DEC2BIN,DEC2OCT") },
366 { GNM_FUNC_HELP_END}
369 static GnmValue *
370 gnumeric_dec2hex (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
372 return val_to_base (ei, argv[0], argv[1],
373 10, 16,
374 GNM_const(-549755813888.0), GNM_const(549755813887.0),
375 V2B_STRINGS_GENERAL);
378 /***************************************************************************/
380 static GnmFuncHelp const help_decimal[] = {
381 { GNM_FUNC_HELP_NAME, F_("DECIMAL:decimal representation of @{x}") },
382 { GNM_FUNC_HELP_ARG, F_("x:number in base @{base}") },
383 { GNM_FUNC_HELP_ARG, F_("base:base of @{x}, (2 \xe2\x89\xa4 @{base} \xe2\x89\xa4 36)") },
384 { GNM_FUNC_HELP_ODF, F_("This function is OpenFormula compatible.") },
385 { GNM_FUNC_HELP_EXAMPLES, "=DECIMAL(\"A1\",16)" },
386 { GNM_FUNC_HELP_EXAMPLES, "=DECIMAL(\"A1\",15)" },
387 { GNM_FUNC_HELP_SEEALSO, "BASE" },
388 { GNM_FUNC_HELP_END}
391 static GnmValue *
392 gnumeric_decimal (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
394 gnm_float base = value_get_as_float (argv[1]);
395 static gnm_float pow_2_40 = GNM_const(1099511627776.0);
397 if (base < 2 || base >= 37)
398 return value_new_error_NUM (ei->pos);
400 return val_to_base (ei, argv[0], NULL,
401 (int)base, 10,
402 0, pow_2_40 - 1,
403 V2B_STRINGS_MAXLEN |
404 V2B_STRINGS_BLANK_ZERO |
405 V2B_NUMBER);
408 /***************************************************************************/
410 static GnmFuncHelp const help_oct2dec[] = {
411 { GNM_FUNC_HELP_NAME, F_("OCT2DEC:decimal representation of the octal number @{x}") },
412 { GNM_FUNC_HELP_ARG, F_("x:a octal number, either as a string or as a number") },
413 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
414 { GNM_FUNC_HELP_EXAMPLES, "=OCT2DEC(\"124\")" },
415 { GNM_FUNC_HELP_EXAMPLES, "=OCT2DEC(124)" },
416 { GNM_FUNC_HELP_SEEALSO, ("DEC2OCT,OCT2BIN,OCT2HEX") },
417 { GNM_FUNC_HELP_END}
421 static GnmValue *
422 gnumeric_oct2dec (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
424 return val_to_base (ei, argv[0], NULL,
425 8, 10,
426 0, GNM_const(7777777777.0),
427 V2B_STRINGS_MAXLEN |
428 V2B_STRINGS_BLANK_ZERO |
429 V2B_NUMBER);
432 /***************************************************************************/
434 static GnmFuncHelp const help_oct2bin[] = {
435 { GNM_FUNC_HELP_NAME, F_("OCT2BIN:binary representation of the octal number @{x}") },
436 { GNM_FUNC_HELP_ARG, F_("x:a octal number, either as a string or as a number") },
437 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
438 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, OCT2BIN pads the result with zeros to achieve "
439 "exactly @{places} digits. If this is not possible, OCT2BIN returns #NUM!") },
440 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
441 { GNM_FUNC_HELP_EXAMPLES, "=OCT2BIN(\"213\")" },
442 { GNM_FUNC_HELP_SEEALSO, ("BIN2OCT,OCT2DEC,OCT2HEX") },
443 { GNM_FUNC_HELP_END}
446 static GnmValue *
447 gnumeric_oct2bin (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
449 return val_to_base (ei, argv[0], argv[1],
450 8, 2,
451 0, GNM_const(7777777777.0),
452 V2B_STRINGS_MAXLEN | V2B_STRINGS_BLANK_ZERO);
455 /***************************************************************************/
457 static GnmFuncHelp const help_oct2hex[] = {
458 { GNM_FUNC_HELP_NAME, F_("OCT2HEX:hexadecimal representation of the octal number @{x}") },
459 { GNM_FUNC_HELP_ARG, F_("x:a octal number, either as a string or as a number") },
460 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
461 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, OCT2HEX pads the result with zeros to achieve "
462 "exactly @{places} digits. If this is not possible, OCT2HEX returns #NUM!") },
463 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
464 { GNM_FUNC_HELP_EXAMPLES, "=OCT2HEX(132)" },
465 { GNM_FUNC_HELP_SEEALSO, ("HEX2OCT,OCT2BIN,OCT2DEC") },
466 { GNM_FUNC_HELP_END}
469 static GnmValue *
470 gnumeric_oct2hex (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
472 return val_to_base (ei, argv[0], argv[1],
473 8, 16,
474 0, GNM_const(7777777777.0),
475 V2B_STRINGS_MAXLEN | V2B_STRINGS_BLANK_ZERO);
478 /***************************************************************************/
480 static GnmFuncHelp const help_hex2bin[] = {
481 { GNM_FUNC_HELP_NAME, F_("HEX2BIN:binary representation of the hexadecimal number @{x}") },
482 { GNM_FUNC_HELP_ARG, F_("x:a hexadecimal number, either as a string or as a number if no A to F are needed") },
483 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
484 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, HEX2BIN pads the result with zeros to achieve "
485 "exactly @{places} digits. If this is not possible, HEX2BIN returns #NUM!") },
486 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
487 { GNM_FUNC_HELP_EXAMPLES, "=HEX2BIN(\"2A\")" },
488 { GNM_FUNC_HELP_SEEALSO, ("BIN2HEX,HEX2OCT,HEX2DEC") },
489 { GNM_FUNC_HELP_END}
492 static GnmValue *
493 gnumeric_hex2bin (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
495 return val_to_base (ei, argv[0], argv[1],
496 16, 2,
497 0, GNM_const(9999999999.0),
498 V2B_STRINGS_MAXLEN | V2B_STRINGS_BLANK_ZERO);
501 /***************************************************************************/
503 static GnmFuncHelp const help_hex2oct[] = {
504 { GNM_FUNC_HELP_NAME, F_("HEX2OCT:octal representation of the hexadecimal number @{x}") },
505 { GNM_FUNC_HELP_ARG, F_("x:a hexadecimal number, either as a string or as a number if no A to F are needed") },
506 { GNM_FUNC_HELP_ARG, F_("places:number of digits") },
507 { GNM_FUNC_HELP_DESCRIPTION, F_("If @{places} is given, HEX2OCT pads the result with zeros to achieve "
508 "exactly @{places} digits. If this is not possible, HEX2OCT returns #NUM!") },
509 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
510 { GNM_FUNC_HELP_EXAMPLES, "=HEX2OCT(\"2A\")" },
511 { GNM_FUNC_HELP_SEEALSO, ("OCT2HEX,HEX2BIN,HEX2DEC") },
512 { GNM_FUNC_HELP_END}
515 static GnmValue *
516 gnumeric_hex2oct (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
518 return val_to_base (ei, argv[0], argv[1],
519 16, 8,
520 0, GNM_const(9999999999.0),
521 V2B_STRINGS_MAXLEN | V2B_STRINGS_BLANK_ZERO);
524 /***************************************************************************/
526 static GnmFuncHelp const help_hex2dec[] = {
527 { GNM_FUNC_HELP_NAME, F_("HEX2DEC:decimal representation of the hexadecimal number @{x}") },
528 { GNM_FUNC_HELP_ARG, F_("x:a hexadecimal number, either as a string or as a number if no A to F are needed") },
529 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
530 { GNM_FUNC_HELP_EXAMPLES, "=HEX2DEC(\"2A\")" },
531 { GNM_FUNC_HELP_SEEALSO, ("DEC2HEX,HEX2BIN,HEX2OCT") },
532 { GNM_FUNC_HELP_END}
535 static GnmValue *
536 gnumeric_hex2dec (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
538 static gnm_float pow_2_40 = GNM_const(1099511627776.0);
539 return val_to_base (ei, argv[0], NULL,
540 16, 10,
541 0, pow_2_40 - 1,
542 V2B_STRINGS_MAXLEN |
543 V2B_STRINGS_BLANK_ZERO |
544 V2B_NUMBER);
547 /***************************************************************************/
549 static GnmFuncHelp const help_besseli[] = {
550 { GNM_FUNC_HELP_NAME, F_("BESSELI:Modified Bessel function of the first kind of order @{\xce\xb1} at @{x}") },
551 { GNM_FUNC_HELP_ARG, F_("X:number") },
552 { GNM_FUNC_HELP_ARG, F_("\xce\xb1:order (any non-negative number)") },
553 { GNM_FUNC_HELP_NOTE, F_("If @{x} or @{\xce\xb1} are not numeric, #VALUE! is returned. If @{\xce\xb1} < 0, #NUM! is returned.") },
554 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible if only integer orders @{\xce\xb1} are used.") },
555 { GNM_FUNC_HELP_EXAMPLES, "=BESSELI(0.7,3)" },
556 { GNM_FUNC_HELP_SEEALSO, "BESSELJ,BESSELK,BESSELY" },
557 { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Bessel_function") },
558 { GNM_FUNC_HELP_END}
561 static GnmValue *
562 gnumeric_besseli (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
564 gnm_float x = value_get_as_float (argv[0]);
565 gnm_float order = value_get_as_float (argv[1]);
566 return value_new_float (gnm_bessel_i (x, order));
569 /***************************************************************************/
571 static GnmFuncHelp const help_besselk[] = {
572 { GNM_FUNC_HELP_NAME, F_("BESSELK:Modified Bessel function of the second kind of order @{\xce\xb1} at @{x}") },
573 { GNM_FUNC_HELP_ARG, F_("X:number") },
574 { GNM_FUNC_HELP_ARG, F_("\xce\xb1:order (any non-negative number)") },
575 { GNM_FUNC_HELP_NOTE, F_("If @{x} or @{\xce\xb1} are not numeric, #VALUE! is returned. If @{\xce\xb1} < 0, #NUM! is returned.") },
576 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible if only integer orders @{\xce\xb1} are used.") },
577 { GNM_FUNC_HELP_EXAMPLES, "=BESSELK(3,9)" },
578 { GNM_FUNC_HELP_SEEALSO, "BESSELI,BESSELJ,BESSELY" },
579 { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Bessel_function") },
580 { GNM_FUNC_HELP_END}
584 static GnmValue *
585 gnumeric_besselk (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
587 gnm_float x = value_get_as_float (argv[0]);
588 gnm_float order = value_get_as_float (argv[1]); /* the order */
589 return value_new_float (gnm_bessel_k (x, order));
592 /***************************************************************************/
594 static GnmFuncHelp const help_besselj[] = {
595 { GNM_FUNC_HELP_NAME, F_("BESSELJ:Bessel function of the first kind of order @{\xce\xb1} at @{x}") },
596 { GNM_FUNC_HELP_ARG, F_("X:number") },
597 { GNM_FUNC_HELP_ARG, F_("\xce\xb1:order (any non-negative integer)") },
598 { GNM_FUNC_HELP_NOTE, F_("If @{x} or @{\xce\xb1} are not numeric, #VALUE! is returned. "
599 "If @{\xce\xb1} < 0, #NUM! is returned.") },
600 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible if only integer orders @{\xce\xb1} are used.") },
601 { GNM_FUNC_HELP_EXAMPLES, "=BESSELJ(0.89,3)" },
602 { GNM_FUNC_HELP_SEEALSO, "BESSELI,BESSELK,BESSELY" },
603 { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Bessel_function") },
604 { GNM_FUNC_HELP_END}
607 static GnmValue *
608 gnumeric_besselj (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
610 gnm_float x = value_get_as_float (argv[0]);
611 gnm_float y = value_get_as_float (argv[1]);
612 return value_new_float (gnm_bessel_j (x, y));
615 /***************************************************************************/
617 static GnmFuncHelp const help_bessely[] = {
618 { GNM_FUNC_HELP_NAME, F_("BESSELY:Bessel function of the second kind of order @{\xce\xb1} at @{x}") },
619 { GNM_FUNC_HELP_ARG, F_("X:number") },
620 { GNM_FUNC_HELP_ARG, F_("\xce\xb1:order (any non-negative integer)") },
621 { GNM_FUNC_HELP_NOTE, F_("If @{x} or @{\xce\xb1} are not numeric, #VALUE! is returned. "
622 "If @{\xce\xb1} < 0, #NUM! is returned.") },
623 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible if only integer orders @{\xce\xb1} are used.") },
624 { GNM_FUNC_HELP_EXAMPLES, "=BESSELY(4,2)" },
625 { GNM_FUNC_HELP_SEEALSO, "BESSELI,BESSELJ,BESSELK" },
626 { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Bessel_function") },
627 { GNM_FUNC_HELP_END}
630 static GnmValue *
631 gnumeric_bessely (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
633 gnm_float x = value_get_as_float (argv[0]);
634 gnm_float y = value_get_as_float (argv[1]);
635 return value_new_float (gnm_bessel_y (x, y));
638 /***************************************************************************/
640 static GnmFuncHelp const help_convert[] = {
641 { GNM_FUNC_HELP_NAME, F_("CONVERT:a converted measurement") },
642 { GNM_FUNC_HELP_ARG, F_("x:number") },
643 { GNM_FUNC_HELP_ARG, F_("from:unit (string)") },
644 { GNM_FUNC_HELP_ARG, F_("to:unit (string)") },
645 { GNM_FUNC_HELP_DESCRIPTION, F_("CONVERT returns a conversion from one measurement system to another. "
646 "@{x} is a value in @{from} units that is to be converted into @{to} units.") },
647 { GNM_FUNC_HELP_NOTE, F_("If @{from} and @{to} are different types, CONVERT returns #N/A!") },
648 { GNM_FUNC_HELP_DESCRIPTION, F_("@{from} and @{to} can be any of the following:\n\n"
649 "Weight and mass:\n"
650 "\t'brton'\t\tImperial ton\n"
651 "\t'cwt'\t\t\tU.S. (short) hundredweight\n"
652 "\t'g' \t\t\tGram\n"
653 "\t'grain'\t\tGrain\n"
654 "\t'hweight'\t\tImperial (long) hundredweight\n"
655 "\t'LTON'\t\tImperial ton\n"
656 "\t'sg' \t\t\tSlug\n"
657 "\t'shweight'\tU.S. (short) hundredweight\n"
658 "\t'lbm'\t\tPound\n"
659 "\t'lcwt'\t\tImperial (long) hundredweight\n"
660 "\t'u' \t\t\tU (atomic mass)\n"
661 "\t'uk_cwt'\t\tImperial (long) hundredweight\n"
662 "\t'uk_ton'\t\tImperial ton\n"
663 "\t'ozm'\t\tOunce\n"
664 "\t'stone'\t\tStone\n"
665 "\t'ton'\t\t\tTon\n\n"
666 "Distance:\n"
667 "\t'm' \t\tMeter\n"
668 "\t'mi' \t\tStatute mile\n"
669 "\t'survey_mi' \tU.S. survey mile\n"
670 "\t'Nmi' \t\tNautical mile\n"
671 "\t'in' \t\t\tInch\n"
672 "\t'ft' \t\t\tFoot\n"
673 "\t'yd' \t\tYard\n"
674 "\t'ell' \t\t\tEnglish Ell\n"
675 "\t'ang' \t\tAngstrom\n"
676 "\t'ly' \t\t\tLight-Year\n"
677 "\t'pc' \t\t\tParsec\n"
678 "\t'parsec' \t\tParsec\n"
679 "\t'Pica'\t\tPica Points\n"
680 "\t'Picapt'\t\tPica Points\n"
681 "\t'picapt'\t\tPica Points\n"
682 "\t'pica'\t\tPica\n\n"
683 "Time:\n"
684 "\t'yr' \t\t\tYear\n"
685 "\t'day' \t\tDay\n"
686 "\t'hr' \t\t\tHour\n"
687 "\t'mn' \t\tMinute\n"
688 "\t'sec' \t\tSecond\n\n"
689 "Pressure:\n"
690 "\t'Pa' \t\t\tPascal\n"
691 "\t'psi' \t\t\tPSI\n"
692 "\t'atm' \t\tAtmosphere\n"
693 "\t'Pa' \t\t\tPascal\n"
694 "\t'mmHg'\t\tmm of Mercury\n"
695 "\t'Torr'\t\t\tTorr\n\n"
696 "Force:\n"
697 "\t'N' \t\t\tNewton\n"
698 "\t'dyn' \t\tDyne\n"
699 "\t'pond' \t\tPond\n"
700 "\t'lbf' \t\t\tPound force\n\n"
701 "Energy:\n"
702 "\t'J' \t\t\tJoule\n"
703 "\t'e' \t\tErg\n"
704 "\t'c' \t\tThermodynamic calorie\n"
705 "\t'cal' \t\tIT calorie\n"
706 "\t'eV' \t\tElectron volt\n"
707 "\t'HPh' \t\tHorsepower-hour\n"
708 "\t'Wh' \t\tWatt-hour\n"
709 "\t'flb' \t\tFoot-pound\n"
710 "\t'BTU' \t\tBTU\n\n"
711 "Power:\n"
712 "\t'HP' \t\tHorsepower\n"
713 "\t'PS' \t\tPferdestärke\n"
714 "\t'W' \t\tWatt\n\n"
715 "Magnetism:\n"
716 "\t'T' \t\tTesla\n"
717 "\t'ga' \t\tGauss\n\n"
718 "Temperature:\n"
719 "\t'C' \t\tDegree Celsius\n"
720 "\t'F' \t\tDegree Fahrenheit\n"
721 "\t'K' \t\tKelvin\n"
722 "\t'Rank' \t\tDegree Rankine\n"
723 "\t'Reau' \t\tDegree Réaumur\n\n"
724 "Volume (liquid measure):\n"
725 "\t'tsp' \t\tTeaspoon\n"
726 "\t'tspm' \t\tTeaspoon (modern, metric)\n"
727 "\t'tbs' \t\tTablespoon\n"
728 "\t'oz' \t\tFluid ounce\n"
729 "\t'cup' \t\tCup\n"
730 "\t'pt' \t\tPint\n"
731 "\t'us_pt'\t\tU.S. pint\n"
732 "\t'uk_pt'\t\tImperial pint (U.K.)\n"
733 "\t'qt' \t\tQuart\n"
734 "\t'uk_qt' \t\tImperial quart\n"
735 "\t'gal' \t\tGallon\n"
736 "\t'uk_gal' \t\tImperial gallon\n"
737 "\t'GRT' \t\tRegistered ton\n"
738 "\t'regton' \t\tRegistered ton\n"
739 "\t'MTON' \t\tMeasurement ton (freight ton)\n"
740 "\t'l' \t\t\tLiter\n"
741 "\t'L' \t\tLiter\n"
742 "\t'lt' \t\t\tLiter\n"
743 "\t'ang3' \t\tCubic Angstrom\n"
744 "\t'ang^3' \t\tCubic Angstrom\n"
745 "\t'barrel' \t\tU.S. oil barrel (bbl)\n"
746 "\t'bushel' \t\tU.S. bushel\n"
747 "\t'ft3' \t\t\tCubic feet\n"
748 "\t'ft^3' \t\tCubic feet\n"
749 "\t'in3' \t\tCubic inch\n"
750 "\t'in^3' \t\tCubic inch\n"
751 "\t'ly3' \t\t\tCubic light-year\n"
752 "\t'ly^3' \t\tCubic light-year\n"
753 "\t'm3' \t\tCubic meter\n"
754 "\t'm^3' \t\tCubic meter\n"
755 "\t'mi3' \t\tCubic mile\n"
756 "\t'mi^3' \t\tCubic mile\n"
757 "\t'yd3' \t\tCubic yard\n"
758 "\t'yd^3' \t\tCubic yard\n"
759 "\t'Nmi3' \t\tCubic nautical mile\n"
760 "\t'Nmi^3' \t\tCubic nautical mile\n"
761 "\t'Picapt3' \t\tCubic Pica\n"
762 "\t'Picapt^3' \tCubic Pica\n"
763 "\t'Pica3' \t\tCubic Pica\n"
764 "\t'Pica^3' \t\tCubic Pica\n\n"
765 "Area:\n"
766 "\t'uk_acre' \t\tInternational acre\n"
767 "\t'us_acre' \t\tU.S. survey/statute acre\n"
768 "\t'ang2' \t\tSquare angstrom\n"
769 "\t'ang^2' \t\tSquare angstrom\n"
770 "\t'ar' \t\t\tAre\n"
771 "\t'ha' \t\t\tHectare\n"
772 "\t'in2' \t\tSquare inches\n"
773 "\t'in^2' \t\tSquare inches\n"
774 "\t'ly2' \t\t\tSquare light-year\n"
775 "\t'ly^2' \t\tSquare light-year\n"
776 "\t'm2' \t\tSquare meter\n"
777 "\t'm^2' \t\tSquare meter\n"
778 "\t'Morgen' \t\tMorgen (North German Confederation)\n"
779 "\t'mi2' \t\tSquare miles\n"
780 "\t'mi^2' \t\tSquare miles\n"
781 "\t'Nmi2' \t\tSquare nautical miles\n"
782 "\t'Nmi^2' \t\tSquare nautical miles\n"
783 "\t'Picapt2' \t\tSquare Pica\n"
784 "\t'Picapt^2' \tSquare Pica\n"
785 "\t'Pica2' \t\tSquare Pica\n"
786 "\t'Pica^2' \t\tSquare Pica\n"
787 "\t'yd2' \t\tSquare yards\n"
788 "\t'yd^2' \t\tSquare yards\n\n"
789 "Bits and Bytes:\n"
790 "\t'bit' \t\t\tBit\n"
791 "\t'byte' \t\tByte\n\n"
792 "Speed:\n"
793 "\t'admkn' \t\tAdmiralty knot\n"
794 "\t'kn' \t\t\tknot\n"
795 "\t'm/h' \t\tMeters per hour\n"
796 "\t'm/hr' \t\tMeters per hour\n"
797 "\t'm/s' \t\tMeters per second\n"
798 "\t'm/sec' \t\tMeters per second\n"
799 "\t'mph' \t\tMiles per hour\n\n"
800 "For metric units any of the following prefixes can be used:\n"
801 "\t'Y' \tyotta \t\t1E+24\n"
802 "\t'Z' \tzetta \t\t1E+21\n"
803 "\t'E' \texa \t\t1E+18\n"
804 "\t'P' \tpeta \t\t1E+15\n"
805 "\t'T' \ttera \t\t1E+12\n"
806 "\t'G' \tgiga \t\t1E+09\n"
807 "\t'M' \tmega \t\t1E+06\n"
808 "\t'k' \tkilo \t\t\t1E+03\n"
809 "\t'h' \thecto \t\t1E+02\n"
810 "\t'e' \tdeca (deka)\t1E+01\n"
811 "\t'd' \tdeci \t\t1E-01\n"
812 "\t'c' \tcenti \t\t1E-02\n"
813 "\t'm' \tmilli \t\t\t1E-03\n"
814 "\t'u' \tmicro \t\t1E-06\n"
815 "\t'n' \tnano \t\t1E-09\n"
816 "\t'p' \tpico \t\t1E-12\n"
817 "\t'f' \tfemto \t\t1E-15\n"
818 "\t'a' \tatto \t\t1E-18\n"
819 "\t'z' \tzepto \t\t1E-21\n"
820 "\t'y' \tyocto \t\t1E-24\n\n"
821 "For bits and bytes any of the following prefixes can be also be used:\n"
822 "\t'Yi' \tyobi \t\t2^80\n"
823 "\t'Zi' \tzebi \t\t\t2^70\n"
824 "\t'Ei' \texbi \t\t2^60\n"
825 "\t'Pi' \tpebi \t\t2^50\n"
826 "\t'Ti' \ttebi \t\t\t2^40\n"
827 "\t'Gi' \tgibi \t\t\t2^30\n"
828 "\t'Mi' \tmebi \t\t2^20\n"
829 "\t'ki' \tkibi \t\t\t2^10") },
830 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible (except \"picapt\").") },
831 { GNM_FUNC_HELP_ODF, F_("This function is OpenFormula compatible.") },
832 { GNM_FUNC_HELP_EXAMPLES, "=CONVERT(3,\"lbm\",\"g\")" },
833 { GNM_FUNC_HELP_EXAMPLES, "=CONVERT(5.8,\"m\",\"in\")" },
834 { GNM_FUNC_HELP_EXAMPLES, "=CONVERT(7.9,\"cal\",\"J\")" },
835 { GNM_FUNC_HELP_EXAMPLES, "=CONVERT(3,\"Yibyte\",\"bit\")" },
836 { GNM_FUNC_HELP_END}
839 typedef struct {
840 char const *str;
841 gnm_float c;
842 } eng_convert_unit_t;
845 static gnm_float
846 get_constant_of_unit(const eng_convert_unit_t units[],
847 const eng_convert_unit_t prefixes[],
848 char const *unit_name,
849 gnm_float *c, gnm_float *prefix)
851 int i;
853 *prefix = 1;
854 for (i = 0; units[i].str != NULL; i++)
855 if (strcmp (unit_name, units[i].str) == 0) {
856 *c = units[i].c;
857 return 1;
860 if (prefixes != NULL)
861 for (i = 0; prefixes[i].str != NULL; i++) {
862 int prefix_length = strlen (prefixes[i].str);
863 if (strncmp (unit_name, prefixes[i].str, prefix_length) == 0) {
864 *prefix = prefixes[i].c;
865 unit_name += prefix_length;
866 break;
870 for (i = 0; units[i].str != NULL; i++)
871 if (strcmp (unit_name, units[i].str) == 0) {
872 *c = units[i].c;
873 return 1;
876 return 0;
879 /* See also http://physics.nist.gov/cuu/Units/prefixes.html */
881 static gboolean
882 convert (eng_convert_unit_t const units[],
883 eng_convert_unit_t const prefixes[],
884 char const *from_unit, char const *to_unit,
885 gnm_float n, GnmValue **v, GnmEvalPos const *ep)
887 gnm_float from_c, from_prefix, to_c, to_prefix;
889 if (get_constant_of_unit (units, prefixes, from_unit, &from_c,
890 &from_prefix)) {
892 if (!get_constant_of_unit (units, prefixes,
893 to_unit, &to_c, &to_prefix))
894 *v = value_new_error_NUM (ep);
895 else if (from_c == 0 || to_prefix == 0)
896 *v = value_new_error_NUM (ep);
897 else
898 *v = value_new_float (((n * from_prefix) / from_c) *
899 to_c / to_prefix);
900 return TRUE;
903 return FALSE;
906 typedef enum {
907 temp_invalid = 0,
908 temp_K,
909 temp_C,
910 temp_F,
911 temp_Rank,
912 temp_Reau
913 } temp_types;
915 static temp_types
916 convert_temp_unit (char const *unit) {
917 if (0 == strcmp (unit, "K"))
918 return temp_K;
919 else if (0 == strcmp (unit, "C"))
920 return temp_C;
921 else if (0 == strcmp (unit, "F"))
922 return temp_F;
923 else if (0 == strcmp (unit, "Reau"))
924 return temp_Reau;
925 else if (0 == strcmp (unit, "Rank"))
926 return temp_Rank;
927 return temp_invalid;
930 static gboolean
931 convert_temp (char const *from_unit, char const *to_unit, gnm_float n, GnmValue **v, GnmEvalPos const *ep)
933 /* Temperature constants */
934 const gnm_float C_K_offset = GNM_const (273.15);
936 temp_types from_unit_type = convert_temp_unit (from_unit);
937 temp_types to_unit_type = convert_temp_unit (to_unit);
939 gnm_float nO = n;
941 if ((from_unit_type == temp_invalid) || (to_unit_type == temp_invalid))
942 return FALSE;
944 /* Convert from from_unit to K */
945 switch (from_unit_type) {
946 case temp_C:
947 n += C_K_offset;
948 break;
949 case temp_F:
950 n = (n - 32) * 5 / 9 + C_K_offset;
951 break;
952 case temp_Rank:
953 n = n * 5/9;
954 break;
955 case temp_Reau:
956 n = n * 5/4 + C_K_offset;
957 break;
958 default:
959 break;
962 /* temperatures below 0K do not exist */
963 if (n < 0.) {
964 *v = value_new_error_NUM (ep);
965 return TRUE;
968 if (from_unit_type == to_unit_type) {
969 *v = value_new_float (nO);
970 return TRUE;
973 /* Convert from K to to_unit */
974 switch (to_unit_type) {
975 case temp_C:
976 n -= C_K_offset;
977 break;
978 case temp_F:
979 n = (n - C_K_offset) * 9/5 + 32;
980 break;
981 case temp_Rank:
982 n = n * 9/5;
983 break;
984 case temp_Reau:
985 n = (n - C_K_offset) * 4/5;
986 break;
987 default:
988 break;
991 *v = value_new_float (n);
993 return TRUE;
996 static GnmValue *
997 gnumeric_convert (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
999 /* Weight and mass constants */
1000 #define one_g_to_cwt (one_g_to_lbm/100) /* exact relative definition */
1001 #define one_g_to_grain (one_g_to_lbm*7000) /* exact relative definition */
1002 #define one_g_to_uk_cwt (one_g_to_lbm/112) /* exact relative definition */
1003 #define one_g_to_uk_ton (one_g_to_lbm/2240) /* exact relative definition */
1004 #define one_g_to_stone (one_g_to_lbm/14) /* exact relative definition */
1005 #define one_g_to_ton (one_g_to_lbm/2000) /* exact relative definition */
1006 #define one_g_to_sg GNM_const (0.00006852205001)
1007 #define one_g_to_lbm (1/GNM_const (453.59237)) /* exact definition */
1008 #define one_g_to_u GNM_const (6.02217e+23)
1009 #define one_g_to_ozm (one_g_to_lbm*16) /* exact relative definition */
1011 /* Distance constants */
1012 #define one_m_to_mi (one_m_to_yd / 1760)
1013 #define one_m_to_survey_mi (1 / GNM_const (1609.347218694))
1014 #define one_m_to_Nmi (1 / GNM_const (1852.0))
1015 #define one_m_to_in (10000 / GNM_const (254.0))
1016 #define one_m_to_ft (one_m_to_in / 12)
1017 #define one_m_to_yd (one_m_to_ft / 3)
1018 #define one_m_to_ell (one_m_to_in / 45)
1019 #define one_m_to_ang GNM_const (1e10)
1020 #define one_m_to_ly (1 / GNM_const (9.4607304725808E15))
1021 #define one_m_to_pc (GNM_const (1e-16)/GNM_const (3.0856776))
1022 #define one_m_to_pica 236.2204724409449
1023 #define one_m_to_Pica one_m_to_pica * 12
1025 /* Time constants */
1026 #define one_yr_to_day 365.25
1027 #define one_yr_to_hr (24 * one_yr_to_day)
1028 #define one_yr_to_mn (60 * one_yr_to_hr)
1029 #define one_yr_to_sec (60 * one_yr_to_mn)
1031 /* Pressure constants */
1032 #define one_Pa_to_atm 0.9869233e-5
1033 #define one_Pa_to_mmHg 0.00750061708
1034 #define one_Pa_to_psi 0.000145037738
1035 #define one_Pa_to_Torr (GNM_const (760)/GNM_const (101325))
1037 /* Force constants */
1038 #define one_N_to_dyn 100000
1039 #define one_N_to_lbf 0.224808924
1040 #define one_N_to_pond 0.00010197
1043 /* Power constants */
1044 #define one_HP_to_W 745.701
1045 #define one_PS_to_W 735.49875
1047 /* Energy constants */
1048 #define one_J_to_e 9999995.193
1049 #define one_J_to_c 0.239006249
1050 #define one_J_to_cal 0.238846191
1051 #define one_J_to_eV 6.2146e+18
1052 #define one_J_to_HPh (GNM_const (1.0) / (3600 * one_HP_to_W))
1053 #define one_J_to_Wh (GNM_const (1.0) / 3600)
1054 #define one_J_to_flb 23.73042222
1055 #define one_J_to_BTU 0.000947815
1057 /* Magnetism constants */
1058 #define one_T_to_ga 10000
1060 /* Liquid measure constants */
1061 #define one_l_to_uk_gal (GNM_const (1.0) / GNM_const (4.54609))
1062 #define one_tsp_to_tspm (one_tsp_to_l/GNM_const (0.005))
1063 #define one_tsp_to_tbs (GNM_const (1.0) / 3)
1064 #define one_tsp_to_oz (GNM_const (1.0) / 6)
1065 #define one_tsp_to_cup (GNM_const (1.0) / 48)
1066 #define one_tsp_to_pt (GNM_const (1.0) / 96)
1067 #define one_tsp_to_uk_pt (one_tsp_to_l * one_l_to_uk_gal * 8)
1068 #define one_tsp_to_qt (GNM_const (1.0) / 192)
1069 #define one_tsp_to_uk_qt (one_tsp_to_l * one_l_to_uk_gal * 2)
1070 #define one_tsp_to_gal (GNM_const (1.0) / 768)
1071 #define one_tsp_to_uk_gal (one_tsp_to_l * one_l_to_uk_gal)
1072 #define one_tsp_to_l GNM_const (0.004928921593749999)
1073 #define one_tsp_to_ang3 (one_tsp_to_l * GNM_const (1E-27))
1074 #define one_tsp_to_barrel (one_tsp_to_gal / 42)
1075 #define one_tsp_to_bushel (one_tsp_to_gal / GNM_const (9.3092))
1076 #define one_tsp_to_grt (one_tsp_to_cubic_ft / 100)
1077 #define one_tsp_to_mton (one_tsp_to_cubic_ft / 40)
1078 #define one_tsp_to_cubic_m (one_tsp_to_l / 1000)
1079 #define one_tsp_to_cubic_ft (one_tsp_to_cubic_m * one_m_to_ft * one_m_to_ft * one_m_to_ft)
1080 #define one_tsp_to_cubic_in (one_tsp_to_cubic_m * one_m_to_in * one_m_to_in * one_m_to_in)
1081 #define one_tsp_to_cubic_ly (one_tsp_to_cubic_m * one_m_to_ly * one_m_to_ly * one_m_to_ly)
1082 #define one_tsp_to_cubic_mi (one_tsp_to_cubic_m * one_m_to_mi * one_m_to_mi * one_m_to_mi)
1083 #define one_tsp_to_cubic_yd (one_tsp_to_cubic_m * one_m_to_yd * one_m_to_yd * one_m_to_yd)
1084 #define one_tsp_to_cubic_Nmi (one_tsp_to_cubic_m * one_m_to_Nmi * one_m_to_Nmi * one_m_to_Nmi)
1085 #define one_tsp_to_cubic_Pica (one_tsp_to_cubic_m * one_m_to_Pica * one_m_to_Pica * one_m_to_Pica)
1087 /* Bits and Bytes */
1088 #define one_byte_to_bit 8
1090 /* Area constants */
1091 #define one_m2_to_uk_acre (1/GNM_const (4046.8564224))
1092 #define one_m2_to_us_acre (1/(4046 + GNM_const (13525426.)/15499969))
1093 #define one_m2_to_ang2 (one_m_to_ang * one_m_to_ang)
1094 #define one_m2_to_ar GNM_const (0.01)
1095 #define one_m2_to_ha (one_m2_to_ar / hecto)
1096 #define one_m2_to_ft2 (one_m_to_ft * one_m_to_ft)
1097 #define one_m2_to_in2 (one_m_to_in * one_m_to_in)
1098 #define one_m2_to_ly2 (one_m_to_ly * one_m_to_ly)
1099 #define one_m2_to_mi2 (one_m_to_mi * one_m_to_mi)
1100 #define one_m2_to_Nmi2 (one_m_to_Nmi * one_m_to_Nmi)
1101 #define one_m2_to_yd2 (one_m_to_yd * one_m_to_yd)
1102 #define one_m2_to_Pica2 (one_m_to_Pica * one_m_to_Pica)
1103 #define one_m2_to_Morgen (one_m2_to_ha * 4)
1105 /* Speed constants */
1106 #define one_mh_to_kn one_m_to_Nmi
1107 #define one_mh_to_admkn (1/GNM_const (1853.184))
1108 #define one_mh_to_msec (GNM_const (1.0)/(60*60))
1109 #define one_mh_to_mph one_m_to_mi
1112 /* Prefixes */
1113 #define yotta GNM_const (1e+24)
1114 #define zetta GNM_const (1e+21)
1115 #define exa GNM_const (1e+18)
1116 #define peta GNM_const (1e+15)
1117 #define tera GNM_const (1e+12)
1118 #define giga GNM_const (1e+09)
1119 #define mega GNM_const (1e+06)
1120 #define kilo GNM_const (1e+03)
1121 #define hecto GNM_const (1e+02)
1122 #define deka GNM_const (1e+01)
1123 #define deci GNM_const (1e-01)
1124 #define centi GNM_const (1e-02)
1125 #define milli GNM_const (1e-03)
1126 #define micro GNM_const (1e-06)
1127 #define nano GNM_const (1e-09)
1128 #define pico GNM_const (1e-12)
1129 #define femto GNM_const (1e-15)
1130 #define atto GNM_const (1e-18)
1131 #define zepto GNM_const (1e-21)
1132 #define yocto GNM_const (1e-24)
1134 /* Binary Prefixes */
1135 #define yobi (zebi * kibi)
1136 #define zebi (exbi * kibi)
1137 #define exbi (pebi * kibi)
1138 #define pebi (tebi * kibi)
1139 #define tebi (gibi * kibi)
1140 #define gibi (mebi * kibi)
1141 #define mebi (kibi * kibi)
1142 #define kibi GNM_const (1024.0)
1144 static const eng_convert_unit_t weight_units[] = {
1145 { "g", 1.0 },
1146 { "brton",one_g_to_uk_ton },
1147 { "cwt", one_g_to_cwt },
1148 { "grain",one_g_to_grain },
1149 { "hweight",one_g_to_uk_cwt },
1150 { "LTON",one_g_to_uk_ton },
1151 { "sg", one_g_to_sg },
1152 { "shweight",one_g_to_cwt },
1153 { "lbm", one_g_to_lbm },
1154 { "lcwt", one_g_to_uk_cwt },
1155 { "u", one_g_to_u },
1156 { "uk_cwt",one_g_to_uk_cwt },
1157 { "uk_ton",one_g_to_uk_ton },
1158 { "ozm", one_g_to_ozm },
1159 { "stone",one_g_to_stone },
1160 { "ton", one_g_to_ton },
1161 { NULL, 0.0 }
1164 static const eng_convert_unit_t distance_units[] = {
1165 { "m", 1.0 },
1166 { "mi", one_m_to_mi },
1167 { "survey_mi", one_m_to_survey_mi},
1168 { "Nmi", one_m_to_Nmi },
1169 { "in", one_m_to_in },
1170 { "ft", one_m_to_ft },
1171 { "yd", one_m_to_yd },
1172 { "ell", one_m_to_ell },
1173 { "ang", one_m_to_ang },
1174 { "pc", one_m_to_pc },
1175 { "parsec", one_m_to_pc },
1176 { "ly", one_m_to_ly },
1177 { "Pica", one_m_to_Pica },
1178 { "Picapt", one_m_to_Pica },
1179 { "picapt", one_m_to_Pica },
1180 { "pica", one_m_to_pica },
1181 { NULL, 0.0 }
1184 static const eng_convert_unit_t time_units[] = {
1185 { "yr", 1.0 },
1186 { "day", one_yr_to_day },
1187 { "hr", one_yr_to_hr },
1188 { "mn", one_yr_to_mn },
1189 { "sec", one_yr_to_sec },
1190 { NULL, 0.0 }
1193 static const eng_convert_unit_t pressure_units[] = {
1194 { "Pa", 1.0 },
1195 { "psi", one_Pa_to_psi },
1196 { "atm", one_Pa_to_atm },
1197 { "mmHg", one_Pa_to_mmHg },
1198 { "Torr", one_Pa_to_Torr },
1199 { NULL, 0.0 }
1202 static const eng_convert_unit_t force_units[] = {
1203 { "N", 1.0 },
1204 { "dyn", one_N_to_dyn },
1205 { "pond", one_N_to_pond },
1206 { "lbf", one_N_to_lbf },
1207 { NULL, 0.0 }
1210 static const eng_convert_unit_t energy_units[] = {
1211 { "J", 1.0 },
1212 { "e", one_J_to_e },
1213 { "c", one_J_to_c },
1214 { "cal", one_J_to_cal },
1215 { "eV", one_J_to_eV },
1216 { "HPh", one_J_to_HPh },
1217 { "Wh", one_J_to_Wh },
1218 { "flb", one_J_to_flb },
1219 { "BTU", one_J_to_BTU },
1220 { NULL, 0.0 }
1223 static const eng_convert_unit_t power_units[] = {
1224 { "HP", 1.0 },
1225 { "PS", one_HP_to_W/one_PS_to_W },
1226 { "W", one_HP_to_W },
1227 { NULL, 0.0 }
1230 static const eng_convert_unit_t magnetism_units[] = {
1231 { "T", 1.0 },
1232 { "ga", one_T_to_ga },
1233 { NULL, 0.0 }
1236 static const eng_convert_unit_t liquid_units[] = {
1237 { "tsp", 1.0 },
1238 { "tspm", one_tsp_to_tspm },
1239 { "tbs", one_tsp_to_tbs },
1240 { "oz", one_tsp_to_oz },
1241 { "cup", one_tsp_to_cup },
1242 { "pt", one_tsp_to_pt },
1243 { "qt", one_tsp_to_qt },
1244 { "uk_qt", one_tsp_to_uk_qt },
1245 { "gal", one_tsp_to_gal },
1246 { "uk_gal", one_tsp_to_uk_gal },
1247 { "us_pt",one_tsp_to_pt },
1248 { "uk_pt",one_tsp_to_uk_pt },
1249 { "l", one_tsp_to_l },
1250 { "L", one_tsp_to_l },
1251 { "lt", one_tsp_to_l },
1252 { "ang3", one_tsp_to_ang3 },
1253 { "ang^3", one_tsp_to_ang3 },
1254 { "bushel", one_tsp_to_bushel },
1255 { "barrel", one_tsp_to_barrel },
1256 { "GRT", one_tsp_to_grt },
1257 { "regton", one_tsp_to_grt },
1258 { "MTON", one_tsp_to_mton },
1259 { "ft3", one_tsp_to_cubic_ft},
1260 { "ft^3", one_tsp_to_cubic_ft},
1261 { "in3", one_tsp_to_cubic_in},
1262 { "in^3", one_tsp_to_cubic_in},
1263 { "ly3", one_tsp_to_cubic_ly},
1264 { "ly^3", one_tsp_to_cubic_ly},
1265 { "m3", one_tsp_to_cubic_m},
1266 { "m^3", one_tsp_to_cubic_m},
1267 { "mi3", one_tsp_to_cubic_mi},
1268 { "mi^3", one_tsp_to_cubic_mi},
1269 { "yd3", one_tsp_to_cubic_yd},
1270 { "yd^3", one_tsp_to_cubic_yd},
1271 { "Nmi3", one_tsp_to_cubic_Nmi},
1272 { "Nmi^3", one_tsp_to_cubic_Nmi},
1273 { "Pica3", one_tsp_to_cubic_Pica},
1274 { "Pica^3", one_tsp_to_cubic_Pica},
1275 { "Picapt3", one_tsp_to_cubic_Pica},
1276 { "Picapt^3", one_tsp_to_cubic_Pica},
1277 { NULL, 0.0 }
1280 static const eng_convert_unit_t information_units[] = {
1281 { "byte", 1.0 },
1282 { "bit", one_byte_to_bit},
1283 { NULL, 0.0 }
1286 static const eng_convert_unit_t speed_units[] = {
1287 { "m/h", 1.0 },
1288 { "m/hr", 1.0 },
1289 { "admkn", one_mh_to_admkn },
1290 { "kn", one_mh_to_kn },
1291 { "m/s", one_mh_to_msec },
1292 { "m/sec", one_mh_to_msec },
1293 { "mph", one_mh_to_mph },
1294 { NULL, 0.0 }
1297 static const eng_convert_unit_t area_units[] = {
1298 { "m2", 1.0 },
1299 { "m^2", 1.0 },
1300 { "uk_acre", one_m2_to_uk_acre },
1301 { "us_acre", one_m2_to_us_acre },
1302 { "ang2", one_m2_to_ang2 },
1303 { "ang^2", one_m2_to_ang2 },
1304 { "ar", one_m2_to_ar },
1305 { "ha", one_m2_to_ha },
1306 { "in2", one_m2_to_in2 },
1307 { "in^2", one_m2_to_in2 },
1308 { "ft2", one_m2_to_ft2 },
1309 { "ft^2", one_m2_to_ft2 },
1310 { "ly2", one_m2_to_ly2 },
1311 { "ly^2", one_m2_to_ly2 },
1312 { "mi2", one_m2_to_mi2 },
1313 { "mi^2", one_m2_to_mi2 },
1314 { "Nmi2", one_m2_to_Nmi2 },
1315 { "Nmi^2", one_m2_to_Nmi2 },
1316 { "yd2", one_m2_to_yd2 },
1317 { "yd^2", one_m2_to_yd2 },
1318 { "Picapt2", one_m2_to_Pica2 },
1319 { "Picapt^2", one_m2_to_Pica2 },
1320 { "Pica2", one_m2_to_Pica2 },
1321 { "Pica^2", one_m2_to_Pica2 },
1322 { "Morgen", one_m2_to_Morgen },
1323 { NULL, 0.0 }
1326 static const eng_convert_unit_t prefixes[] = {
1327 { "Y", yotta },
1328 { "Z", zetta },
1329 { "E", exa },
1330 { "P", peta },
1331 { "T", tera },
1332 { "G", giga },
1333 { "M", mega },
1334 { "k", kilo },
1335 { "h", hecto },
1336 { "e", deka },
1337 { "d", deci },
1338 { "c", centi },
1339 { "m", milli },
1340 { "u", micro },
1341 { "n", nano },
1342 { "p", pico },
1343 { "f", femto },
1344 { "a", atto },
1345 { "z", zepto },
1346 { "y", yocto },
1347 { NULL,0.0 }
1349 static const eng_convert_unit_t binary_prefixes[] = {
1350 { "Yi", yobi },
1351 { "Zi", zebi },
1352 { "Ei", exbi },
1353 { "Pi", pebi },
1354 { "Ti", tebi },
1355 { "Gi", gibi },
1356 { "Mi", mebi },
1357 { "ki", kibi },
1358 { NULL,0.0 }
1361 gnm_float n;
1362 char const *from_unit, *to_unit;
1363 GnmValue *v;
1365 n = value_get_as_float (argv[0]);
1366 from_unit = value_peek_string (argv[1]);
1367 to_unit = value_peek_string (argv[2]);
1369 if (convert_temp (from_unit, to_unit, n, &v, ei->pos))
1370 return v;
1372 if (convert (weight_units, prefixes, from_unit, to_unit, n, &v,
1373 ei->pos))
1374 return v;
1375 if (convert (distance_units, prefixes, from_unit, to_unit, n, &v,
1376 ei->pos))
1377 return v;
1378 if (convert (time_units, NULL, from_unit, to_unit, n, &v,
1379 ei->pos))
1380 return v;
1381 if (convert (pressure_units, prefixes, from_unit, to_unit, n, &v,
1382 ei->pos))
1383 return v;
1384 if (convert (force_units, prefixes, from_unit, to_unit, n, &v,
1385 ei->pos))
1386 return v;
1387 if (convert (energy_units, prefixes, from_unit, to_unit, n, &v,
1388 ei->pos))
1389 return v;
1390 if (convert (power_units, prefixes, from_unit, to_unit, n, &v,
1391 ei->pos))
1392 return v;
1393 if (convert (magnetism_units, prefixes, from_unit, to_unit, n, &v,
1394 ei->pos))
1395 return v;
1396 if (convert (liquid_units, prefixes, from_unit, to_unit, n, &v,
1397 ei->pos))
1398 return v;
1399 if (convert (information_units, prefixes, from_unit, to_unit, n, &v,
1400 ei->pos))
1401 return v;
1402 if (convert (information_units, binary_prefixes, from_unit, to_unit, n, &v,
1403 ei->pos))
1404 return v;
1405 if (convert (speed_units, prefixes, from_unit, to_unit, n, &v,
1406 ei->pos))
1407 return v;
1408 if (convert (area_units, prefixes, from_unit, to_unit, n, &v,
1409 ei->pos))
1410 return v;
1412 return value_new_error_NA (ei->pos);
1415 /***************************************************************************/
1417 static GnmFuncHelp const help_erf[] = {
1418 { GNM_FUNC_HELP_NAME, F_("ERF:Gauss error function") },
1419 { GNM_FUNC_HELP_ARG, F_("lower:lower limit of the integral, defaults to 0") },
1420 { GNM_FUNC_HELP_ARG, F_("upper:upper limit of the integral") },
1421 { GNM_FUNC_HELP_DESCRIPTION, F_("ERF returns 2/sqrt(\xcf\x80)* integral from @{lower} to @{upper} of exp(-t*t) dt") },
1422 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible if two arguments are supplied and neither is negative.") },
1423 { GNM_FUNC_HELP_EXAMPLES, "=ERF(0.4)" },
1424 { GNM_FUNC_HELP_EXAMPLES, "=ERF(6,10)" },
1425 { GNM_FUNC_HELP_EXAMPLES, "=ERF(1.6448536269515/SQRT(2))" },
1426 { GNM_FUNC_HELP_SEEALSO, "ERFC" },
1427 { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Error_function") },
1428 { GNM_FUNC_HELP_END}
1431 static GnmValue *
1432 gnumeric_erf (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1434 gnm_float lower = value_get_as_float (argv[0]);
1435 gnm_float ans;
1437 if (argv[1]) {
1438 gnm_float upper = value_get_as_float (argv[1]);
1439 ans = 2 * pnorm2 (lower * M_SQRT2gnum, upper * M_SQRT2gnum);
1440 } else
1441 ans = gnm_erf (lower);
1443 return value_new_float (ans);
1446 /***************************************************************************/
1448 static GnmFuncHelp const help_erfc[] = {
1449 { GNM_FUNC_HELP_NAME, F_("ERFC:Complementary Gauss error function") },
1450 { GNM_FUNC_HELP_ARG, F_("x:number") },
1451 { GNM_FUNC_HELP_DESCRIPTION, F_("ERFC returns 2/sqrt(\xcf\x80)* integral from @{x} to \xe2\x88\x9e of exp(-t*t) dt") },
1452 { GNM_FUNC_HELP_EXAMPLES, "=ERFC(6)" },
1453 { GNM_FUNC_HELP_SEEALSO, "ERF" },
1454 { GNM_FUNC_HELP_EXTREF, F_("wiki:en:Error_function") },
1455 { GNM_FUNC_HELP_END}
1458 static GnmValue *
1459 gnumeric_erfc (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1461 gnm_float x = value_get_as_float (argv[0]);
1463 return value_new_float (gnm_erfc (x));
1466 /***************************************************************************/
1468 static GnmFuncHelp const help_delta[] = {
1469 { GNM_FUNC_HELP_NAME, F_("DELTA:Kronecker delta function") },
1470 { GNM_FUNC_HELP_ARG, F_("x0:number") },
1471 { GNM_FUNC_HELP_ARG, F_("x1:number, defaults to 0") },
1472 { GNM_FUNC_HELP_DESCRIPTION, F_("DELTA returns 1 if @{x1} = @{x0} and 0 otherwise.") },
1473 { GNM_FUNC_HELP_NOTE, F_("If either argument is non-numeric, #VALUE! is returned.") },
1474 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
1475 { GNM_FUNC_HELP_EXAMPLES, "=DELTA(42.99,43)" },
1476 { GNM_FUNC_HELP_SEEALSO, "EXACT,GESTEP" },
1477 { GNM_FUNC_HELP_END}
1480 static GnmValue *
1481 gnumeric_delta (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1483 gnm_float x = value_get_as_float (argv[0]);
1484 gnm_float y = argv[1] ? value_get_as_float (argv[1]) : 0;
1486 return value_new_int (x == y);
1489 /***************************************************************************/
1491 static GnmFuncHelp const help_gestep[] = {
1492 { GNM_FUNC_HELP_NAME, F_("GESTEP:step function with step at @{x1} evaluated at @{x0}") },
1493 { GNM_FUNC_HELP_ARG, F_("x0:number") },
1494 { GNM_FUNC_HELP_ARG, F_("x1:number, defaults to 0") },
1495 { GNM_FUNC_HELP_DESCRIPTION, F_("GESTEP returns 1 if @{x1} \xe2\x89\xa4 @{x0} and 0 otherwise.") },
1496 { GNM_FUNC_HELP_NOTE, F_("If either argument is non-numeric, #VALUE! is returned.") },
1497 { GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
1498 { GNM_FUNC_HELP_EXAMPLES, "=GESTEP(5,4)" },
1499 { GNM_FUNC_HELP_SEEALSO, "DELTA" },
1500 { GNM_FUNC_HELP_END}
1503 static GnmValue *
1504 gnumeric_gestep (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1506 gnm_float x = value_get_as_float (argv[0]);
1507 gnm_float y = argv[1] ? value_get_as_float (argv[1]) : 0;
1509 return value_new_int (x >= y);
1512 /***************************************************************************/
1514 static GnmFuncHelp const help_hexrep[] = {
1515 { GNM_FUNC_HELP_NAME, F_("HEXREP:hexadecimal representation of numeric value") },
1516 { GNM_FUNC_HELP_ARG, F_("x:number") },
1517 { GNM_FUNC_HELP_DESCRIPTION, F_("HEXREP returns a hexadecimal string representation of @{x}.") },
1518 { GNM_FUNC_HELP_NOTE, F_("This is a function meant for debugging. The layout of the result may change and even depend on how Gnumeric was compiled.") },
1519 { GNM_FUNC_HELP_END}
1522 static GnmValue *
1523 gnumeric_hexrep (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1525 gnm_float x = value_get_as_float (argv[0]);
1526 unsigned char data[sizeof(gnm_float)];
1527 unsigned ui;
1528 char res[2 * sizeof(gnm_float) + 1];
1529 static const char hex[16] = "0123456789abcdef";
1531 /* We don't have a long double version yet. */
1532 GSF_LE_SET_DOUBLE (data, x);
1533 for (ui = 0; ui < G_N_ELEMENTS (data); ui++) {
1534 unsigned char b = data[ui];
1535 res[2 * ui] = hex[b >> 4];
1536 res[2 * ui + 1] = hex[b & 0xf];
1538 res[2 * ui] = 0;
1540 return value_new_string (res);
1543 /***************************************************************************/
1545 static GnmFuncHelp const help_invsuminv[] = {
1546 { GNM_FUNC_HELP_NAME, F_("INVSUMINV:the reciprocal of the sum of reciprocals of the arguments") },
1547 { GNM_FUNC_HELP_ARG, F_("x0:non-negative number") },
1548 { GNM_FUNC_HELP_ARG, F_("x1:non-negative number") },
1549 { GNM_FUNC_HELP_NOTE, F_("If any of the arguments is negative, #VALUE! is returned.\n"
1550 "If any argument is zero, the result is zero.") },
1551 { GNM_FUNC_HELP_DESCRIPTION, F_("INVSUMINV sum calculates the reciprocal (the inverse) "
1552 "of the sum of reciprocals (inverses) of all its arguments.") },
1553 { GNM_FUNC_HELP_EXAMPLES, "=INVSUMINV(2000,2000)" },
1554 { GNM_FUNC_HELP_SEEALSO, "HARMEAN" },
1555 { GNM_FUNC_HELP_END}
1559 static int
1560 range_invsuminv (gnm_float const *xs, int n, gnm_float *res)
1562 int i;
1563 gnm_float suminv = 0;
1564 gboolean zerop = FALSE;
1566 if (n <= 0) return 1;
1568 for (i = 0; i < n; i++) {
1569 gnm_float x = xs[i];
1570 if (x < 0) return 1;
1571 if (x == 0)
1572 zerop = TRUE;
1573 else
1574 suminv += 1 / x;
1577 *res = zerop ? 0 : 1 / suminv;
1578 return 0;
1581 static GnmValue *
1582 gnumeric_invsuminv (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
1584 return float_range_function (argc, argv, ei,
1585 range_invsuminv,
1586 COLLECT_IGNORE_STRINGS |
1587 COLLECT_IGNORE_BOOLS |
1588 COLLECT_IGNORE_BLANKS,
1589 GNM_ERROR_VALUE);
1592 /***************************************************************************/
1594 GnmFuncDescriptor const engineering_functions[] = {
1595 { "base", "Sf|f", help_base,
1596 gnumeric_base, NULL,
1597 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1599 { "besseli", "ff", help_besseli,
1600 gnumeric_besseli, NULL,
1601 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1602 { "besselj", "ff", help_besselj,
1603 gnumeric_besselj, NULL,
1604 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1605 { "besselk", "ff", help_besselk,
1606 gnumeric_besselk, NULL,
1607 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1608 { "bessely", "ff", help_bessely,
1609 gnumeric_bessely, NULL,
1610 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1612 { "bin2dec", "S", help_bin2dec,
1613 gnumeric_bin2dec, NULL,
1614 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1615 { "bin2hex", "S|f", help_bin2hex,
1616 gnumeric_bin2hex, NULL,
1617 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1618 { "bin2oct", "S|f", help_bin2oct,
1619 gnumeric_bin2oct, NULL,
1620 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1622 { "convert", "fss", help_convert,
1623 gnumeric_convert, NULL,
1624 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1625 { "dec2bin", "S|f", help_dec2bin,
1626 gnumeric_dec2bin, NULL,
1627 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1628 { "dec2oct", "S|f", help_dec2oct,
1629 gnumeric_dec2oct, NULL,
1630 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1631 { "dec2hex", "S|f", help_dec2hex,
1632 gnumeric_dec2hex, NULL,
1633 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1634 { "decimal", "Sf", help_decimal,
1635 gnumeric_decimal, NULL,
1636 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1638 { "delta", "f|f", help_delta,
1639 gnumeric_delta, NULL,
1640 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1641 { "erf", "f|f", help_erf,
1642 gnumeric_erf , NULL,
1643 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1644 { "erfc", "f", help_erfc,
1645 gnumeric_erfc, NULL,
1646 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1648 { "gestep", "f|f", help_gestep,
1649 gnumeric_gestep, NULL,
1650 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1652 { "hex2bin", "S|f", help_hex2bin,
1653 gnumeric_hex2bin, NULL,
1654 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1655 { "hex2dec", "S", help_hex2dec,
1656 gnumeric_hex2dec, NULL,
1657 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1658 { "hex2oct", "S|f", help_hex2oct,
1659 gnumeric_hex2oct, NULL,
1660 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1662 { "hexrep", "f", help_hexrep,
1663 gnumeric_hexrep, NULL,
1664 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1666 { "invsuminv", NULL, help_invsuminv,
1667 NULL, gnumeric_invsuminv,
1668 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1670 { "oct2bin", "S|f", help_oct2bin,
1671 gnumeric_oct2bin, NULL,
1672 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1673 { "oct2dec", "S", help_oct2dec,
1674 gnumeric_oct2dec, NULL,
1675 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1676 { "oct2hex", "S|f", help_oct2hex,
1677 gnumeric_oct2hex, NULL,
1678 GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1680 {NULL}