fn-math.c 65.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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95

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;
96
97
98
99
        int                 total_num;
        gboolean            actual_range;
        float_t             sum;
        GSList              *current;
100
101
102
103
104
105
106
107
} 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;
108
	gpointer        n;
109

110
	mm->total_num++;
111
112
113
114
115
	if (cell == NULL || cell->value == NULL)
	        return TRUE;

        switch (cell->value->type) {
	case VALUE_INTEGER:
Michael Meeks's avatar
Michael Meeks committed
116
	        v = value_new_int (cell->value->v.v_int);
117
118
		break;
	case VALUE_FLOAT:
Michael Meeks's avatar
Michael Meeks committed
119
	        v = value_new_float (cell->value->v.v_float);
120
121
		break;
	case VALUE_STRING:
Michael Meeks's avatar
Michael Meeks committed
122
	        v = value_new_string (cell->value->v.str->str);
123
124
125
126
127
128
		break;
	default:
	        return TRUE;
	}

	if (mm->fun(v, mm->test_value)) {
129
130
131
132
133
134
	        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);
135
136
137
138
139
140
141
		mm->num++;
	} else
	        value_release(v);

	return TRUE;
}

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
142
143
static char *help_gcd = {
	N_("@FUNCTION=GCD\n"
144
	   "@SYNTAX=GCD(number1,number2,...)\n"
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
145
146

	   "@DESCRIPTION="
147
	   "GCD returns the greatest common divisor of given numbers. "
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
148
149
150
151
152
153
154
	   "\n"
	   "If any of the arguments is less than zero, GCD returns #NUM! "
	   "error. "
	   "\n"
	   "@SEEALSO=LCM")
};

Morten Welinder's avatar
Morten Welinder committed
155
156
static int
range_gcd (const float_t *xs, int n, float_t *res)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
157
{
Morten Welinder's avatar
Morten Welinder committed
158
159
160
161
162
163
164
165
166
	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);
167
		}
Morten Welinder's avatar
Morten Welinder committed
168
169
170
171
172
		*res = gcd_so_far;
		return 0;
	} else
		return 1;
}
173

Morten Welinder's avatar
Morten Welinder committed
174
175
176
177
178
179
180
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
181
182
}

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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
199
200
callback_function_lcm (const EvalPosition *ep, Value *value,
		       ErrorMessage *error, void *closure)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
201
202
203
204
205
206
207
208
209
210
211
212
213
{
	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
214

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
215
216
217
218
	return TRUE;
}

static Value *
219
gnumeric_lcm (FunctionEvalInfo *ei, GList *nodes)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
220
221
222
223
224
225
226
{
	Value *result;

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

227
228
229
230
231
	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
232
233
234
235
236
	}

	return result;
}

237
238
239
static char *help_abs = {
	N_("@FUNCTION=ABS\n"
	   "@SYNTAX=ABS(b1)\n"
240

241
242
243
	   "@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."
244
	   "\n"
245
	   "Performing this function on a string or empty cell simply does nothing."
246
	   "\n"
247
	   "@SEEALSO=CEIL, FLOOR")
248
249
};

250
static Value *
251
gnumeric_abs (FunctionEvalInfo *ei, Value **args)
252
{
253
	return value_new_float (fabs (value_get_as_float (args [0])));
254
}
255
256

static char *help_acos = {
257
	N_("@FUNCTION=ACOS\n"
258
	   "@SYNTAX=ACOS(x)\n"
259

260
	   "@DESCRIPTION="
261
262
	   "The ACOS function calculates the arc cosine of x; that "
	   " is the value whose cosine is x.  If x  falls  outside  the "
263
264
	   " range -1 to 1, ACOS fails and returns the error 'acos - domain error'. "
	   " The value it returns is in radians. "
265
	   "\n"
266
267
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
268
269
	   "\n"
	   "@SEEALSO=COS, SIN, DEGREES, RADIANS")
270
271
};

272
static Value *
273
gnumeric_acos (FunctionEvalInfo *ei, Value **args)
274
275
{
	float_t t;
Donnie Barnes's avatar
Donnie Barnes committed
276

277
278
279
280
	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
281
	return value_new_float (acos (t));
282
283
284
285
}

