functions.c 64.5 KB
Newer Older
Arturo Espinosa's avatar
Arturo Espinosa committed
1
/*
2
 * fn-math.c:  Built in mathematical functions and functions registration
Arturo Espinosa's avatar
Arturo Espinosa committed
3
 *
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
4
 * Authors:
Arturo Espinosa's avatar
Arturo Espinosa committed
5
 *  Miguel de Icaza (miguel@gnu.org)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
6
 *  Jukka-Pekka Iivonen (iivonen@iki.fi)
Arturo Espinosa's avatar
Arturo Espinosa committed
7
8
 */
#include <config.h>
Morten Welinder's avatar
Morten Welinder committed
9
#include <math.h>
Arturo Espinosa's avatar
Arturo Espinosa committed
10
11
12
#include "gnumeric.h"
#include "utils.h"
#include "func.h"
Morten Welinder's avatar
Morten Welinder committed
13
14
#include "mathfunc.h"
#include "collect.h"
Arturo Espinosa's avatar
Arturo Espinosa committed
15

Donnie Barnes's avatar
Donnie Barnes committed
16
17
18
#if 0
/* help template */
static char *help_ = {
19
20
	N_("@FUNCTION=NAME\n"
	   "@SYNTAX=(b1, b2, ...)\n"
Donnie Barnes's avatar
Donnie Barnes committed
21

22
	   "@DESCRIPTION"
Donnie Barnes's avatar
Donnie Barnes committed
23
	   ""
24
	   "\n"
Donnie Barnes's avatar
Donnie Barnes committed
25
26
27

	   ""
	   ""
28
	   "\n"
Morten Welinder's avatar
Morten Welinder committed
29

Donnie Barnes's avatar
Donnie Barnes committed
30
31
32
	   ""
	   ""
	   ""
33
34
	   ""
	   "@SEEALSO=")
Donnie Barnes's avatar
Donnie Barnes committed
35
36
37
38
};

#endif

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
39
static int
Morten Welinder's avatar
Morten Welinder committed
40
gcd (int a, int b)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
41
{
Morten Welinder's avatar
Morten Welinder committed
42
	/* Euclid's Algorithm.	Assumes non-negative numbers.  */
Morten Welinder's avatar
Morten Welinder committed
43

Morten Welinder's avatar
Morten Welinder committed
44
45
	while (b != 0) {
		int r;
Morten Welinder's avatar
Morten Welinder committed
46

Morten Welinder's avatar
Morten Welinder committed
47
48
49
50
		r = a - (a / b) * b;	/* r = remainder from
					 * dividing a by b	*/
		a = b;
		b = r;
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
51
	}
Morten Welinder's avatar
Morten Welinder committed
52
	return a;
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
53
}
Morten Welinder's avatar
Morten Welinder committed
54

55
static float_t
Morten Welinder's avatar
Morten Welinder committed
56
gpow10 (int n)
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
{
	float_t res = 1.0;
	float_t p;
	const int maxn = 300;

	if (n >= 0) {
		p = 10.0;
		n = (n > maxn) ? maxn : n;
	} else {
		p = 0.1;
		/* Note carefully that we avoid overflow.  */
		n = (n < -maxn) ? maxn : -n;
	}
	while (n > 0) {
		if (n & 1) res *= p;
		p *= p;
		n >>= 1;
	}
	return res;
}

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

typedef struct {
        GSList *list;
        int    num;
} math_sums_t;

static int
callback_function_sumxy (Sheet *sheet, int col, int row,
			 Cell *cell, void *user_data)
{
        math_sums_t *mm = user_data;
        float_t     x;
	gpointer    p;

	if (cell == NULL || cell->value == NULL)
	        return TRUE;

        switch (cell->value->type) {
	case VALUE_INTEGER:
	        x = cell->value->v.v_int;
		break;
	case VALUE_FLOAT:
	        x = cell->value->v.v_float;
		break;
	default:
	        return TRUE;
	}

	p = g_new(float_t, 1);
	*((float_t *) p) = x;
	mm->list = g_slist_append(mm->list, p);
	mm->num++;

	return TRUE;
}

typedef struct {
        GSList              *list;
        criteria_test_fun_t fun;
        Value               *test_value;
        int                 num;
119
120
121
122
        int                 total_num;
        gboolean            actual_range;
        float_t             sum;
        GSList              *current;
123
124
125
126
127
128
129
130
} math_criteria_t;

