1 /*
2  * fn-complex.c:  Built in complex number functions and functions registration
3  *
4  * Authors:
5  *   Michael Meeks <michael@ximian.com>
6  *   Jukka-Pekka Iivonen (iivonen@iki.fi)
7  *   Morten Welinder (terra@gnome.org)
8  *
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.
13  *
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.
18  *
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/>.
21  */
22 
23 #include <gnumeric-config.h>
24 #include <gnumeric.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <func.h>
28 
29 #include <complex.h>
30 #include <sf-gamma.h>
31 #include <parse-util.h>
32 #include <cell.h>
33 #include <expr.h>
34 #include <value.h>
35 #include <mathfunc.h>
36 #include <gnm-i18n.h>
37 
38 #include <goffice/goffice.h>
39 #include <gnm-plugin.h>
40 #include "gsl-complex.h"
41 
42 
43 GNM_PLUGIN_MODULE_HEADER;
44 
45 /* Converts a complex number string into its coefficients.  Returns 0 if ok,
46  * 1 if an error occurred.
47  */
48 static int
value_get_as_complex(GnmValue const * val,gnm_complex * res,char * imunit)49 value_get_as_complex (GnmValue const *val, gnm_complex *res, char *imunit)
50 {
51 	if (VALUE_IS_NUMBER (val)) {
52 		*res = GNM_CREAL (value_get_as_float (val));
53 		*imunit = 'i';
54 		return 0;
55 	} else {
56 		return gnm_complex_from_string (res,
57 						value_peek_string (val),
58 						imunit);
59 	}
60 }
61 
62 static GnmValue *
value_new_complex(gnm_complex const * c,char imunit)63 value_new_complex (gnm_complex const *c, char imunit)
64 {
65 	if (gnm_complex_invalid_p (c))
66 		return value_new_error_NUM (NULL);
67 	else if (GNM_CREALP (*c))
68 		return value_new_float (c->re);
69 	else
70 		return value_new_string_nocopy (gnm_complex_to_string (c, imunit));
71 }
72 
73 static GnmValue *
value_new_complexv(gnm_complex c,char imunit)74 value_new_complexv (gnm_complex c, char imunit)
75 {
76 	return value_new_complex (&c, imunit);
77 }
78 
79 
80 /***************************************************************************/
81 
82 static GnmFuncHelp const help_complex[] = {
83 	{ GNM_FUNC_HELP_NAME, F_("COMPLEX:a complex number of the form @{x} + @{y}@{i}") },
84 	{ GNM_FUNC_HELP_ARG, F_("x:real part") },
85 	{ GNM_FUNC_HELP_ARG, F_("y:imaginary part") },
86 	{ GNM_FUNC_HELP_ARG, F_("i:the suffix for the complex number, either \"i\" or \"j\"; defaults to \"i\"") },
87 	{ GNM_FUNC_HELP_NOTE, F_("If @{i} is neither \"i\" nor \"j\", COMPLEX returns #VALUE!") },
88 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
89 	{ GNM_FUNC_HELP_EXAMPLES, "=COMPLEX(1,-1)" },
90 	{ GNM_FUNC_HELP_END}
91 };
92 
93 static GnmValue *
gnumeric_complex(GnmFuncEvalInfo * ei,GnmValue const * const * argv)94 gnumeric_complex (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
95 {
96 	gnm_complex c = GNM_CMAKE (value_get_as_float (argv[0]),
97 				   value_get_as_float (argv[1]));
98 	char const *suffix = argv[2] ? value_peek_string (argv[2]) : "i";
99 
100 	if (strcmp (suffix, "i") != 0 && strcmp (suffix, "j") != 0)
101 		return value_new_error_VALUE (ei->pos);
102 
103 	return value_new_complex (&c, *suffix);
104 }
105 
106 /***************************************************************************/
107 
108 static GnmFuncHelp const help_imaginary[] = {
109 	{ GNM_FUNC_HELP_NAME, F_("IMAGINARY:the imaginary part of the complex number @{z}") },
110 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
111 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
112 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
113 	{ GNM_FUNC_HELP_EXAMPLES, "=IMAGINARY(\"132-j\")" },
114 	{ GNM_FUNC_HELP_SEEALSO, "IMREAL" },
115 	{ GNM_FUNC_HELP_END}
116 };
117 
118 static GnmValue *
gnumeric_imaginary(GnmFuncEvalInfo * ei,GnmValue const * const * argv)119 gnumeric_imaginary (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
120 {
121 	gnm_complex c;
122 	char imunit;
123 
124 	if (VALUE_IS_NUMBER (argv[0]))
125 	        return value_new_float (0.0);
126 
127 	if (value_get_as_complex (argv[0], &c, &imunit))
128 		return value_new_error_NUM (ei->pos);
129 
130 	return value_new_float (c.im);
131 }
132 
133 /***************************************************************************/
134 
135 static GnmFuncHelp const help_imabs[] = {
136 	{ GNM_FUNC_HELP_NAME, F_("IMABS:the absolute value of the complex number @{z}") },
137 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
138 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
139 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
140 	{ GNM_FUNC_HELP_EXAMPLES, "=IMABS(\"2-j\")" },
141 	{ GNM_FUNC_HELP_SEEALSO, "IMAGINARY,IMREAL" },
142 	{ GNM_FUNC_HELP_END}
143 };
144 
145 static GnmValue *
gnumeric_imabs(GnmFuncEvalInfo * ei,GnmValue const * const * argv)146 gnumeric_imabs (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
147 {
148 	gnm_complex c;
149 	char imunit;
150 
151 	if (value_get_as_complex (argv[0], &c, &imunit))
152 		return value_new_error_NUM (ei->pos);
153 
154 	return value_new_float (GNM_CABS (c));
155 }
156 
157 /***************************************************************************/
158 
159 static GnmFuncHelp const help_imreal[] = {
160 	{ GNM_FUNC_HELP_NAME, F_("IMREAL:the real part of the complex number @{z}") },
161 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
162 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
163 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
164 	{ GNM_FUNC_HELP_EXAMPLES, "=IMREAL(\"132-j\")" },
165 	{ GNM_FUNC_HELP_SEEALSO, "IMAGINARY" },
166 	{ GNM_FUNC_HELP_END}
167 };
168 
169 static GnmValue *
gnumeric_imreal(GnmFuncEvalInfo * ei,GnmValue const * const * argv)170 gnumeric_imreal (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
171 {
172 	gnm_complex c;
173 	char imunit;
174 
175 	if (VALUE_IS_NUMBER (argv[0]))
176 		return value_dup (argv[0]);
177 
178 	if (value_get_as_complex (argv[0], &c, &imunit))
179 		return value_new_error_NUM (ei->pos);
180 
181 	return value_new_float (c.re);
182 }
183 
184 /***************************************************************************/
185 
186 static GnmFuncHelp const help_imconjugate[] = {
187 	{ GNM_FUNC_HELP_NAME, F_("IMCONJUGATE:the complex conjugate of the complex number @{z}") },
188 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
189 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
190 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
191 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCONJUGATE(\"1-j\")" },
192 	{ GNM_FUNC_HELP_SEEALSO, "IMAGINARY,IMREAL" },
193 	{ GNM_FUNC_HELP_END}
194 };
195 
196 static GnmValue *
gnumeric_imconjugate(GnmFuncEvalInfo * ei,GnmValue const * const * argv)197 gnumeric_imconjugate (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
198 {
199 	gnm_complex c;
200 	char imunit;
201 
202 	if (value_get_as_complex (argv[0], &c, &imunit))
203 		return value_new_error_NUM (ei->pos);
204 
205 	return value_new_complexv (GNM_CCONJ (c), imunit);
206 }
207 
208 /***************************************************************************/
209 
210 static GnmFuncHelp const help_iminv[] = {
211 	{ GNM_FUNC_HELP_NAME, F_("IMINV:the reciprocal, or inverse, of the complex number @{z}") },
212 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
213 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
214 	{ GNM_FUNC_HELP_EXAMPLES, "=IMINV(\"1-j\")" },
215 	{ GNM_FUNC_HELP_END}
216 };
217 
218 static GnmValue *
gnumeric_iminv(GnmFuncEvalInfo * ei,GnmValue const * const * argv)219 gnumeric_iminv (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
220 {
221 	gnm_complex c;
222 	char imunit;
223 
224 	if (value_get_as_complex (argv[0], &c, &imunit))
225 		return value_new_error_NUM (ei->pos);
226 
227 	return value_new_complexv (GNM_CINV (c), imunit);
228 }
229 
230 /***************************************************************************/
231 
232 static GnmFuncHelp const help_imneg[] = {
233 	{ GNM_FUNC_HELP_NAME, F_("IMNEG:the negative of the complex number @{z}") },
234 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
235 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
236 	{ GNM_FUNC_HELP_EXAMPLES, "=IMNEG(\"1-j\")" },
237 	{ GNM_FUNC_HELP_END}
238 };
239 
240 static GnmValue *
gnumeric_imneg(GnmFuncEvalInfo * ei,GnmValue const * const * argv)241 gnumeric_imneg (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
242 {
243 	gnm_complex c;
244 	char imunit;
245 
246 	if (value_get_as_complex (argv[0], &c, &imunit))
247 		return value_new_error_NUM (ei->pos);
248 
249 	return value_new_complexv (GNM_CNEG (c), imunit);
250 }
251 
252 /***************************************************************************/
253 
254 static GnmFuncHelp const help_imcos[] = {
255 	{ GNM_FUNC_HELP_NAME, F_("IMCOS:the cosine of the complex number @{z}") },
256 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
257 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
258 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
259 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCOS(\"1+j\")" },
260 	{ GNM_FUNC_HELP_SEEALSO, "IMSIN,IMTAN" },
261 	{ GNM_FUNC_HELP_END}
262 };
263 
264 
265 static GnmValue *
gnumeric_imcos(GnmFuncEvalInfo * ei,GnmValue const * const * argv)266 gnumeric_imcos (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
267 {
268 	gnm_complex c;
269 	char imunit;
270 
271 	if (value_get_as_complex (argv[0], &c, &imunit))
272 		return value_new_error_NUM (ei->pos);
273 
274 	return value_new_complexv (GNM_CCOS (c), imunit);
275 }
276 
277 /***************************************************************************/
278 
279 static GnmFuncHelp const help_imtan[] = {
280 	{ GNM_FUNC_HELP_NAME, F_("IMTAN:the tangent of the complex number @{z}") },
281 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
282 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
283 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
284 	{ GNM_FUNC_HELP_EXAMPLES, "=IMTAN(\"2-j\")" },
285 	{ GNM_FUNC_HELP_SEEALSO, "IMSIN,IMCOS" },
286 	{ GNM_FUNC_HELP_END}
287 };
288 
289 
290 static GnmValue *
gnumeric_imtan(GnmFuncEvalInfo * ei,GnmValue const * const * argv)291 gnumeric_imtan (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
292 {
293 	gnm_complex c;
294 	char imunit;
295 
296 	if (value_get_as_complex (argv[0], &c, &imunit))
297 		return value_new_error_NUM (ei->pos);
298 
299 	return value_new_complexv (GNM_CTAN (c), imunit);
300 }
301 
302 /***************************************************************************/
303 
304 static GnmFuncHelp const help_imsec[] = {
305 	{ GNM_FUNC_HELP_NAME, F_("IMSEC:the secant of the complex number @{z}") },
306 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
307 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMSEC(@{z}) = 1/IMCOS(@{z}).") },
308 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
309 	{ GNM_FUNC_HELP_EXAMPLES, "=IMSEC(\"2-j\")" },
310 	{ GNM_FUNC_HELP_SEEALSO, "IMCSC,IMCOT" },
311 	{ GNM_FUNC_HELP_END}
312 };
313 
314 
315 static GnmValue *
gnumeric_imsec(GnmFuncEvalInfo * ei,GnmValue const * const * argv)316 gnumeric_imsec (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
317 {
318 	gnm_complex c;
319 	char imunit;
320 
321 	if (value_get_as_complex (argv[0], &c, &imunit))
322 		return value_new_error_NUM (ei->pos);
323 
324 	return value_new_complexv (GNM_CINV (GNM_CCOS (c)), imunit);
325 }
326 
327 /***************************************************************************/
328 
329 static GnmFuncHelp const help_imcsc[] = {
330 	{ GNM_FUNC_HELP_NAME, F_("IMCSC:the cosecant of the complex number @{z}") },
331 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
332 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMCSC(@{z}) = 1/IMSIN(@{z}).") },
333 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
334 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCSC(\"2-j\")" },
335 	{ GNM_FUNC_HELP_SEEALSO, "IMSEC,IMCOT" },
336 	{ GNM_FUNC_HELP_END}
337 };
338 
339 static GnmValue *
gnumeric_imcsc(GnmFuncEvalInfo * ei,GnmValue const * const * argv)340 gnumeric_imcsc (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
341 {
342 	gnm_complex c;
343 	char imunit;
344 
345 	if (value_get_as_complex (argv[0], &c, &imunit))
346 		return value_new_error_NUM (ei->pos);
347 
348 	return value_new_complexv (GNM_CINV (GNM_CSIN (c)), imunit);
349 }
350 
351 /***************************************************************************/
352 
353 static GnmFuncHelp const help_imcot[] = {
354 	{ GNM_FUNC_HELP_NAME, F_("IMCOT:the cotangent of the complex number @{z}") },
355 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
356 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMCOT(@{z}) = IMCOS(@{z})/IMSIN(@{z}).") },
357 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
358 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCOT(\"2-i\")" },
359 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCOT(\"2+j\")" },
360 	{ GNM_FUNC_HELP_SEEALSO, "IMSEC,IMCSC" },
361 	{ GNM_FUNC_HELP_END}
362 };
363 
364 static GnmValue *
gnumeric_imcot(GnmFuncEvalInfo * ei,GnmValue const * const * argv)365 gnumeric_imcot (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
366 {
367 	gnm_complex c;
368 	char imunit;
369 
370 	if (value_get_as_complex (argv[0], &c, &imunit))
371 		return value_new_error_NUM (ei->pos);
372 
373 	return value_new_complexv (GNM_CINV (GNM_CTAN (c)), imunit);
374 }
375 
376 /***************************************************************************/
377 
378 static GnmFuncHelp const help_imexp[] = {
379 	{ GNM_FUNC_HELP_NAME, F_("IMEXP:the exponential of the complex number @{z}") },
380 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
381 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
382 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
383 	{ GNM_FUNC_HELP_EXAMPLES, "=IMEXP(\"2-i\")" },
384 	{ GNM_FUNC_HELP_EXAMPLES, "=IMEXP(\"2+j\")" },
385 	{ GNM_FUNC_HELP_SEEALSO, "IMLN" },
386 	{ GNM_FUNC_HELP_END}
387 };
388 
389 
390 static GnmValue *
gnumeric_imexp(GnmFuncEvalInfo * ei,GnmValue const * const * argv)391 gnumeric_imexp (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
392 {
393 	gnm_complex c;
394 	char imunit;
395 
396 	if (value_get_as_complex (argv[0], &c, &imunit))
397 		return value_new_error_NUM (ei->pos);
398 
399 	return value_new_complexv (GNM_CEXP (c), imunit);
400 }
401 
402 /***************************************************************************/
403 
404 static GnmFuncHelp const help_imargument[] = {
405 	{ GNM_FUNC_HELP_NAME, F_("IMARGUMENT:the argument theta of the complex number @{z}") },
406 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
407 	{ GNM_FUNC_HELP_DESCRIPTION, F_("The argument theta of a complex number is its angle in radians from the real axis.") },
408 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
409 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is 0, 0 is returned.  This is different from Excel which returns an error.") },
410 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARGUMENT(\"2-j\")" },
411 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARGUMENT(0)" },
412 	{ GNM_FUNC_HELP_END}
413 };
414 
415 static GnmValue *
gnumeric_imargument(GnmFuncEvalInfo * ei,GnmValue const * const * argv)416 gnumeric_imargument (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
417 {
418 	gnm_complex c;
419 	char imunit;
420 
421 	if (value_get_as_complex (argv[0], &c, &imunit))
422 		return value_new_error_NUM (ei->pos);
423 
424 	return value_new_float (GNM_CARG (c));
425 }
426 
427 /***************************************************************************/
428 
429 static GnmFuncHelp const help_imln[] = {
430 	{ GNM_FUNC_HELP_NAME, F_("IMLN:the natural logarithm of the complex number @{z}") },
431 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
432 	{ GNM_FUNC_HELP_DESCRIPTION, F_("The result will have an imaginary part between -\xcf\x80 and +\xcf\x80.\n"
433 					"The natural logarithm is not uniquely defined on complex numbers. "
434 					"You may need to add or subtract an even multiple of \xcf\x80 to the imaginary part.")},
435 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
436 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
437 	{ GNM_FUNC_HELP_EXAMPLES, "=IMLN(\"3-j\")" },
438 	{ GNM_FUNC_HELP_SEEALSO, "IMEXP,IMLOG2,IMLOG10" },
439 	{ GNM_FUNC_HELP_END}
440 };
441 
442 static GnmValue *
gnumeric_imln(GnmFuncEvalInfo * ei,GnmValue const * const * argv)443 gnumeric_imln (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
444 {
445 	gnm_complex c;
446 	char imunit;
447 
448 	if (value_get_as_complex (argv[0], &c, &imunit))
449 		return value_new_error_NUM (ei->pos);
450 
451 	return value_new_complexv (GNM_CLN (c), imunit);
452 }
453 
454 /***************************************************************************/
455 
456 static GnmFuncHelp const help_imlog2[] = {
457 	{ GNM_FUNC_HELP_NAME, F_("IMLOG2:the base-2 logarithm of the complex number @{z}") },
458 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
459 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
460 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
461 	{ GNM_FUNC_HELP_EXAMPLES, "=IMLOG2(\"3-j\")" },
462 	{ GNM_FUNC_HELP_SEEALSO, "IMLN,IMLOG10" },
463 	{ GNM_FUNC_HELP_END}
464 };
465 
466 
467 static GnmValue *
gnumeric_imlog2(GnmFuncEvalInfo * ei,GnmValue const * const * argv)468 gnumeric_imlog2 (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
469 {
470 	gnm_complex c;
471 	char imunit;
472 
473 	if (value_get_as_complex (argv[0], &c, &imunit))
474 		return value_new_error_NUM (ei->pos);
475 
476 	return value_new_complexv (GNM_CSCALE (GNM_CLN (c), 1 / M_LN2gnum), imunit);
477 }
478 
479 /***************************************************************************/
480 
481 static GnmFuncHelp const help_imlog10[] = {
482 	{ GNM_FUNC_HELP_NAME, F_("IMLOG10:the base-10 logarithm of the complex number @{z}") },
483 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
484 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
485 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
486 	{ GNM_FUNC_HELP_EXAMPLES, "=IMLOG10(\"3-j\")" },
487 	{ GNM_FUNC_HELP_SEEALSO, "IMLN,IMLOG2" },
488 	{ GNM_FUNC_HELP_END}
489 };
490 
491 static GnmValue *
gnumeric_imlog10(GnmFuncEvalInfo * ei,GnmValue const * const * argv)492 gnumeric_imlog10 (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
493 {
494 	gnm_complex c;
495 	char imunit;
496 
497 	if (value_get_as_complex (argv[0], &c, &imunit))
498 		return value_new_error_NUM (ei->pos);
499 
500 	return value_new_complexv (GNM_CSCALE (GNM_CLN (c), M_LN10INVgnum), imunit);
501 }
502 
503 /***************************************************************************/
504 
505 static GnmFuncHelp const help_impower[] = {
506 	{ GNM_FUNC_HELP_NAME, F_("IMPOWER:the complex number @{z1} raised to the @{z2}th power") },
507 	{ GNM_FUNC_HELP_ARG, F_("z1:a complex number") },
508 	{ GNM_FUNC_HELP_ARG, F_("z2:a complex number") },
509 	{ GNM_FUNC_HELP_NOTE, F_("If @{z1} or @{z2} is not a valid complex number, #VALUE! is returned.") },
510 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
511 	{ GNM_FUNC_HELP_EXAMPLES, "=IMPOWER(\"4-j\",2)" },
512 	{ GNM_FUNC_HELP_SEEALSO, "IMSQRT" },
513 	{ GNM_FUNC_HELP_END}
514 };
515 
516 static GnmValue *
gnumeric_impower(GnmFuncEvalInfo * ei,GnmValue const * const * argv)517 gnumeric_impower (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
518 {
519 	gnm_complex a, b;
520 	char imunit;
521 
522 	if (value_get_as_complex (argv[0], &a, &imunit))
523 		return value_new_error_NUM (ei->pos);
524 
525 	if (value_get_as_complex (argv[1], &b, &imunit))
526 		return value_new_error_NUM (ei->pos);
527 
528 	if (GNM_CZEROP (a) && GNM_CZEROP (b))
529 		return value_new_error_DIV0 (ei->pos);
530 
531 	return value_new_complexv (GNM_CPOW (a, b), imunit);
532 }
533 
534 /***************************************************************************/
535 
536 static GnmFuncHelp const help_imdiv[] = {
537 	{ GNM_FUNC_HELP_NAME, F_("IMDIV:the quotient of two complex numbers @{z1}/@{z2}") },
538 	{ GNM_FUNC_HELP_ARG, F_("z1:a complex number") },
539 	{ GNM_FUNC_HELP_ARG, F_("z2:a complex number") },
540 	{ GNM_FUNC_HELP_NOTE, F_("If @{z1} or @{z2} is not a valid complex number, #VALUE! is returned.") },
541 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
542 	{ GNM_FUNC_HELP_EXAMPLES, "=IMDIV(\"2-j\",\"2+j\")" },
543 	{ GNM_FUNC_HELP_SEEALSO, "IMPRODUCT" },
544 	{ GNM_FUNC_HELP_END}
545 };
546 
547 
548 static GnmValue *
gnumeric_imdiv(GnmFuncEvalInfo * ei,GnmValue const * const * argv)549 gnumeric_imdiv (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
550 {
551 	gnm_complex a, b;
552 	char imunit;
553 
554 	if (value_get_as_complex (argv[0], &a, &imunit))
555 		return value_new_error_NUM (ei->pos);
556 
557 	if (value_get_as_complex (argv[1], &b, &imunit))
558 		return value_new_error_NUM (ei->pos);
559 
560 	if (GNM_CZEROP (b))
561 		return value_new_error_DIV0 (ei->pos);
562 
563 	return value_new_complexv (GNM_CDIV (a, b), imunit);
564 }
565 
566 /***************************************************************************/
567 
568 static GnmFuncHelp const help_imsin[] = {
569 	{ GNM_FUNC_HELP_NAME, F_("IMSIN:the sine of the complex number @{z}") },
570 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
571 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
572 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
573 	{ GNM_FUNC_HELP_EXAMPLES, "=IMSIN(\"1+j\")" },
574 	{ GNM_FUNC_HELP_SEEALSO, "IMCOS,IMTAN" },
575 	{ GNM_FUNC_HELP_END}
576 };
577 
578 static GnmValue *
gnumeric_imsin(GnmFuncEvalInfo * ei,GnmValue const * const * argv)579 gnumeric_imsin (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
580 {
581 	gnm_complex c;
582 	char imunit;
583 
584 	if (value_get_as_complex (argv[0], &c, &imunit))
585 		return value_new_error_NUM (ei->pos);
586 
587 	return value_new_complexv (GNM_CSIN (c), imunit);
588 }
589 
590 /***************************************************************************/
591 
592 static GnmFuncHelp const help_imsinh[] = {
593 	{ GNM_FUNC_HELP_NAME, F_("IMSINH:the hyperbolic sine of the complex number @{z}") },
594 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
595 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
596 	{ GNM_FUNC_HELP_EXAMPLES, "=IMSINH(\"1+j\")" },
597 	{ GNM_FUNC_HELP_SEEALSO, "IMCOSH,IMTANH" },
598 	{ GNM_FUNC_HELP_END}
599 };
600 
601 static GnmValue *
gnumeric_imsinh(GnmFuncEvalInfo * ei,GnmValue const * const * argv)602 gnumeric_imsinh (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
603 {
604 	gnm_complex c;
605 	char imunit;
606 
607 	if (value_get_as_complex (argv[0], &c, &imunit))
608 		return value_new_error_NUM (ei->pos);
609 
610 	return value_new_complexv (GNM_CSINH (c), imunit);
611 }
612 
613 /***************************************************************************/
614 
615 static GnmFuncHelp const help_imcosh[] = {
616 	{ GNM_FUNC_HELP_NAME, F_("IMCOSH:the hyperbolic cosine of the complex number @{z}") },
617 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
618 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
619 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCOSH(\"1+j\")" },
620 	{ GNM_FUNC_HELP_SEEALSO, "IMSINH,IMTANH" },
621 	{ GNM_FUNC_HELP_END}
622 };
623 
624 
625 static GnmValue *
gnumeric_imcosh(GnmFuncEvalInfo * ei,GnmValue const * const * argv)626 gnumeric_imcosh (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
627 {
628 	gnm_complex c;
629 	char imunit;
630 
631 	if (value_get_as_complex (argv[0], &c, &imunit))
632 		return value_new_error_NUM (ei->pos);
633 
634 	return value_new_complexv (GNM_CCOSH (c), imunit);
635 }
636 
637 /***************************************************************************/
638 
639 static GnmFuncHelp const help_imtanh[] = {
640 	{ GNM_FUNC_HELP_NAME, F_("IMTANH:the hyperbolic tangent of the complex number @{z}") },
641 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
642 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
643 	{ GNM_FUNC_HELP_EXAMPLES, "=IMTANH(\"1+j\")" },
644 	{ GNM_FUNC_HELP_SEEALSO, "IMSINH,IMCOSH" },
645 	{ GNM_FUNC_HELP_END}
646 };
647 
648 
649 static GnmValue *
gnumeric_imtanh(GnmFuncEvalInfo * ei,GnmValue const * const * argv)650 gnumeric_imtanh (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
651 {
652 	gnm_complex c;
653 	char imunit;
654 
655 	if (value_get_as_complex (argv[0], &c, &imunit))
656 		return value_new_error_NUM (ei->pos);
657 
658 	return value_new_complexv (GNM_CTANH (c), imunit);
659 }
660 
661 /***************************************************************************/
662 
663 static GnmFuncHelp const help_imsech[] = {
664 	{ GNM_FUNC_HELP_NAME, F_("IMSECH:the hyperbolic secant of the complex number @{z}") },
665 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
666 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
667 	{ GNM_FUNC_HELP_EXAMPLES, "=IMSECH(\"1+j\")" },
668 	{ GNM_FUNC_HELP_SEEALSO, "IMCSCH,IMCOTH" },
669 	{ GNM_FUNC_HELP_END}
670 };
671 
672 static GnmValue *
gnumeric_imsech(GnmFuncEvalInfo * ei,GnmValue const * const * argv)673 gnumeric_imsech (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
674 {
675 	gnm_complex c;
676 	char imunit;
677 
678 	if (value_get_as_complex (argv[0], &c, &imunit))
679 		return value_new_error_NUM (ei->pos);
680 
681 	return value_new_complexv (GNM_CSECH (c), imunit);
682 }
683 
684 /***************************************************************************/
685 
686 static GnmFuncHelp const help_imcsch[] = {
687 	{ GNM_FUNC_HELP_NAME, F_("IMCSCH:the hyperbolic cosecant of the complex number @{z}") },
688 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
689 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
690 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCSCH(\"1+j\")" },
691 	{ GNM_FUNC_HELP_SEEALSO, "IMSECH,IMCOTH" },
692 	{ GNM_FUNC_HELP_END}
693 };
694 
695 
696 static GnmValue *
gnumeric_imcsch(GnmFuncEvalInfo * ei,GnmValue const * const * argv)697 gnumeric_imcsch (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
698 {
699 	gnm_complex c;
700 	char imunit;
701 
702 	if (value_get_as_complex (argv[0], &c, &imunit))
703 		return value_new_error_NUM (ei->pos);
704 
705 	return value_new_complexv (GNM_CCSCH (c), imunit);
706 }
707 
708 /***************************************************************************/
709 
710 static GnmFuncHelp const help_imcoth[] = {
711 	{ GNM_FUNC_HELP_NAME, F_("IMCOTH:the hyperbolic cotangent of the complex number @{z}") },
712 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
713 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
714 	{ GNM_FUNC_HELP_EXAMPLES, "=IMCOTH(\"1+j\")" },
715 	{ GNM_FUNC_HELP_SEEALSO, "IMSECH,IMCSCH" },
716 	{ GNM_FUNC_HELP_END}
717 };
718 
719 static GnmValue *
gnumeric_imcoth(GnmFuncEvalInfo * ei,GnmValue const * const * argv)720 gnumeric_imcoth (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
721 {
722 	gnm_complex c;
723 	char imunit;
724 
725 	if (value_get_as_complex (argv[0], &c, &imunit))
726 		return value_new_error_NUM (ei->pos);
727 
728 	return value_new_complexv (GNM_CCOTH (c), imunit);
729 }
730 
731 /***************************************************************************/
732 
733 static GnmFuncHelp const help_imarcsin[] = {
734 	{ GNM_FUNC_HELP_NAME, F_("IMARCSIN:the complex arcsine of the complex number @{z}") },
735 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
736 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMARCSIN returns the complex arcsine of the complex number "
737 	   "@{z}. The branch cuts are on the real axis, less than -1 and greater than 1.") },
738 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
739 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCSIN(\"1+j\")" },
740 	{ GNM_FUNC_HELP_SEEALSO, "IMARCCOS,IMARCTAN" },
741 	{ GNM_FUNC_HELP_END}
742 };
743 
744 
745 static GnmValue *
gnumeric_imarcsin(GnmFuncEvalInfo * ei,GnmValue const * const * argv)746 gnumeric_imarcsin (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
747 {
748 	gnm_complex c;
749 	char imunit;
750 
751 	if (value_get_as_complex (argv[0], &c, &imunit))
752 		return value_new_error_NUM (ei->pos);
753 
754 	return value_new_complexv (GNM_CARCSIN (c), imunit);
755 }
756 
757 /***************************************************************************/
758 
759 static GnmFuncHelp const help_imarccos[] = {
760 	{ GNM_FUNC_HELP_NAME, F_("IMARCCOS:the complex arccosine of the complex number") },
761 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
762 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMARCCOS returns the complex arccosine of the complex number "
763 	   "@{z}. The branch cuts are on the real axis, less than -1 and greater than 1.") },
764 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
765 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCCOS(\"1+j\")" },
766 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSIN,IMARCTAN" },
767 	{ GNM_FUNC_HELP_END}
768 };
769 
770 
771 static GnmValue *
gnumeric_imarccos(GnmFuncEvalInfo * ei,GnmValue const * const * argv)772 gnumeric_imarccos (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
773 {
774 	gnm_complex c;
775 	char imunit;
776 
777 	if (value_get_as_complex (argv[0], &c, &imunit))
778 		return value_new_error_NUM (ei->pos);
779 
780 	return value_new_complexv (GNM_CARCCOS (c), imunit);
781 }
782 
783 /***************************************************************************/
784 
785 static GnmFuncHelp const help_imarctan[] = {
786 	{ GNM_FUNC_HELP_NAME, F_("IMARCTAN:the complex arctangent of the complex number") },
787 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
788 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMARCTAN returns the complex arctangent of the complex number "
789 	   "@{z}. The branch cuts are on the imaginary axis, below -i and above i.") },
790 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
791 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCTAN(\"1+j\")" },
792 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSIN,IMARCCOS" },
793 	{ GNM_FUNC_HELP_END}
794 };
795 
796 
797 static GnmValue *
gnumeric_imarctan(GnmFuncEvalInfo * ei,GnmValue const * const * argv)798 gnumeric_imarctan (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
799 {
800 	gnm_complex c;
801 	char imunit;
802 
803 	if (value_get_as_complex (argv[0], &c, &imunit))
804 		return value_new_error_NUM (ei->pos);
805 
806 	return value_new_complexv (GNM_CARCTAN (c), imunit);
807 }
808 
809 /***************************************************************************/
810 
811 static GnmFuncHelp const help_imarcsec[] = {
812 	{ GNM_FUNC_HELP_NAME, F_("IMARCSEC:the complex arcsecant of the complex number @{z}") },
813 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
814 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
815 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCSEC(\"1+j\")" },
816 	{ GNM_FUNC_HELP_SEEALSO, "IMARCCSC,IMARCCOT" },
817 	{ GNM_FUNC_HELP_END}
818 };
819 
820 static GnmValue *
gnumeric_imarcsec(GnmFuncEvalInfo * ei,GnmValue const * const * argv)821 gnumeric_imarcsec (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
822 {
823 	gnm_complex c;
824 	char imunit;
825 
826 	if (value_get_as_complex (argv[0], &c, &imunit))
827 		return value_new_error_NUM (ei->pos);
828 
829 	return value_new_complexv (GNM_CARCSEC (c), imunit);
830 }
831 
832 /***************************************************************************/
833 
834 static GnmFuncHelp const help_imarccsc[] = {
835 	{ GNM_FUNC_HELP_NAME, F_("IMARCCSC:the complex arccosecant of the complex number @{z}") },
836 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
837 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
838 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCCSC(\"1+j\")" },
839 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSEC,IMARCCOT" },
840 	{ GNM_FUNC_HELP_END}
841 };
842 
843 
844 static GnmValue *
gnumeric_imarccsc(GnmFuncEvalInfo * ei,GnmValue const * const * argv)845 gnumeric_imarccsc (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
846 {
847 	gnm_complex c;
848 	char imunit;
849 
850 	if (value_get_as_complex (argv[0], &c, &imunit))
851 		return value_new_error_NUM (ei->pos);
852 
853 	return value_new_complexv (GNM_CARCCSC (c), imunit);
854 }
855 
856 /***************************************************************************/
857 
858 static GnmFuncHelp const help_imarccot[] = {
859 	{ GNM_FUNC_HELP_NAME, F_("IMARCCOT:the complex arccotangent of the complex number @{z}") },
860 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
861 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
862 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCCOT(\"1+j\")" },
863 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSEC,IMARCCSC" },
864 	{ GNM_FUNC_HELP_END}
865 };
866 
867 static GnmValue *
gnumeric_imarccot(GnmFuncEvalInfo * ei,GnmValue const * const * argv)868 gnumeric_imarccot (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
869 {
870 	gnm_complex c;
871 	char imunit;
872 
873 	if (value_get_as_complex (argv[0], &c, &imunit))
874 		return value_new_error_NUM (ei->pos);
875 
876 	return value_new_complexv (GNM_CARCCOT (c), imunit);
877 }
878 
879 /***************************************************************************/
880 
881 static GnmFuncHelp const help_imarcsinh[] = {
882 	{ GNM_FUNC_HELP_NAME, F_("IMARCSINH:the complex hyperbolic arcsine of the complex number @{z}") },
883 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
884 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMARCSINH returns the complex hyperbolic arcsine of the complex number @{z}. "
885 					" The branch cuts are on the imaginary axis, below -i and above i.") },
886 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
887 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCSINH(\"1+j\")" },
888 	{ GNM_FUNC_HELP_SEEALSO, "IMARCCOSH,IMARCTANH" },
889 	{ GNM_FUNC_HELP_END}
890 };
891 
892 
893 static GnmValue *
gnumeric_imarcsinh(GnmFuncEvalInfo * ei,GnmValue const * const * argv)894 gnumeric_imarcsinh (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
895 {
896 	gnm_complex c;
897 	char imunit;
898 
899 	if (value_get_as_complex (argv[0], &c, &imunit))
900 		return value_new_error_NUM (ei->pos);
901 
902 	return value_new_complexv (GNM_CARCSINH (c), imunit);
903 }
904 
905 /***************************************************************************/
906 
907 static GnmFuncHelp const help_imarccosh[] = {
908 	{ GNM_FUNC_HELP_NAME, F_("IMARCCOSH:the complex hyperbolic arccosine of the complex number @{z}") },
909 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
910 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMARCCOSH returns the complex hyperbolic arccosine of the "
911 					"complex number @{z}. The branch cut is on the real "
912 					"axis, less than 1.") },
913 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
914 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCCOSH(\"1+j\")" },
915 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSINH,IMARCTANH" },
916 	{ GNM_FUNC_HELP_END}
917 };
918 
919 
920 static GnmValue *
gnumeric_imarccosh(GnmFuncEvalInfo * ei,GnmValue const * const * argv)921 gnumeric_imarccosh (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
922 {
923 	gnm_complex c;
924 	char imunit;
925 
926 	if (value_get_as_complex (argv[0], &c, &imunit))
927 		return value_new_error_NUM (ei->pos);
928 
929 	return value_new_complexv (GNM_CARCCOSH (c), imunit);
930 }
931 
932 /***************************************************************************/
933 
934 static GnmFuncHelp const help_imarctanh[] = {
935 	{ GNM_FUNC_HELP_NAME, F_("IMARCTANH:the complex hyperbolic arctangent of the complex number @{z}") },
936 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
937 	{ GNM_FUNC_HELP_DESCRIPTION, F_("IMARCTANH returns the complex hyperbolic arctangent of the "
938 					"complex number @{z}. The branch cuts are on the "
939 					"real axis, less than -1 and greater than 1.") },
940 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
941 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCTANH(\"1+j\")" },
942 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSINH,IMARCCOSH" },
943 	{ GNM_FUNC_HELP_END}
944 };
945 
946 
947 static GnmValue *
gnumeric_imarctanh(GnmFuncEvalInfo * ei,GnmValue const * const * argv)948 gnumeric_imarctanh (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
949 {
950 	gnm_complex c;
951 	char imunit;
952 
953 	if (value_get_as_complex (argv[0], &c, &imunit))
954 		return value_new_error_NUM (ei->pos);
955 
956 	return value_new_complexv (GNM_CARCTANH (c), imunit);
957 }
958 
959 /***************************************************************************/
960 
961 static GnmFuncHelp const help_imarcsech[] = {
962 	{ GNM_FUNC_HELP_NAME, F_("IMARCSECH:the complex hyperbolic arcsecant of the complex number @{z}") },
963 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
964 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
965 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCSECH(\"1+j\")" },
966 	{ GNM_FUNC_HELP_SEEALSO, "IMARCCSCH,IMARCCOTH" },
967 	{ GNM_FUNC_HELP_END}
968 };
969 
970 static GnmValue *
gnumeric_imarcsech(GnmFuncEvalInfo * ei,GnmValue const * const * argv)971 gnumeric_imarcsech (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
972 {
973 	gnm_complex c;
974 	char imunit;
975 
976 	if (value_get_as_complex (argv[0], &c, &imunit))
977 		return value_new_error_NUM (ei->pos);
978 
979 	return value_new_complexv (GNM_CARCSECH (c), imunit);
980 }
981 
982 /***************************************************************************/
983 
984 static GnmFuncHelp const help_imarccsch[] = {
985 	{ GNM_FUNC_HELP_NAME, F_("IMARCCSCH:the complex hyperbolic arccosecant of the complex number @{z}") },
986 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
987 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
988 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCCSCH(\"1+j\")" },
989 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSECH,IMARCCOTH" },
990 	{ GNM_FUNC_HELP_END}
991 };
992 
993 
994 static GnmValue *
gnumeric_imarccsch(GnmFuncEvalInfo * ei,GnmValue const * const * argv)995 gnumeric_imarccsch (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
996 {
997 	gnm_complex c;
998 	char imunit;
999 
1000 	if (value_get_as_complex (argv[0], &c, &imunit))
1001 		return value_new_error_NUM (ei->pos);
1002 
1003 	return value_new_complexv (GNM_CARCCSCH (c), imunit);
1004 }
1005 
1006 /***************************************************************************/
1007 
1008 static GnmFuncHelp const help_imarccoth[] = {
1009 	{ GNM_FUNC_HELP_NAME, F_("IMARCCOTH:the complex hyperbolic arccotangent of the complex number @{z}") },
1010 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
1011 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
1012 	{ GNM_FUNC_HELP_EXAMPLES, "=IMARCCOTH(\"1+j\")" },
1013 	{ GNM_FUNC_HELP_SEEALSO, "IMARCSECH,IMARCCSCH" },
1014 	{ GNM_FUNC_HELP_END}
1015 };
1016 
1017 
1018 static GnmValue *
gnumeric_imarccoth(GnmFuncEvalInfo * ei,GnmValue const * const * argv)1019 gnumeric_imarccoth (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1020 {
1021 	gnm_complex c;
1022 	char imunit;
1023 
1024 	if (value_get_as_complex (argv[0], &c, &imunit))
1025 		return value_new_error_NUM (ei->pos);
1026 
1027 	return value_new_complexv (GNM_CARCCOTH (c), imunit);
1028 }
1029 
1030 /***************************************************************************/
1031 
1032 static GnmFuncHelp const help_imsqrt[] = {
1033 	{ GNM_FUNC_HELP_NAME, F_("IMSQRT:the square root of the complex number @{z}") },
1034 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
1035 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
1036 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
1037 	{ GNM_FUNC_HELP_EXAMPLES, "=IMSQRT(\"1+j\")" },
1038 	{ GNM_FUNC_HELP_SEEALSO, "IMPOWER" },
1039 	{ GNM_FUNC_HELP_END}
1040 };
1041 
1042 
1043 static GnmValue *
gnumeric_imsqrt(GnmFuncEvalInfo * ei,GnmValue const * const * argv)1044 gnumeric_imsqrt (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1045 {
1046 	gnm_complex c;
1047 	char imunit;
1048 
1049 	if (value_get_as_complex (argv[0], &c, &imunit))
1050 		return value_new_error_NUM (ei->pos);
1051 
1052 	return value_new_complexv (GNM_CSQRT (c), imunit);
1053 }
1054 
1055 /***************************************************************************/
1056 
1057 static GnmFuncHelp const help_imfact[] = {
1058 	{ GNM_FUNC_HELP_NAME, F_("IMFACT:the factorial of the complex number @{z}") },
1059 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
1060 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
1061 	{ GNM_FUNC_HELP_EXAMPLES, "=IMFACT(\"1+j\")" },
1062 	{ GNM_FUNC_HELP_SEEALSO, "IMGAMMA" },
1063 	{ GNM_FUNC_HELP_END}
1064 };
1065 
1066 
1067 static GnmValue *
gnumeric_imfact(GnmFuncEvalInfo * ei,GnmValue const * const * argv)1068 gnumeric_imfact (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1069 {
1070 	gnm_complex c;
1071 	char imunit;
1072 
1073 	if (value_get_as_complex (argv[0], &c, &imunit))
1074 		return value_new_error_NUM (ei->pos);
1075 
1076 	return value_new_complexv (gnm_complex_fact (c, NULL), imunit);
1077 }
1078 
1079 /***************************************************************************/
1080 
1081 static GnmFuncHelp const help_imgamma[] = {
1082 	{ GNM_FUNC_HELP_NAME, F_("IMGAMMA:the gamma function of the complex number @{z}") },
1083 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number") },
1084 	{ GNM_FUNC_HELP_NOTE, F_("If @{z} is not a valid complex number, #VALUE! is returned.") },
1085 	{ GNM_FUNC_HELP_EXAMPLES, "=IMGAMMA(\"1+j\")" },
1086 	{ GNM_FUNC_HELP_SEEALSO, "IMGAMMA" },
1087 	{ GNM_FUNC_HELP_END}
1088 };
1089 
1090 
1091 static GnmValue *
gnumeric_imgamma(GnmFuncEvalInfo * ei,GnmValue const * const * argv)1092 gnumeric_imgamma (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1093 {
1094 	gnm_complex c;
1095 	char imunit;
1096 
1097 	if (value_get_as_complex (argv[0], &c, &imunit))
1098 		return value_new_error_NUM (ei->pos);
1099 
1100 	return value_new_complexv (gnm_complex_gamma (c, NULL), imunit);
1101 }
1102 
1103 /***************************************************************************/
1104 
1105 static GnmFuncHelp const help_imigamma[] = {
1106 	{ GNM_FUNC_HELP_NAME, F_("IMIGAMMA:the incomplete Gamma function")},
1107 	{ GNM_FUNC_HELP_ARG, F_("a:a complex number")},
1108 	{ GNM_FUNC_HELP_ARG, F_("z:a complex number")},
1109 	{ GNM_FUNC_HELP_ARG, F_("lower:if true (the default), the lower incomplete gamma function, otherwise the upper incomplete gamma function")},
1110 	{ GNM_FUNC_HELP_ARG, F_("regularize:if true (the default), the regularized version of the incomplete gamma function")},
1111 	{ GNM_FUNC_HELP_NOTE, F_("The regularized incomplete gamma function is the unregularized incomplete gamma function divided by GAMMA(@{a}).") },
1112 	{ GNM_FUNC_HELP_EXAMPLES, "=IMIGAMMA(2.5,-1.8,TRUE,TRUE)" },
1113 	{ GNM_FUNC_HELP_EXAMPLES, "=IMIGAMMA(2.5,-1.8,TRUE,TRUE)" },
1114 	{ GNM_FUNC_HELP_SEEALSO, "GAMMA,IMIGAMMA"},
1115 	{ GNM_FUNC_HELP_END}
1116 };
1117 
1118 
1119 static GnmValue *
gnumeric_imigamma(GnmFuncEvalInfo * ei,GnmValue const * const * argv)1120 gnumeric_imigamma (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1121 {
1122 	gnm_complex a, z;
1123 	char imunit;
1124 	gboolean lower = argv[2] ? value_get_as_checked_bool (argv[2]) : TRUE;
1125 	gboolean reg = argv[3] ? value_get_as_checked_bool (argv[3]) : TRUE;
1126 
1127 	if (value_get_as_complex (argv[0], &a, &imunit))
1128 		return value_new_error_NUM (ei->pos);
1129 	if (value_get_as_complex (argv[1], &z, &imunit))
1130 		return value_new_error_NUM (ei->pos);
1131 
1132 	return value_new_complexv (gnm_complex_igamma (a, z, lower, reg), imunit);
1133 }
1134 
1135 /***************************************************************************/
1136 
1137 static GnmFuncHelp const help_imsub[] = {
1138 	{ GNM_FUNC_HELP_NAME, F_("IMSUB:the difference of two complex numbers") },
1139 	{ GNM_FUNC_HELP_ARG, F_("z1:a complex number") },
1140 	{ GNM_FUNC_HELP_ARG, F_("z2:a complex number") },
1141 	{ GNM_FUNC_HELP_NOTE, F_("If @{z1} or @{z2} is not a valid complex number, #VALUE! is returned.") },
1142 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
1143 	{ GNM_FUNC_HELP_EXAMPLES, "=IMSUB(\"3-j\",\"2+j\")" },
1144 	{ GNM_FUNC_HELP_SEEALSO, "IMSUM" },
1145 	{ GNM_FUNC_HELP_END}
1146 };
1147 
1148 
1149 static GnmValue *
gnumeric_imsub(GnmFuncEvalInfo * ei,GnmValue const * const * argv)1150 gnumeric_imsub (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
1151 {
1152 	gnm_complex a, b;
1153 	char imunit;
1154 
1155 	if (value_get_as_complex (argv[0], &a, &imunit))
1156 		return value_new_error_NUM (ei->pos);
1157 
1158 	if (value_get_as_complex (argv[1], &b, &imunit))
1159 		return value_new_error_NUM (ei->pos);
1160 
1161 	return value_new_complexv (GNM_CSUB (a, b), imunit);
1162 }
1163 
1164 /***************************************************************************/
1165 
1166 static GnmFuncHelp const help_improduct[] = {
1167 	{ GNM_FUNC_HELP_NAME, F_("IMPRODUCT:the product of the given complex numbers") },
1168 	{ GNM_FUNC_HELP_ARG, F_("z1:a complex number") },
1169 	{ GNM_FUNC_HELP_ARG, F_("z2:a complex number") },
1170 	{ GNM_FUNC_HELP_NOTE, F_("If any of @{z1}, @{z2},... is not a valid complex number, #VALUE! is returned.") },
1171 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
1172 	{ GNM_FUNC_HELP_EXAMPLES, "=IMPRODUCT(\"2-j\",\"4-2j\")" },
1173 	{ GNM_FUNC_HELP_SEEALSO, "IMDIV" },
1174 	{ GNM_FUNC_HELP_END}
1175 };
1176 
1177 
1178 typedef enum {
1179 	Improduct, Imsum
1180 } eng_imoper_type_t;
1181 
1182 typedef struct {
1183 	gnm_complex       res;
1184 	char              imunit;
1185 	eng_imoper_type_t type;
1186 } eng_imoper_t;
1187 
1188 static GnmValue *
callback_function_imoper(GnmEvalPos const * ep,GnmValue const * value,void * closure)1189 callback_function_imoper (GnmEvalPos const *ep, GnmValue const *value, void *closure)
1190 {
1191 	eng_imoper_t *result = closure;
1192 	gnm_complex c;
1193 	char *imptr, dummy;
1194 
1195 	imptr = VALUE_IS_NUMBER (value) ? &dummy : &result->imunit;
1196 	if (value_get_as_complex (value, &c, imptr))
1197 		return value_new_error_NUM (ep);
1198 
1199 	switch (result->type) {
1200 	case Improduct:
1201 		result->res = GNM_CMUL (result->res, c);
1202 	        break;
1203 	case Imsum:
1204 		result->res = GNM_CADD (result->res, c);
1205 	        break;
1206 	default:
1207 		abort ();
1208 	}
1209 
1210 	return NULL;
1211 }
1212 
1213 static GnmValue *
gnumeric_improduct(GnmFuncEvalInfo * ei,int argc,GnmExprConstPtr const * argv)1214 gnumeric_improduct (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
1215 {
1216 	GnmValue *v;
1217 	eng_imoper_t p;
1218 
1219 	p.type = Improduct;
1220 	p.imunit = 'j';
1221 	p.res = GNM_C1;
1222 
1223 	v = function_iterate_argument_values
1224 		(ei->pos, callback_function_imoper, &p,
1225 		 argc, argv, TRUE, CELL_ITER_IGNORE_BLANK);
1226 
1227 	if (v != NULL)
1228 		return v;
1229 
1230 	return value_new_complexv (p.res, p.imunit);
1231 }
1232 
1233 /***************************************************************************/
1234 
1235 static GnmFuncHelp const help_imsum[] = {
1236 	{ GNM_FUNC_HELP_NAME, F_("IMSUM:the sum of the given complex numbers") },
1237 	{ GNM_FUNC_HELP_ARG, F_("z1:a complex number") },
1238 	{ GNM_FUNC_HELP_ARG, F_("z2:a complex number") },
1239 	{ GNM_FUNC_HELP_NOTE, F_("If any of @{z1}, @{z2},... is not a valid complex number, #VALUE! is returned.") },
1240 	{ GNM_FUNC_HELP_EXCEL, F_("This function is Excel compatible.") },
1241 	{ GNM_FUNC_HELP_EXAMPLES, "=IMSUM(\"2-4j\",\"9-j\")" },
1242 	{ GNM_FUNC_HELP_SEEALSO, "IMSUB" },
1243 	{ GNM_FUNC_HELP_END}
1244 };
1245 
1246 
1247 static GnmValue *
gnumeric_imsum(GnmFuncEvalInfo * ei,int argc,GnmExprConstPtr const * argv)1248 gnumeric_imsum (GnmFuncEvalInfo *ei, int argc, GnmExprConstPtr const *argv)
1249 {
1250 	GnmValue *v;
1251 	eng_imoper_t p;
1252 
1253 	p.type = Imsum;
1254 	p.imunit = 'j';
1255 	p.res = GNM_C0;
1256 
1257 	v = function_iterate_argument_values
1258 		(ei->pos, callback_function_imoper, &p,
1259 		 argc, argv, TRUE, CELL_ITER_IGNORE_BLANK);
1260 
1261 	if (v != NULL)
1262 		return v;
1263 
1264 	return value_new_complexv (p.res, p.imunit);
1265 }
1266 
1267 /***************************************************************************/
1268 
1269 GnmFuncDescriptor const complex_functions[] = {
1270 	{ "complex",     "ff|s",  help_complex,
1271 	  gnumeric_complex, NULL,
1272 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1273 	{ "imabs",       "S",     help_imabs,
1274 	  gnumeric_imabs, NULL,
1275 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1276 	{ "imaginary",   "S",     help_imaginary,
1277 	  gnumeric_imaginary, NULL,
1278 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1279 	{ "imargument",  "S",     help_imargument,
1280 	  gnumeric_imargument, NULL,
1281 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1282 	{ "imconjugate", "S",     help_imconjugate,
1283 	  gnumeric_imconjugate, NULL,
1284 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1285 	{ "imcos",       "S",     help_imcos,
1286 	  gnumeric_imcos, NULL,
1287 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1288 	{ "imdiv",       "SS",    help_imdiv,
1289 	  gnumeric_imdiv, NULL,
1290 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1291 	{ "imexp",       "S",     help_imexp,
1292 	  gnumeric_imexp, NULL,
1293 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1294 	{ "imln",        "S",     help_imln,
1295 	  gnumeric_imln, NULL,
1296 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1297 	{ "imlog10",     "S",     help_imlog10,
1298 	  gnumeric_imlog10, NULL,
1299 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1300 	{ "imlog2",      "S",     help_imlog2,
1301 	  gnumeric_imlog2, NULL,
1302 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1303 	{ "impower",     "SS",    help_impower,
1304 	  gnumeric_impower, NULL,
1305 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1306 	{ "imreal",      "S",     help_imreal,
1307 	  gnumeric_imreal, NULL,
1308 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1309 	{ "imsin",       "S",     help_imsin,
1310 	  gnumeric_imsin, NULL,
1311 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1312 	{ "imsqrt",      "S",     help_imsqrt,
1313 	  gnumeric_imsqrt, NULL,
1314 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1315 	{ "imsub",       "SS",    help_imsub,
1316 	  gnumeric_imsub, NULL,
1317 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1318 	{ "imsum",       NULL,    help_imsum,
1319 	  NULL, gnumeric_imsum,
1320 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1321 
1322 	{ "iminv",   "S",     help_iminv,
1323 	  gnumeric_iminv, NULL,
1324 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1325 	{ "imneg",   "S",     help_imneg,
1326 	  gnumeric_imneg, NULL,
1327 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1328 	{ "imtan",       "S",     help_imtan,
1329 	  gnumeric_imtan, NULL,
1330 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1331 	{ "improduct",   NULL,    help_improduct,
1332 	  NULL, gnumeric_improduct,
1333 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_BASIC },
1334 	{ "imsec",       "S",     help_imsec,
1335 	  gnumeric_imsec, NULL,
1336 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1337 	{ "imcsc",       "S",     help_imcsc,
1338 	  gnumeric_imcsc, NULL,
1339 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1340 	{ "imcot",       "S",     help_imcot,
1341 	  gnumeric_imcot, NULL,
1342 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1343 	{ "imsinh",       "S",    help_imsinh,
1344 	  gnumeric_imsinh, NULL,
1345 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1346 	{ "imcosh",       "S",    help_imcosh,
1347 	  gnumeric_imcosh, NULL,
1348 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1349 	{ "imtanh",       "S",    help_imtanh,
1350 	  gnumeric_imtanh, NULL,
1351 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1352 	{ "imsech",       "S",    help_imsech,
1353 	  gnumeric_imsech, NULL,
1354 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1355 	{ "imcsch",       "S",    help_imcsch,
1356 	  gnumeric_imcsch, NULL,
1357 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1358 	{ "imcoth",       "S",    help_imcoth,
1359 	  gnumeric_imcoth, NULL,
1360 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1361 	{ "imarcsin",     "S",    help_imarcsin,
1362 	  gnumeric_imarcsin, NULL,
1363 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1364 	{ "imarccos",     "S",    help_imarccos,
1365 	  gnumeric_imarccos, NULL,
1366 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1367 	{ "imarctan",     "S",    help_imarctan,
1368 	  gnumeric_imarctan, NULL,
1369 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1370 	{ "imarcsec",     "S",    help_imarcsec,
1371 	  gnumeric_imarcsec, NULL,
1372 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1373 	{ "imarccsc",     "S",    help_imarccsc,
1374 	  gnumeric_imarccsc, NULL,
1375 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1376 	{ "imarccot",     "S",    help_imarccot,
1377 	  gnumeric_imarccot, NULL,
1378 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1379 	{ "imarcsinh",    "S",    help_imarcsinh,
1380 	  gnumeric_imarcsinh, NULL,
1381 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1382 	{ "imarccosh",    "S",    help_imarccosh,
1383 	  gnumeric_imarccosh, NULL,
1384 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1385 	{ "imarctanh",    "S",    help_imarctanh,
1386 	  gnumeric_imarctanh, NULL,
1387 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1388 	{ "imarcsech",    "S",    help_imarcsech,
1389 	  gnumeric_imarcsech, NULL,
1390 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1391 	{ "imarccsch",    "S",    help_imarccsch,
1392 	  gnumeric_imarccsch, NULL,
1393 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1394 	{ "imarccoth",    "S",    help_imarccoth,
1395 	  gnumeric_imarccoth, NULL,
1396 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_COMPLETE, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1397 
1398 	{ "imfact",       "S",    help_imfact,
1399 	  gnumeric_imfact, NULL,
1400 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1401 	{ "imgamma",      "S",    help_imgamma,
1402 	  gnumeric_imgamma, NULL,
1403 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_EXHAUSTIVE },
1404 	{ "imigamma",     "SS|bb",  help_imigamma,
1405 	  gnumeric_imigamma, NULL,
1406 	  GNM_FUNC_SIMPLE, GNM_FUNC_IMPL_STATUS_UNIQUE_TO_GNUMERIC, GNM_FUNC_TEST_STATUS_NO_TESTSUITE },
1407 
1408 	{NULL}
1409 };
1410