static char *help_acosh = {
	N_("@FUNCTION=ACOSH\n"
286
	   "@SYNTAX=ACOSH(x)\n"
287
288
289

	   "@DESCRIPTION="
	   "The ACOSH  function  calculates  the inverse hyperbolic "
290
291
	   "cosine of x; that is the value whose hyperbolic cosine is "
	   "x. If x is less than 1.0, acosh() returns the error "
292
	   " 'acosh - domain error'"
Arturo Espinosa's avatar
Arturo Espinosa committed
293
	   "\n"
294
295
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
296
	   "\n"
297
	   "@SEEALSO=ACOS, DEGREES, RADIANS ")
Donnie Barnes's avatar
Donnie Barnes committed
298
299
};

300
static Value *
301
gnumeric_acosh (FunctionEvalInfo *ei, Value **args)
302
303
304
{
	float_t t;

305
306
307
308
	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
309
	return value_new_float (acosh (t));
310
311
312
313
}

static char *help_asin = {
	N_("@FUNCTION=ASIN\n"
314
	   "@SYNTAX=ASIN(x)\n"
315
316

	   "@DESCRIPTION="
317
318
	   "The ASIN function calculates the arc sine of x; that is "
	   "the value whose sine is x. If x falls outside  the  range "
319
320
321
322
323
324
325
326
	   "-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
327
static Value *
328
gnumeric_asin (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
329
330
331
{
	float_t t;

332
333
334
335
	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
336
	return value_new_float (asin (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
337
338
}

339
340
static char *help_asinh = {
	N_("@FUNCTION=ASINH\n"
341
	   "@SYNTAX=ASINH(x)\n"
342
343

	   "@DESCRIPTION="
344
345
	   "The ASINH  function  calculates  the inverse hyperbolic "
	   " sine of x; that is the value whose hyperbolic sine is x. "
346
347
348
349
350
351
352
353
	   "\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
354
static Value *
355
gnumeric_asinh (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
356
{
357
	return value_new_float (asinh (value_get_as_float (args [0])));
358
}
Arturo Espinosa's avatar
Arturo Espinosa committed
359

360
361
static char *help_atan = {
	N_("@FUNCTION=ATAN\n"
362
	   "@SYNTAX=ATAN(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
363

364
	   "@DESCRIPTION="
365
366
	   "The ATAN function calculates the arc tangent of x; that "
	   " is the value whose tangent is x."
367
368
369
370
371
372
373
374
375
	   "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
376
377

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

383
384
static char *help_atanh = {
	N_("@FUNCTION=ATANH\n"
385
	   "@SYNTAX=ATANH(x)\n"
386
387
388

	   "@DESCRIPTION="
	   "The  ATANH  function  calculates  the inverse hyperbolic "
389
390
	   "tangent of x; that is the value whose  hyperbolic  tangent "
	   "is  x.   If  the  absolute value of x is greater than 1.0, "
391
392
393
394
395
396
397
398
399
	   " 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
400
static Value *
401
gnumeric_atanh (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
402
403
404
{
	float_t t;

405
406
407
408
409
	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
410
411
}

412
static char *help_atan2 = {
413
	N_("@FUNCTION=ATAN2\n"
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
	   "@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
429
static Value *
430
gnumeric_atan2 (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
431
{
Morten Welinder's avatar
Morten Welinder committed
432
433
	return value_new_float (atan2 (value_get_as_float (args [1]),
				       value_get_as_float (args [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
434
435
}

436
437
static char *help_ceil = {
	N_("@FUNCTION=CEIL\n"
438
	   "@SYNTAX=CEIL(x)\n"
439

440
441
	   "@DESCRIPTION=The CEIL function rounds x up to the next nearest "
	   "integer.\n"
442
443
444

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

446
447
448
	   "@SEEALSO=ABS, FLOOR, INT")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
449
static Value *
450
gnumeric_ceil (FunctionEvalInfo *ei, Value **args)
Arturo Espinosa's avatar
Arturo Espinosa committed
451
{
452
	return value_new_float (ceil (value_get_as_float (args [0])));
453
454
}

455
456
457
458
459
460
461
462
463
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
464

465
466
467
468
	   "@SEEALSO=COUNT,SUMIF")
};

static Value *
469
gnumeric_countif (FunctionEvalInfo *ei, Value **argv)
470
471
{
        Value           *range = argv[0];
Morten Welinder's avatar
Morten Welinder committed
472
	Value           *tmpvalue = NULL;
473
	Sheet           *sheet;
474

475
476
477
478
479
480
	math_criteria_t items;
	int             ret;
	GSList          *list;

	items.num  = 0;
	items.list = NULL;
481
	items.actual_range = FALSE;
482
483

	if ((!VALUE_IS_NUMBER(argv[1]) && argv[1]->type != VALUE_STRING)
484
485
	    || (range->type != VALUE_CELLRANGE))
	        return function_error (ei, gnumeric_err_VALUE);
486
487
488
489

	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
490
	} else {
491
492
	        parse_criteria(argv[1]->v.str->str,
			       &items.fun, &items.test_value);
Morten Welinder's avatar
Morten Welinder committed
493
494
		tmpvalue = items.test_value;
	}
495

496
	sheet = eval_sheet (range->v.cell_range.cell_a.sheet, ei->pos.sheet);
497
	ret = sheet_cell_foreach_range (
498
		sheet, TRUE,
499
500
501
502
503
504
		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
505
506
507
508

	if (tmpvalue)
		value_release (tmpvalue);

509
510
	if (ret == FALSE)
	        return function_error (ei, gnumeric_err_VALUE);
511
512
513
514

        list = items.list;

	while (list != NULL) {
Morten Welinder's avatar
Morten Welinder committed
515
		value_release (list->data);
516
517
518
519
		list = list->next;
	}
	g_slist_free(items.list);

Michael Meeks's avatar
Michael Meeks committed
520
	return value_new_int (items.num);
521
522
523
524
}

static char *help_sumif = {
	N_("@FUNCTION=SUMIF\n"
525
	   "@SYNTAX=SUMIF(range,criteria[,actual_range])\n"
526
527
528

	   "@DESCRIPTION="
	   "SUMIF function sums the values in the given range that meet "
529
530
531
	   "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. "
532
533
534
535
	   "\n"
	   "@SEEALSO=COUNTIF,SUM")
};

536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
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;
}


577
static Value *
578
gnumeric_sumif (FunctionEvalInfo *ei, Value **argv)
579
580
{
        Value           *range = argv[0];
581
	Value           *actual_range = argv[2];
Morten Welinder's avatar
Morten Welinder committed
582
	Value           *tmpvalue = NULL;
583

584
585
586
587
588
589
	math_criteria_t items;
	int             ret;
	float_t         sum;
	GSList          *list;

	items.num  = 0;
590
	items.total_num = 0;
591
592
593
	items.list = NULL;

	if ((!VALUE_IS_NUMBER(argv[1]) && argv[1]->type != VALUE_STRING)
594
595
	    || (range->type != VALUE_CELLRANGE))
	        return function_error (ei, gnumeric_err_VALUE);
596
597
598
599

	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
600
	} else {
601
602
	        parse_criteria(argv[1]->v.str->str,
			       &items.fun, &items.test_value);
Morten Welinder's avatar
Morten Welinder committed
603
604
		tmpvalue = items.test_value;
	}
605

606
607
608
609
610
	if (actual_range != NULL)
	        items.actual_range = TRUE;
	else
	        items.actual_range = FALSE;

611
	ret = sheet_cell_foreach_range (
612
613
614
615
616
617
618
		eval_sheet (range->v.cell_range.cell_a.sheet, ei->pos.sheet), TRUE,
		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
619
620
621
622

	if (tmpvalue)
		value_release (tmpvalue);

623
624
	if (ret == FALSE)
	        return function_error (ei, gnumeric_err_VALUE);
625

626
627
628
	if (actual_range == NULL) {
	        list = items.list;
		sum = 0;
629

630
631
		while (list != NULL) {
		        Value *v = list->data;
632

633
634
635
636
637
638
639
640
641
			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 (
642
643
644
645
646
647
648
649
		      eval_sheet (actual_range->v.cell_range.cell_a.sheet, ei->pos.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);
650
	      sum = items.sum;
651
652
	}

653
654
	g_slist_free(items.list);
		
Michael Meeks's avatar
Michael Meeks committed
655
	return value_new_float (sum);
656
657
}

658
659
660
661
662
663
664
665
666
667
668
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
669

670
671
672
673
	   "@SEEALSO=CEIL")
};

static Value *
674
gnumeric_ceiling (FunctionEvalInfo *ei, Value **argv)
675
{
Morten Welinder's avatar
Morten Welinder committed
676
        float_t number, s;
677

Morten Welinder's avatar
Morten Welinder committed
678
679
680
681
682
	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]);
683
	}
Morten Welinder's avatar
Morten Welinder committed
684

685
686
	if (s == 0 || number / s < 0)
		return function_error (ei, gnumeric_err_NUM);
687

Morten Welinder's avatar
Morten Welinder committed
688
	return value_new_float (ceil (number / s) * s);
689
690
}

691
692
static char *help_cos = {
	N_("@FUNCTION=COS\n"
693
	   "@SYNTAX=COS(x)\n"
694
695

	   "@DESCRIPTION="
696
	   "The  COS  function  returns  the cosine of x, where x is "
697
698
699
700
701
702
703
704
           "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
705
static Value *
706
gnumeric_cos (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
707
{
Michael Meeks's avatar
Michael Meeks committed
708
	return value_new_float (cos (value_get_as_float (argv [0])));
709
}
Arturo Espinosa's avatar
Arturo Espinosa committed
710

711
712
static char *help_cosh = {
	N_("@FUNCTION=COSH\n"
713
	   "@SYNTAX=COSH(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
714

715
	   "@DESCRIPTION="
716
717
718
	   "The COSH  function  returns the hyperbolic cosine of x, "
	   " which is defined mathematically as (exp(x) + exp(-x)) / 2.   "
	   " x is in radians. "
719
720
721
722
723
724
	   "\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
725
726

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

732
733
static char *help_degrees = {
	N_("@FUNCTION=DEGREES\n"
734
	   "@SYNTAX=DEGREES(x)\n"
735
736

	   "@DESCRIPTION="
737
738
	   "Computes the number of degrees equivalent to "
	   " x radians."
739
740
741
742
	   "\n"

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

744
745
746
	   "@SEEALSO=RADIANS, PI")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
747
static Value *
748
gnumeric_degrees (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
749
{
Michael Meeks's avatar
Michael Meeks committed
750
	return value_new_float ((value_get_as_float (argv [0]) * 180.0) / M_PI);
751
}
Arturo Espinosa's avatar
Arturo Espinosa committed
752

753
754
static char *help_exp = {
	N_("@FUNCTION=EXP\n"
755
	   "@SYNTAX=EXP(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
756

757
758
	   "@DESCRIPTION="
	   "Computes the value of e(the base of natural logarithmns) raised "
759
	   "to the power of x. "
760
761
762
763
764
	   "\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
765
766

static Value *
767
gnumeric_exp (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
768
{
Michael Meeks's avatar
Michael Meeks committed
769
	return value_new_float (exp (value_get_as_float (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
770
771
}

772
float_t
773
774
775
776
777
778
779
fact (int n)
{
	if (n == 0)
		return 1;
	return (n * fact (n - 1));
}

780
781
static char *help_fact = {
	N_("@FUNCTION=FACT\n"
782
	   "@SYNTAX=FACT(x)\n"
783
784

	   "@DESCRIPTION="
785
	   "Computes the factorial of x. ie, x!"
786
787
788
789
790
791
792
	   "\n"
	   "Performing this function on a string or empty cell returns an error"
	   "\n"
	   "\n"
	   "@SEEALSO=")
};

793
static Value *
794
gnumeric_fact (FunctionEvalInfo *ei, Value **argv)
795
{
Morten Welinder's avatar
Morten Welinder committed
796
797
	float_t x;
	gboolean x_is_integer;
798

799
800
	if (!VALUE_IS_NUMBER (argv[0]))
		return function_error (ei, gnumeric_err_NUM);
801

Morten Welinder's avatar
Morten Welinder committed
802
	x = value_get_as_float (argv[0]);
803
804
805
	if (x < 0)
		return function_error (ei, gnumeric_err_NUM);

Morten Welinder's avatar
Morten Welinder committed
806
	x_is_integer = (x == floor (x));
Morten Welinder's avatar
Morten Welinder committed
807

Morten Welinder's avatar
Morten Welinder committed
808
809
810
811
812
813
814
	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));
815
816
}

Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
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)
{
834
835
836
837
838
839
840
841
842
843
844
	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
845
846
847
}

static Value *
848
gnumeric_combin (FunctionEvalInfo *ei, Value **argv)
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
849
{
850
	int n ,k;
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
851

852
853
854
855
	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
856
		return value_new_float (combin (n ,k));
857

858
	return function_error (ei, gnumeric_err_NUM);
Jukka-Pekka Iivonen's avatar
Jukka-Pekka Iivonen committed
859
860
}

861
862
static char *help_floor = {
	N_("@FUNCTION=FLOOR\n"
Morten Welinder's avatar
Morten Welinder committed
863
	   "@SYNTAX=FLOOR(x,significance)\n"
864

865
	   "@DESCRIPTION=The FLOOR function rounds x down to the next nearest "
Morten Welinder's avatar
Morten Welinder committed
866
	   "multiple of @significance.  @significance defaults to 1."
867
868
869
870
871
872
	   "\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
873
static Value *
874
gnumeric_floor (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
875
{
Morten Welinder's avatar
Morten Welinder committed
876
877
878
879
880
881
882
883
884
        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]);
	}

885
886
	if (s == 0 || number / s < 0)
		return function_error (ei, gnumeric_err_NUM);
Morten Welinder's avatar
Morten Welinder committed
887
888

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

891
892
893
static char *help_int = {
	N_("@FUNCTION=INT\n"
	   "@SYNTAX=INT(b1, b2, ...)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
894

895
896
897
	   "@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
898
	   "Equivalent to FLOOR(b1) for b1 >= 0, amd CEIL(b1) "
Morten Welinder's avatar
Morten Welinder committed
899
	   "for b1 < 0. "
900
901
902
903
904
905
	   "\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
906
907

static Value *
908
gnumeric_int (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
909
{
910
911
	float_t t;

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

Morten Welinder's avatar
Morten Welinder committed
915
	return value_new_float (floor (value_get_as_float (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
916
917
}

918
919
static char *help_log = {
	N_("@FUNCTION=LOG\n"
920
	   "@SYNTAX=LOG(x[,base])\n"
921
922

	   "@DESCRIPTION="
923
924
	   "Computes the logarithm of x in the given base.  If no base is "
	   "given LOG returns the logarithm in base 10. "
925
	   "\n"
926
	   "@SEEALSO=LN, LOG2, LOG10")
927
928
};

Arturo Espinosa's avatar
Arturo Espinosa committed
929
static Value *
930
gnumeric_log (FunctionEvalInfo *ei, Value **argv)
931
932
933
{
	float_t t, base;

Michael Meeks's avatar
Michael Meeks committed
934
	t = value_get_as_float (argv [0]);
935
936
937
938

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

941
942
	if (t <= 0.0)
		return function_error (ei, gnumeric_err_VALUE);
943

Michael Meeks's avatar
Michael Meeks committed
944
	return value_new_float (log (t) / log (base));
945
946
947
948
949
950
951
952
953
954
955
956
957
}

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 *
958
gnumeric_ln (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
959
960
961
{
	float_t t;

Michael Meeks's avatar
Michael Meeks committed
962
	t = value_get_as_float (argv [0]);
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));
Arturo Espinosa's avatar
Arturo Espinosa committed
968
969
}

970
971
972
973
974
static char *help_power = {
	N_("@FUNCTION=POWER\n"
	   "@SYNTAX=POWER(x,y)\n"

	   "@DESCRIPTION="
Morten Welinder's avatar
Morten Welinder committed
975
	   "Returns the value of x raised to the power y."
976
	   "\n"
Morten Welinder's avatar
Morten Welinder committed
977
	   "Performing this function on a string or empty cell returns an error."
978
979
980
981
982
	   "\n"
	   "@SEEALSO=EXP")
};

static Value *
983
gnumeric_power (FunctionEvalInfo *ei, Value **argv)
984
{
Morten Welinder's avatar
Morten Welinder committed
985
986
987
988
989
990
991
992
993
	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?  */
994
	return function_error (ei, gnumeric_err_VALUE);
995
996
}

997
static char *help_log2 = {
998
	N_("@FUNCTION=LOG2\n"
999
	   "@SYNTAX=LOG2(x)\n"
1000
1001

	   "@DESCRIPTION="
1002
	   "Computes the base-2 logarithm  of x. "
1003
1004
1005
1006
1007
1008
	   "\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
1009
static Value *
1010
gnumeric_log2 (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
1011
1012
1013
{
	float_t t;

Michael Meeks's avatar
Michael Meeks committed
1014
	t = value_get_as_float (argv [0]);
1015
1016
1017
	if (t <= 0.0)
		return function_error (ei, _("log2: domain error"));

Michael Meeks's avatar
Michael Meeks committed
1018
	return value_new_float (log (t) / M_LN2);
Arturo Espinosa's avatar
Arturo Espinosa committed
1019
1020
}

1021
static char *help_log10 = {
1022
	N_("@FUNCTION=LOG10\n"
1023
	   "@SYNTAX=LOG10(x)\n"
1024
1025

	   "@DESCRIPTION="
1026
	   "Computes the base-10 logarithm  of x. "
1027
1028
1029
1030
1031
1032
1033
	   "\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
1034
static Value *
1035
gnumeric_log10 (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
1036
1037
1038
{
	float_t t;

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

Michael Meeks's avatar
Michael Meeks committed
1043
	return value_new_float (log10 (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
1044
1045
}

1046
1047
1048
1049
1050
1051
static char *help_mod = {
	N_("@FUNCTION=MOD\n"
	   "@SYNTAX=MOD(number,divisor)\n"

	   "@DESCRIPTION="
	   "Implements modulo arithmetic."
Morten Welinder's avatar
Morten Welinder committed
1052
	   "Returns the remainder when @divisor is divided into @number."
1053
1054
1055
1056
1057
1058
	   "\n"
	   "Returns #DIV/0! if divisor is zero."
	   "@SEEALSO=INT,FLOOR,CEIL")
};

static Value *
1059
gnumeric_mod (FunctionEvalInfo *ei, Value **argv)
1060
1061
{
	int a,b;
1062

1063
1064
1065
	a = value_get_as_int (argv[0]);
	b = value_get_as_int (argv[1]);

1066
1067
	if (b == 0)
		return function_error (ei, gnumeric_err_NUM);
Morten Welinder's avatar
Morten Welinder committed
1068
1069

	if (b < 0) {
1070
1071
		a = -a;
		b = -b;
Morten Welinder's avatar
Morten Welinder committed
1072
		/* FIXME: check for overflow.  */
1073
	}
Morten Welinder's avatar
Morten Welinder committed
1074

Morten Welinder's avatar
Morten Welinder committed
1075
1076
1077
1078
1079
1080
	if (a >= 0)
		return value_new_int (a % b);
	else {
		int invres = (-a) % b;
		return value_new_int (invres == 0 ? 0 : b - invres);
	}
1081
1082
}

1083
1084
static char *help_radians = {
	N_("@FUNCTION=RADIANS\n"
1085
	   "@SYNTAX=RADIANS(x)\n"
1086
1087

	   "@DESCRIPTION="
1088
1089
	   "Computes the number of radians equivalent to  "
	   "x degrees. "
1090
1091
1092
1093
	   "\n"

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

1095
1096
	   "@SEEALSO=PI,DEGREES")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
1097
1098

static Value *
1099
gnumeric_radians (FunctionEvalInfo *ei, Value **argv)
Arturo Espinosa's avatar
Arturo Espinosa committed
1100
{
Michael Meeks's avatar
Michael Meeks committed
1101