static int
callback_function_criteria (Sheet *sheet, int col, int row,
			    Cell *cell, void *user_data)
{
        math_criteria_t *mm = user_data;
	Value           *v;
131
	gpointer        n;
132

133
	mm->total_num++;
134
135
136
137
138
	if (cell == NULL || cell->value == NULL)
	        return TRUE;

        switch (cell->value->type) {
	case VALUE_INTEGER:
Michael Meeks's avatar
Michael Meeks committed
139
	        v = value_new_int (cell->value->v.v_int);
140
141
		break;
	case VALUE_FLOAT:
Michael Meeks's avatar
Michael Meeks committed
142
	        v = value_new_float (cell->value->v.v_float);
143
144
		break;
	case VALUE_STRING:
Michael Meeks's avatar
Michael Meeks committed
145
	        v = value_new_string (cell->value->v.str->str);
146
147
148
149
150
151
		break;
	default:
	        return TRUE;
	}

	if (mm->fun(v, mm->test_value)) {
152
153
154
155
156
157
	        if (mm->actual_range) {
			n = g_new (int, 1);
			*((int *) n) = mm->total_num;
		        mm->list = g_slist_append (mm->list, n);
		} else
		        mm->list = g_slist_append (mm->list, v);
158
159
160
161
162
163
164
		mm->num++;
	} else
	        value_release(v);

	return TRUE;
}

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
165
166
static char *help_gcd = {
	N_("@FUNCTION=GCD\n"
167
	   "@SYNTAX=GCD(number1,number2,...)\n"
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
168
169

	   "@DESCRIPTION="
170
	   "GCD returns the greatest common divisor of given numbers. "
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
171
172
173
174
175
176
177
	   "\n"
	   "If any of the arguments is less than zero, GCD returns #NUM! "
	   "error. "
	   "\n"
	   "@SEEALSO=LCM")
};

Morten Welinder's avatar
Morten Welinder committed
178
179
static int
range_gcd (const float_t *xs, int n, float_t *res)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
180
{
Morten Welinder's avatar
Morten Welinder committed
181
182
183
184
185
186
187
188
189
	if (n > 0) {
		int i;
		int gcd_so_far = 0;

		for (i = 0; i < n; i++) {
			if (xs[i] <= 0)
				return 1;
			else
				gcd_so_far = gcd ((int)(floor (xs[i])), gcd_so_far);
190
		}
Morten Welinder's avatar
Morten Welinder committed
191
192
193
194
195
		*res = gcd_so_far;
		return 0;
	} else
		return 1;
}
196

Morten Welinder's avatar
Morten Welinder committed
197
198
199
200
201
202
203
static Value *
gnumeric_gcd (FunctionEvalInfo *ei, GList *nodes)
{
	return float_range_function (nodes, ei,
				     range_gcd,
				     COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_BOOLS,
				     gnumeric_err_NUM, ei->error);
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
204
205
}

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
static char *help_lcm = {
	N_("@FUNCTION=LCM\n"
	   "@SYNTAX=LCM(number1,number2,...)\n"

	   "@DESCRIPTION="
	   "LCM returns the least common multiple of integers.  The least "
	   "common multiple is the smallest positive number that is a "
	   "multiple of all integer arguments given. "
	   "\n"
	   "If any of the arguments is less than one, LCM returns #NUM! "
	   "error. "
	   "\n"
	   "@SEEALSO=GCD")
};

static int
222
223
callback_function_lcm (const EvalPosition *ep, Value *value,
		       ErrorMessage *error, void *closure)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
224
225
226
227
228
229
230
231
232
233
234
235
236
{
	Value *result = closure;

	switch (value->type){
	case VALUE_INTEGER:
	        if (value->v.v_int < 1)
		        return FALSE;
	        result->v.v_int /= gcd(result->v.v_int, value->v.v_int);
		result->v.v_int *= value->v.v_int;
		break;
	default:
	        return FALSE;
	}
Morten Welinder's avatar
Morten Welinder committed
237

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
238
239
240
241
	return TRUE;
}

static Value *
242
gnumeric_lcm (FunctionEvalInfo *ei, GList *nodes)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
243
244
245
246
247
248
249
{
	Value *result;

	result = g_new (Value, 1);
	result->type = VALUE_INTEGER;
	result->v.v_int = 1;

250
251
252
253
254
	if (function_iterate_argument_values (&ei->pos, callback_function_lcm,
					      result, nodes,
					      ei->error, TRUE) == FALSE) {
		if (error_message_is_set (ei->error))
			return function_error (ei, gnumeric_err_NUM);
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
255
256
257
258
259
	}

	return result;
}

260
261
262
static char *help_abs = {
	N_("@FUNCTION=ABS\n"
	   "@SYNTAX=ABS(b1)\n"
263

264
265
266
	   "@DESCRIPTION=Implements the Absolute Value function:  the result is "
	   "to drop the negative sign (if present).  This can be done for "
	   "integers and floating point numbers."
267
	   "\n"
268
	   "Performing this function on a string or empty cell simply does nothing."
269
	   "\n"
270
	   "@SEEALSO=CEIL, FLOOR")
271
272
};

273
static Value *
274
gnumeric_abs (FunctionEvalInfo *ei, Value **args)
275
{
276
	return value_new_float (fabs (value_get_as_float (args [0])));
277
}
278
279

static char *help_acos = {
280
	N_("@FUNCTION=ACOS\n"
281
	   "@SYNTAX=ACOS(x)\n"
282

283
	   "@DESCRIPTION="
284
285
	   "The ACOS function calculates the arc cosine of x; that "
	   " is the value whose cosine is x.  If x  falls  outside  the "
286
287
	   " range -1 to 1, ACOS fails and returns the error 'acos - domain error'. "
	   " The value it returns is in radians. "
288
	   "\n"
289
290
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
291
292
	   "\n"
	   "@SEEALSO=COS, SIN, DEGREES, RADIANS")
293
294
};

295
static Value *
296
gnumeric_acos (FunctionEvalInfo *ei, Value **args)
297
298
{
	float_t t;
Donnie Barnes's avatar
Donnie Barnes committed
299

300
301
302
303
	t = value_get_as_float (args [0]);
	if ((t < -1.0) || (t > 1.0))
		return function_error (ei, _("acos - domain error"));

Michael Meeks's avatar
Michael Meeks committed
304
	return value_new_float (acos (t));
305
306
307
308
}

static char *help_acosh = {
	N_("@FUNCTION=ACOSH\n"
309
	   "@SYNTAX=ACOSH(x)\n"
310
311
312

	   "@DESCRIPTION="
	   "The ACOSH  function  calculates  the inverse hyperbolic "
313
314
	   "cosine of x; that is the value whose hyperbolic cosine is "
	   "x. If x is less than 1.0, acosh() returns the error "
315
	   " 'acosh - domain error'"
Arturo Espinosa's avatar
Arturo Espinosa committed
316
	   "\n"
317
318
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
319
	   "\n"
320
	   "@SEEALSO=ACOS, DEGREES, RADIANS ")
Donnie Barnes's avatar
Donnie Barnes committed
321
322
};

323
static Value *
324
gnumeric_acosh (FunctionEvalInfo *ei, Value **args)
325
326
327
{
	float_t t;

328
329
330
331
	t = value_get_as_float (args [0]);
	if (t < 1.0)
		return function_error (ei, _("acosh - domain error"));

Michael Meeks's avatar
Michael Meeks committed
332
	return value_new_float (acosh (t));
333
334
335
336
}

static char *help_asin = {
	N_("@FUNCTION=ASIN\n"
337
	   "@SYNTAX=ASIN(x)\n"
338
339

	   "@DESCRIPTION="
340
341
	   "The ASIN function calculates the arc sine of x; that is "
	   "the value whose sine is x. If x falls outside  the  range "
342
343
344
345
346
347
348
349
	   "-1 to 1, ASIN fails and returns the error 'asin - domain error'   "
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=SIN, COS, ASINH, DEGREES, RADIANS")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
350
static Value *
351
gnumeric_asin (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
352
353
354
{
	float_t t;

355
356
357
358
	t = value_get_as_float (args [0]);
	if ((t < -1.0) || (t > 1.0))
		return function_error (ei, _("asin - domain error"));

Michael Meeks's avatar
Michael Meeks committed
359
	return value_new_float (asin (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
360
361
}

362
363
static char *help_asinh = {
	N_("@FUNCTION=ASINH\n"
364
	   "@SYNTAX=ASINH(x)\n"
365
366

	   "@DESCRIPTION="
367
368
	   "The ASINH  function  calculates  the inverse hyperbolic "
	   " sine of x; that is the value whose hyperbolic sine is x. "
369
370
371
372
373
374
375
376
	   "\n"

	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=ASIN, SIN, COS, DEGREES, RADIANS")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
377
static Value *
378
gnumeric_asinh (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
379
{
380
	return value_new_float (asinh (value_get_as_float (args [0])));
381
}
Arturo Espinosa's avatar
Arturo Espinosa committed
382

383
384
static char *help_atan = {
	N_("@FUNCTION=ATAN\n"
385
	   "@SYNTAX=ATAN(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
386

387
	   "@DESCRIPTION="
388
389
	   "The ATAN function calculates the arc tangent of x; that "
	   " is the value whose tangent is x."
390
391
392
393
394
395
396
397
398
	   "Return value is in radians."
	   "\n"

	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"

	   "@SEEALSO=TAN, COS, SIN, DEGREES, RADIANS")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
399
400

static Value *
401
gnumeric_atan (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
402
{
403
	return value_new_float (atan (value_get_as_float (args [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
404
405
}

406
407
static char *help_atanh = {
	N_("@FUNCTION=ATANH\n"
408
	   "@SYNTAX=ATANH(x)\n"
409
410
411

	   "@DESCRIPTION="
	   "The  ATANH  function  calculates  the inverse hyperbolic "
412
413
	   "tangent of x; that is the value whose  hyperbolic  tangent "
	   "is  x.   If  the  absolute value of x is greater than 1.0, "
414
415
416
417
418
419
420
421
422
	   " ATANH returns an error of 'atanh: domain error'      "
	   "\n"

	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=ATAN, TAN, SIN, COS, DEGREES, RADIANS")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
423
static Value *
424
gnumeric_atanh (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
425
426
427
{
	float_t t;

428
429
430
431
432
	t = value_get_as_float (args [0]);
	if ((t <= -1.0) || (t >= 1.0))
		return function_error (ei, _("atanh: domain error"));

	return value_new_float (atanh (value_get_as_float (args [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
433
434
}

435
static char *help_atan2 = {
436
	N_("@FUNCTION=ATAN2\n"
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
	   "@SYNTAX=ATAN2(b1,b2)\n"

	   "@DESCRIPTION="
	   "The ATAN2 function calculates the arc tangent of the two "
	   "variables b1 and b2.  It is similar to calculating  the  arc "
	   "tangent  of b2 / b1, except that the signs of both arguments "
	   "are used to determine the quadrant of the result. "
	   "The result is in Radians."
	   "\n"

	   "Performing this function on a string or empty cell simply does nothing. "
	   "\n"
	   "@SEEALSO=ATAN, ATANH, COS, SIN, DEGREES, RADIANS")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
452
static Value *
453
gnumeric_atan2 (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
454
{
Morten Welinder's avatar
Morten Welinder committed
455
456
	return value_new_float (atan2 (value_get_as_float (args [1]),
				       value_get_as_float (args [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
457
458
}

459
460
static char *help_ceil = {
	N_("@FUNCTION=CEIL\n"
461
	   "@SYNTAX=CEIL(x)\n"
462

463
464
	   "@DESCRIPTION=The CEIL function rounds x up to the next nearest "
	   "integer.\n"
465
466
467

	   "Performing this function on a string or empty cell simply does nothing."
	   "\n"
Morten Welinder's avatar
Morten Welinder committed
468

469
470
471
	   "@SEEALSO=ABS, FLOOR, INT")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
472
static Value *
473
gnumeric_ceil (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
474
{
475
	return value_new_float (ceil (value_get_as_float (args [0])));
476
477
}

478
479
480
481
482
483
484
485
486
static char *help_countif = {
	N_("@FUNCTION=COUNTIF\n"
	   "@SYNTAX=COUNTIF(range,criteria)\n"

	   "@DESCRIPTION="
	   "COUNTIF function counts the number of cells in the given range "
	   "that meet the given criteria. "

	   "\n"
Morten Welinder's avatar
Morten Welinder committed
487

488
489
490
491
	   "@SEEALSO=COUNT,SUMIF")
};

static Value *
492
gnumeric_countif (FunctionEvalInfo *ei, Value **argv)
493
494
{
        Value           *range = argv[0];
Morten Welinder's avatar
Morten Welinder committed
495
	Value           *tmpvalue = NULL;
496
	Sheet           *sheet;
497

498
499
500
501
502
503
	math_criteria_t items;
	int             ret;
	GSList          *list;

	items.num  = 0;
	items.list = NULL;
504
	items.actual_range = FALSE;
505
506

	if ((!VALUE_IS_NUMBER(argv[1]) && argv[1]->type != VALUE_STRING)
507
508
	    || (range->type != VALUE_CELLRANGE))
	        return function_error (ei, gnumeric_err_VALUE);
509
510
511
512

	if (VALUE_IS_NUMBER(argv[1])) {
	        items.fun = (criteria_test_fun_t) criteria_test_equal;
		items.test_value = argv[1];
Morten Welinder's avatar
Morten Welinder committed
513
	} else {
514
515
	        parse_criteria(argv[1]->v.str->str,
			       &items.fun, &items.test_value);
Morten Welinder's avatar
Morten Welinder committed
516
517
		tmpvalue = items.test_value;
	}
518

519
520
	if (!(sheet = range->v.cell_range.cell_a.sheet))
		sheet = ei->pos.sheet;
521
	ret = sheet_cell_foreach_range (
522
		sheet, TRUE,
523
524
525
526
527
528
		range->v.cell_range.cell_a.col,
		range->v.cell_range.cell_a.row,
		range->v.cell_range.cell_b.col,
		range->v.cell_range.cell_b.row,
		callback_function_criteria,
		&items);
Morten Welinder's avatar
Morten Welinder committed
529
530
531
532

	if (tmpvalue)
		value_release (tmpvalue);

533
534
	if (ret == FALSE)
	        return function_error (ei, gnumeric_err_VALUE);
535
536
537
538

        list = items.list;

	while (list != NULL) {
Morten Welinder's avatar
Morten Welinder committed
539
		value_release (list->data);
540
541
542
543
		list = list->next;
	}
	g_slist_free(items.list);

Michael Meeks's avatar
Michael Meeks committed
544
	return value_new_int (items.num);
545
546
547
548
}

static char *help_sumif = {
	N_("@FUNCTION=SUMIF\n"
549
	   "@SYNTAX=SUMIF(range,criteria[,actual_range])\n"
550
551
552

	   "@DESCRIPTION="
	   "SUMIF function sums the values in the given range that meet "
553
554
555
	   "the given criteria.  If @actual_range is given, SUMIF sums "
	   "the values in the @actual_range whose corresponding components "
	   "in @range meet the given criteria. "
556
557
558
559
	   "\n"
	   "@SEEALSO=COUNTIF,SUM")
};

560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
static int
callback_function_sumif (Sheet *sheet, int col, int row,
			 Cell *cell, void *user_data)
{
        math_criteria_t *mm = user_data;
	float_t         v;
	int             num;

	mm->total_num++;
	if (cell == NULL || cell->value == NULL)
	        return TRUE;

        switch (cell->value->type) {
	case VALUE_INTEGER:
	        v = cell->value->v.v_int;
		break;
	case VALUE_FLOAT:
	        v = cell->value->v.v_float;
		break;
	case VALUE_STRING:
	        v = 0;
		break;
	default:
	        return TRUE;
	}

	if (mm->current == NULL)
	        return TRUE;

	num = *((int*) mm->current->data);

	if (mm->total_num == num) {
	        mm->sum += v;
		g_free(mm->current->data);
		mm->current=mm->current->next;
	}

	return TRUE;
}


601
static Value *
602
gnumeric_sumif (FunctionEvalInfo *ei, Value **argv)
603
604
{
        Value           *range = argv[0];
605
	Value           *actual_range = argv[2];
Morten Welinder's avatar
Morten Welinder committed
606
	Value           *tmpvalue = NULL;
607

608
609
610
611
612
613
	math_criteria_t items;
	int             ret;
	float_t         sum;
	GSList          *list;

	items.num  = 0;
614
	items.total_num = 0;
615
616
617
	items.list = NULL;

	if ((!VALUE_IS_NUMBER(argv[1]) && argv[1]->type != VALUE_STRING)
618
619
	    || (range->type != VALUE_CELLRANGE))
	        return function_error (ei, gnumeric_err_VALUE);
620
621
622
623

	if (VALUE_IS_NUMBER(argv[1])) {
	        items.fun = (criteria_test_fun_t) criteria_test_equal;
		items.test_value = argv[1];
Morten Welinder's avatar
Morten Welinder committed
624
	} else {
625
626
	        parse_criteria(argv[1]->v.str->str,
			       &items.fun, &items.test_value);
Morten Welinder's avatar
Morten Welinder committed
627
628
		tmpvalue = items.test_value;
	}
629

630
631
632
633
634
	if (actual_range != NULL)
	        items.actual_range = TRUE;
	else
	        items.actual_range = FALSE;

635
636
	ret = sheet_cell_foreach_range (
	  range->v.cell_range.cell_a.sheet, TRUE,
Morten Welinder's avatar
Morten Welinder committed
637
	  range->v.cell_range.cell_a.col,
638
639
640
641
642
	  range->v.cell_range.cell_a.row,
	  range->v.cell_range.cell_b.col,
	  range->v.cell_range.cell_b.row,
	  callback_function_criteria,
	  &items);
Morten Welinder's avatar
Morten Welinder committed
643
644
645
646

	if (tmpvalue)
		value_release (tmpvalue);

647
648
	if (ret == FALSE)
	        return function_error (ei, gnumeric_err_VALUE);
649

650
651
652
	if (actual_range == NULL) {
	        list = items.list;
		sum = 0;
653

654
655
		while (list != NULL) {
		        Value *v = list->data;
656

657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
			if (v != NULL)
			        sum += value_get_as_float (v);
			value_release (v);
			list = list->next;
		}
	} else {
	      items.current = items.list;
	      items.sum = items.total_num = 0;
 	      ret = sheet_cell_foreach_range (
		actual_range->v.cell_range.cell_a.sheet, TRUE,
		actual_range->v.cell_range.cell_a.col,
		actual_range->v.cell_range.cell_a.row,
		actual_range->v.cell_range.cell_b.col,
		actual_range->v.cell_range.cell_b.row,
		callback_function_sumif,
		&items);
	      sum = items.sum;
674
675
	}

676
677
	g_slist_free(items.list);
		
Michael Meeks's avatar
Michael Meeks committed
678
	return value_new_float (sum);
679
680
}

681
682
683
684
685
686
687
688
689
690
691
static char *help_ceiling = {
	N_("@FUNCTION=CEILING\n"
	   "@SYNTAX=CEILING(x,significance)\n"

	   "@DESCRIPTION=The CEILING function rounds x up to the nearest "
	   "multiple of significance. "
	   "\n"

	   "If x or significance is non-numeric CEILING returns #VALUE! error. "
	   "If n and significance have different signs CEILING returns #NUM! error. "
	   "\n"
Morten Welinder's avatar
Morten Welinder committed
692

693
694
695
696
	   "@SEEALSO=CEIL")
};

static Value *
697
gnumeric_ceiling (FunctionEvalInfo *ei, Value **argv)
698
{
Morten Welinder's avatar
Morten Welinder committed
699
        float_t number, s;
700

Morten Welinder's avatar
Morten Welinder committed
701
702
703
704
705
	number = value_get_as_float (argv[0]);
	if (argv[1] == NULL)
	        s = (number >= 0) ? 1.0 : -1.0;
	else {
	        s = value_get_as_float (argv[1]);
706
	}
Morten Welinder's avatar
Morten Welinder committed
707

708
709
	if (s == 0 || number / s < 0)
		return function_error (ei, gnumeric_err_NUM);
710

Morten Welinder's avatar
Morten Welinder committed
711
	return value_new_float (ceil (number / s) * s);
712
713
}

714
715
static char *help_cos = {
	N_("@FUNCTION=COS\n"
716
	   "@SYNTAX=COS(x)\n"
717
718

	   "@DESCRIPTION="
719
	   "The  COS  function  returns  the cosine of x, where x is "
720
721
722
723
724
725
726
727
           "given in radians.  "
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=COSH, SIN, SINH, TAN, TANH, RADIANS, DEGREES")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
728
static Value *
729
gnumeric_cos (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
730
{
Michael Meeks's avatar
Michael Meeks committed
731
	return value_new_float (cos (value_get_as_float (argv [0])));
732
}
Arturo Espinosa's avatar
Arturo Espinosa committed
733

734
735
static char *help_cosh = {
	N_("@FUNCTION=COSH\n"
736
	   "@SYNTAX=COSH(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
737

738
	   "@DESCRIPTION="
739
740
741
	   "The COSH  function  returns the hyperbolic cosine of x, "
	   " which is defined mathematically as (exp(x) + exp(-x)) / 2.   "
	   " x is in radians. "
742
743
744
745
746
747
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=COS, SIN, SINH, TAN, TANH, RADIANS, DEGREES, EXP")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
748
749

static Value *
750
gnumeric_cosh (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
751
{
Michael Meeks's avatar
Michael Meeks committed
752
	return value_new_float (cosh (value_get_as_float (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
753
754
}

755
756
static char *help_degrees = {
	N_("@FUNCTION=DEGREES\n"
757
	   "@SYNTAX=DEGREES(x)\n"
758
759

	   "@DESCRIPTION="
760
761
	   "Computes the number of degrees equivalent to "
	   " x radians."
762
763
764
765
	   "\n"

	   "Performing this function on a string or empty cell simply does nothing. "
	   "\n"
Morten Welinder's avatar
Morten Welinder committed
766

767
768
769
	   "@SEEALSO=RADIANS, PI")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
770
static Value *
771
gnumeric_degrees (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
772
{
Michael Meeks's avatar
Michael Meeks committed
773
	return value_new_float ((value_get_as_float (argv [0]) * 180.0) / M_PI);
774
}
Arturo Espinosa's avatar
Arturo Espinosa committed
775

776
777
static char *help_exp = {
	N_("@FUNCTION=EXP\n"
778
	   "@SYNTAX=EXP(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
779

780
781
	   "@DESCRIPTION="
	   "Computes the value of e(the base of natural logarithmns) raised "
782
	   "to the power of x. "
783
784
785
786
787
	   "\n"
	   "Performing this function on a string or empty cell returns an error."
	   "\n"
	   "@SEEALSO=LOG, LOG2, LOG10")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
788
789

static Value *
790
gnumeric_exp (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
791
{
Michael Meeks's avatar
Michael Meeks committed
792
	return value_new_float (exp (value_get_as_float (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
793
794
}

795
float_t
796
797
798
799
800
801
802
fact (int n)
{
	if (n == 0)
		return 1;
	return (n * fact (n - 1));
}

803
804
static char *help_fact = {
	N_("@FUNCTION=FACT\n"
805
	   "@SYNTAX=FACT(x)\n"
806
807

	   "@DESCRIPTION="
808
	   "Computes the factorial of x. ie, x!"
809
810
811
812
813
814
815
	   "\n"
	   "Performing this function on a string or empty cell returns an error"
	   "\n"
	   "\n"
	   "@SEEALSO=")
};

816
static Value *
817
gnumeric_fact (FunctionEvalInfo *ei, Value **argv)
818
{
Morten Welinder's avatar
Morten Welinder committed
819
820
	float_t x;
	gboolean x_is_integer;
821

822
823
	if (!VALUE_IS_NUMBER (argv[0]))
		return function_error (ei, gnumeric_err_NUM);
824

Morten Welinder's avatar
Morten Welinder committed
825
	x = value_get_as_float (argv[0]);
826
827
828
	if (x < 0)
		return function_error (ei, gnumeric_err_NUM);

Morten Welinder's avatar
Morten Welinder committed
829
	x_is_integer = (x == floor (x));
Morten Welinder's avatar
Morten Welinder committed
830

Morten Welinder's avatar
Morten Welinder committed
831
832
833
834
835
836
837
	if (x > 12 || !x_is_integer) {
		float_t res = exp (lgamma (x + 1));
		if (x_is_integer)
			res = floor (res + 0.5);  /* Round, just in case.  */
		return value_new_float (res);
	} else
		return value_new_int (fact (x));
838
839
}

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
static char *help_combin = {
	N_("@FUNCTION=COMBIN\n"
	   "@SYNTAX=COMBIN(n,k)\n"

	   "@DESCRIPTION="
	   "Computes the number of combinations."
	   "\n"
	   "Performing this function on a non-integer or a negative number "
           "returns an error. Also if n is less than k returns an error."
	   "\n"
	   "\n"
	   "@SEEALSO=")
};

float_t
combin (int n, int k)
{
857
858
859
860
861
862
863
864
865
866
867
	if (n >= 15) {
		float_t res;

		res = exp (lgamma (n + 1) - lgamma (k + 1) - lgamma (n - k + 1));
		return floor (res + 0.5);  /* Round, just in case.  */
	} else {
		float_t res;

		res = fact (n) / fact (k) / fact (n - k);
		return res;
	}
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
868
869
870
}

static Value *
871
gnumeric_combin (FunctionEvalInfo *ei, Value **argv)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
872
{
873
	int n ,k;
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
874

875
876
877
878
	n = value_get_as_int (argv[0]);
	k = value_get_as_int (argv[1]);

	if (k >= 0 && n >= k)
Michael Meeks's avatar
Michael Meeks committed
879
		return value_new_float (combin (n ,k));
880

881
	return function_error (ei, gnumeric_err_NUM);
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
882
883
}

884
885
static char *help_floor = {
	N_("@FUNCTION=FLOOR\n"
Morten Welinder's avatar
Morten Welinder committed
886
	   "@SYNTAX=FLOOR(x,significance)\n"
887

888
	   "@DESCRIPTION=The FLOOR function rounds x down to the next nearest "
Morten Welinder's avatar
Morten Welinder committed
889
	   "multiple of @significance.  @significance defaults to 1."
890
891
892
893
894
895
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing."
	   "\n"
	   "@SEEALSO=CEIL, ABS, INT")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
896
static Value *
897
gnumeric_floor (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
898
{
Morten Welinder's avatar
Morten Welinder committed
899
900
901
902
903
904
905
906
907
        float_t number, s;

	number = value_get_as_float (argv[0]);
	if (argv[1] == NULL)
	        s = (number >= 0) ? 1.0 : -1.0;
	else {
	        s = value_get_as_float (argv[1]);
	}

908
909
	if (s == 0 || number / s < 0)
		return function_error (ei, gnumeric_err_NUM);
Morten Welinder's avatar
Morten Welinder committed
910
911

	return value_new_float (floor (number / s) * s);
912
}
Arturo Espinosa's avatar
Arturo Espinosa committed
913

914
915
916
static char *help_int = {
	N_("@FUNCTION=INT\n"
	   "@SYNTAX=INT(b1, b2, ...)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
917

918
919
920
	   "@DESCRIPTION="
	   "The INT function round b1 now to the nearest int. "
	   "Where 'nearest' implies being closer to zero. "
Morten Welinder's avatar
Morten Welinder committed
921
	   "Equivalent to FLOOR(b1) for b1 >= 0, amd CEIL(b1) "
Morten Welinder's avatar
Morten Welinder committed
922
	   "for b1 < 0. "
923
924
925
926
927
928
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing."
	   ""
	   "\n"
	   "@SEEALSO=FLOOR, CEIL, ABS")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
929
930

static Value *
931
gnumeric_int (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
932
{
933
934
	float_t t;

Morten Welinder's avatar
Morten Welinder committed
935
	/* FIXME: What about strings and empty cells?  */
936
937
	t = value_get_as_float (argv [0]);

Morten Welinder's avatar
Morten Welinder committed
938
	return value_new_float (floor (value_get_as_float (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
939
940
}

941
942
static char *help_log = {
	N_("@FUNCTION=LOG\n"
943
	   "@SYNTAX=LOG(x[,base])\n"
944
945

	   "@DESCRIPTION="
946
947
	   "Computes the logarithm of x in the given base.  If no base is "
	   "given LOG returns the logarithm in base 10. "
948
	   "\n"
949
	   "@SEEALSO=LN, LOG2, LOG10")
950
951
};

Arturo Espinosa's avatar
Arturo Espinosa committed
952
static Value *
953
gnumeric_log (FunctionEvalInfo *ei, Value **argv)
954
955
956
{
	float_t t, base;

Michael Meeks's avatar
Michael Meeks committed
957
	t = value_get_as_float (argv [0]);
958
959
960
961

	if (argv[1] == NULL)
	        base = 10;
	else
Michael Meeks's avatar
Michael Meeks committed
962
	        base = value_get_as_float (argv[1]);
963

964
965
	if (t <= 0.0)
		return function_error (ei, gnumeric_err_VALUE);
966

Michael Meeks's avatar
Michael Meeks committed
967
	return value_new_float (log (t) / log (base));
968
969
970
971
972
973
974
975
976
977
978
979
980
}

static char *help_ln = {
	N_("@FUNCTION=LN\n"
	   "@SYNTAX=LN(x)\n"

	   "@DESCRIPTION="
	   "LN returns the natural logarithm of x. "
	   "\n"
	   "@SEEALSO=EXP, LOG2, LOG10")
};

static Value *
981
gnumeric_ln (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
982
983
984
{
	float_t t;

Michael Meeks's avatar
Michael Meeks committed
985
	t = value_get_as_float (argv [0]);
986

987
988
	if (t <= 0.0)
		return function_error (ei, gnumeric_err_VALUE);
989

Michael Meeks's avatar
Michael Meeks committed
990
	return value_new_float (log (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
991
992
}

993
994
995
996
997
static char *help_power = {
	N_("@FUNCTION=POWER\n"
	   "@SYNTAX=POWER(x,y)\n"

	   "@DESCRIPTION="
Morten Welinder's avatar
Morten Welinder committed
998
	   "Returns the value of x raised to the power y."
999
	   "\n"
Morten Welinder's avatar
Morten Welinder committed
1000
	   "Performing this function on a string or empty cell returns an error."
1001
1002
1003
1004
1005
	   "\n"
	   "@SEEALSO=EXP")
};

static Value *
1006
gnumeric_power (FunctionEvalInfo *ei, Value **argv)
1007
{
Morten Welinder's avatar
Morten Welinder committed
1008
1009
1010
1011
1012
1013
1014
1015
1016
	float_t x, y;

	x = value_get_as_float (argv [0]);
	y = value_get_as_float (argv [1]);

	if ((x > 0) || (x == 0 && y > 0) || (x < 0 && y == floor (y)))
		return value_new_float (pow (x, y));

	/* FIXME: What is supposed to happen for x=y=0?  */
1017
	return function_error (ei, gnumeric_err_VALUE);
1018
1019
}

1020
static char *help_log2 = {
1021
	N_("@FUNCTION=LOG2\n"
1022
	   "@SYNTAX=LOG2(x)\n"
1023
1024

	   "@DESCRIPTION="
1025
	   "Computes the base-2 logarithm  of x. "
1026
1027
1028
1029
1030
1031
	   "\n"
	   "Performing this function on a string or empty cell returns an error. "
	   "\n"
	   "@SEEALSO=EXP, LOG10, LOG")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
1032
static Value *
1033
gnumeric_log2 (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
1034
1035
1036
{
	float_t t;

Michael Meeks's avatar
Michael Meeks committed
1037
	t = value_get_as_float (argv [0]);
1038
1039
1040
	if (t <= 0.0)
		return function_error (ei, _("log2: domain error"));

Michael Meeks's avatar
Michael Meeks committed
1041
	return value_new_float (log (t) / M_LN2);
Arturo Espinosa's avatar
Arturo Espinosa committed
1042
1043
}

1044
static char *help_log10 = {
1045
	N_("@FUNCTION=LOG10\n"
1046
	   "@SYNTAX=LOG10(x)\n"
1047
1048

	   "@DESCRIPTION="
1049
	   "Computes the base-10 logarithm  of x. "
1050
1051
1052
1053
1054
1055
1056
	   "\n"

	   "Performing this function on a string or empty cell returns an error. "
	   "\n"
	   "@SEEALSO=EXP, LOG2, LOG")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
1057
static Value *
1058
gnumeric_log10 (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
1059
1060
1061
{
	float_t t;

Michael Meeks's avatar
Michael Meeks committed
1062
	t = value_get_as_float (argv [0]);
1063
1064
1065
	if (t <= 0.0)
		return function_error (ei, _("log10: domain error"));

Michael Meeks's avatar
Michael Meeks committed
1066
	return value_new_float (log10 (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
1067
1068
}

1069
1070
1071
1072
1073
1074
static char *help_mod = {
	N_("@FUNCTION=MOD\n"
	   "@SYNTAX=MOD(number,divisor)\n"

	   "@DESCRIPTION="
	   "Implements modulo arithmetic."
Morten Welinder's avatar
Morten Welinder committed
1075
	   "Returns the remainder when @divisor is divided into @number."
1076
1077
1078
1079
1080
1081
	   "\n"
	   "Returns #DIV/0! if divisor is zero."
	   "@SEEALSO=INT,FLOOR,CEIL")
};

static Value *
1082
gnumeric_mod (FunctionEvalInfo *ei, Value **argv)
1083
1084
{
	int a,b;
1085

1086
1087
1088
	a = value_get_as_int (argv[0]);
	b = value_get_as_int (argv[1]);

1089
1090
	if (b == 0)
		return function_error (ei, gnumeric_err_NUM);
Morten Welinder's avatar
Morten Welinder committed
1091
1092

	if (b < 0) {
1093
1094
		a = -a;
		b = -b;
Morten Welinder's avatar
Morten Welinder committed
1095
		/* FIXME: check for overflow.  */
1096
	}
Morten Welinder's avatar
Morten Welinder committed
1097

Morten Welinder's avatar
Morten Welinder committed
1098
1099
1100
1101
1102
1103
	if (a >= 0)
		return value_new_int (a % b);
	else {
		int invres = (-a) % b;
		return value_new_int (invres == 0 ? 0 : b - invres);
	}
1104
1105
}

1106
1107
static char *help_radians = {
	N_("@FUNCTION=RADIANS\n"