functions.c 29.7 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 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * Author:
 *  Miguel de Icaza (miguel@gnu.org)
 */
#include <config.h>
#include <gnome.h>
#include "math.h"
#include "gnumeric.h"
#include "gnumeric-sheet.h"
#include "utils.h"
#include "func.h"

/* Some forward declarations */
static Value *gnumeric_sum         (void *tsheet, GList *expr_node_list,
				    int eval_col, int eval_row,
				    char **error_string);

static Value *gnumeric_count       (void *tsheet, GList *expr_node_list,
				    int eval_col, int eval_row,
				    char **error_string);

Donnie Barnes's avatar
Donnie Barnes committed
24 25 26
#if 0
/* help template */
static char *help_ = {
27 28
	N_("@FUNCTION=NAME\n"
	   "@SYNTAX=(b1, b2, ...)\n"
Donnie Barnes's avatar
Donnie Barnes committed
29

30
	   "@DESCRIPTION"
Donnie Barnes's avatar
Donnie Barnes committed
31
	   ""
32
	   "\n"
Donnie Barnes's avatar
Donnie Barnes committed
33 34 35

	   ""
	   ""
36
	   "\n"
Donnie Barnes's avatar
Donnie Barnes committed
37 38 39 40
	   
	   ""
	   ""
	   ""
41 42
	   ""
	   "@SEEALSO=")
Donnie Barnes's avatar
Donnie Barnes committed
43 44 45 46
};

#endif

47 48 49
static char *help_abs = {
	N_("@FUNCTION=ABS\n"
	   "@SYNTAX=ABS(b1)\n"
50

51 52 53
	   "@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."
54
	   "\n"
55
	   "Performing this function on a string or empty cell simply does nothing."
56
	   "\n"
57
	   "@SEEALSO=CEIL, FLOOR")
58 59
};

60 61 62 63 64
static Value *
gnumeric_abs (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
	return value_float (fabs (value_get_as_double (argv [0])));
}
65 66

static char *help_acos = {
67
	N_("@FUNCTION=ACOS\n"
68
	   "@SYNTAX=ACOS(x)\n"
69

70
	   "@DESCRIPTION="
71 72
	   "The ACOS function calculates the arc cosine of x; that "
	   " is the value whose cosine is x.  If x  falls  outside  the "
73 74
	   " range -1 to 1, ACOS fails and returns the error 'acos - domain error'. "
	   " The value it returns is in radians. "
75
	   "\n"
76 77
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
78 79
	   "\n"
	   "@SEEALSO=COS, SIN, DEGREES, RADIANS")
80 81
};

82 83 84 85
static Value *
gnumeric_acos (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
	float_t t;
Donnie Barnes's avatar
Donnie Barnes committed
86

87 88 89 90 91 92 93 94 95 96
	t = value_get_as_double (argv [0]);
	if ((t < -1.0) || (t > 1.0)){
		*error_string = _("acos - domain error");
		return NULL;
	}
	return value_float (acos (t));
}

static char *help_acosh = {
	N_("@FUNCTION=ACOSH\n"
97
	   "@SYNTAX=ACOSH(x)\n"
98 99 100

	   "@DESCRIPTION="
	   "The ACOSH  function  calculates  the inverse hyperbolic "
101 102
	   "cosine of x; that is the value whose hyperbolic cosine is "
	   "x. If x is less than 1.0, acosh() returns the error "
103
	   " 'acosh - domain error'"
Arturo Espinosa's avatar
Arturo Espinosa committed
104
	   "\n"
105 106
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
107
	   "\n"
108
	   "@SEEALSO=ACOS, DEGREES, RADIANS ")
Donnie Barnes's avatar
Donnie Barnes committed
109 110
};

111 112 113 114 115 116 117 118 119 120 121 122 123
static Value *
gnumeric_acosh (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
	float_t t;

	t = value_get_as_double (argv [0]);
	if (t < 1.0){
		*error_string = _("acosh - domain error");
		return NULL;
	}
	return value_float (acosh (t));
}

Arturo Espinosa's avatar
Arturo Espinosa committed
124
static char *help_and = {
125 126
	N_("@FUNCTION=AND\n"
	   "@SYNTAX=AND(b1, b2, ...)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
127

128
	   "@DESCRIPTION=Implements the logical AND function: the result is TRUE "
Donnie Barnes's avatar
Donnie Barnes committed
129
	   "if all of the expression evaluates to TRUE, otherwise it returns "
130
	   "FALSE.\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
131

132
	   "b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
Arturo Espinosa's avatar
Arturo Espinosa committed
133
	   "If an integer or floating point value is provided zero is considered "
134
	   "FALSE and anything else is TRUE.\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
135 136 137 138
	   
	   "If the values contain strings or empty cells those values are "
	   "ignored.  If no logical values are provided, then the error '#VALUE!' "
	   "is returned. "
139
	   "\n"
140
	   "@SEEALSO=OR")
Arturo Espinosa's avatar
Arturo Espinosa committed
141 142
};

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
static int
callback_function_and (Sheet *sheet, Value *value, char **error_string, void *closure)
{
	Value *result = closure;
	
	switch (value->type){
	case VALUE_INTEGER:
		if (value->v.v_int == 0){
			result->v.v_int = 0;
			return FALSE;
		} else
			result->v.v_int = 1;
		break;

	case VALUE_FLOAT:
		if (value->v.v_float == 0.0){
			result->v.v_int = 0;
			return FALSE;
		} else
			result->v.v_int = 1;

	default:
		/* ignore strings */
	}
	
	return TRUE;
}

Arturo Espinosa's avatar
Arturo Espinosa committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
static Value *
gnumeric_and (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
	Value *result;
	Sheet *sheet = (Sheet *) tsheet;

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

	function_iterate_argument_values (sheet, callback_function_and,
					  result, expr_node_list,
					  eval_col, eval_row, error_string);

	/* See if there was any value worth using */
	if (result->v.v_int == -1){
		value_release (result);
		*error_string = _("#VALUE");
		return NULL;
	}
	return result;
}

194 195
static char *help_asin = {
	N_("@FUNCTION=ASIN\n"
196
	   "@SYNTAX=ASIN(x)\n"
197 198

	   "@DESCRIPTION="
199 200
	   "The ASIN function calculates the arc sine of x; that is "
	   "the value whose sine is x. If x falls outside  the  range "
201 202 203 204 205 206 207 208
	   "-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
209
static Value *
210
gnumeric_asin (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
211 212 213 214 215 216 217 218
{
	float_t t;

	t = value_get_as_double (argv [0]);
	if ((t < -1.0) || (t > 1.0)){
		*error_string = _("asin - domain error");
		return NULL;
	}
219
	return value_float (asin (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
220 221
}

222 223
static char *help_asinh = {
	N_("@FUNCTION=ASINH\n"
224
	   "@SYNTAX=ASINH(x)\n"
225 226

	   "@DESCRIPTION="
227 228
	   "The ASINH  function  calculates  the inverse hyperbolic "
	   " sine of x; that is the value whose hyperbolic sine is x. "
229 230 231 232 233 234 235 236
	   "\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
237
static Value *
238
gnumeric_asinh (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
239
{
240 241
	return value_float (asinh (value_get_as_double (argv [0])));
}
Arturo Espinosa's avatar
Arturo Espinosa committed
242

243 244
static char *help_atan = {
	N_("@FUNCTION=ATAN\n"
245
	   "@SYNTAX=ATAN(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
246

247
	   "@DESCRIPTION="
248 249
	   "The ATAN function calculates the arc tangent of x; that "
	   " is the value whose tangent is x."
250 251 252 253 254 255 256 257 258
	   "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
259 260

static Value *
261
gnumeric_atan (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
262
{
263
	return value_float (atan (value_get_as_double (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
264 265
}

266 267
static char *help_atanh = {
	N_("@FUNCTION=ATANH\n"
268
	   "@SYNTAX=ATANH(x)\n"
269 270 271

	   "@DESCRIPTION="
	   "The  ATANH  function  calculates  the inverse hyperbolic "
272 273
	   "tangent of x; that is the value whose  hyperbolic  tangent "
	   "is  x.   If  the  absolute value of x is greater than 1.0, "
274 275 276 277 278 279 280 281 282
	   " 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
283
static Value *
284
gnumeric_atanh (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
285 286 287 288 289 290 291 292
{
	float_t t;

	t = value_get_as_double (argv [0]);
	if ((t <= -1.0) || (t >= 1.0)){
		*error_string = _("atanh: domain error");
		return NULL;
	}
293
	return value_float (atanh (value_get_as_double (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
294 295
}

296
static char *help_atan2 = {
297
	N_("@FUNCTION=ATAN2\n"
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
	   "@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
313
static Value *
314
gnumeric_atan2 (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
315
{
316 317
	return value_float (atan2 (value_get_as_double (argv [0]),
				   value_get_as_double (argv [1])));
Arturo Espinosa's avatar
Arturo Espinosa committed
318 319
}

320 321
static char *help_average = {
	N_("@FUNCTION=AVERAGE\n"
322
	   "@SYNTAX=AVERAGE(value1, value2,...)\n"
323 324 325 326 327 328 329 330 331

	   "@DESCRIPTION="
	   "Computes the average of all the values and cells referenced in the "
	   "argument list.  This is equivalent to the sum of the arguments divided "
	   "by the count of the arguments."
	   "\n"
	   "@SEEALSO=SUM, COUNT")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
332 333 334 335 336
static Value *
gnumeric_average (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
	Value *result;
	Value *sum, *count;
337 338
	double c;
	
Arturo Espinosa's avatar
Arturo Espinosa committed
339 340 341 342 343
	sum = gnumeric_sum (tsheet, expr_node_list, eval_col, eval_row, error_string);
	if (!sum)
		return NULL;
	
	count = gnumeric_count (tsheet, expr_node_list, eval_col, eval_row, error_string);
344
	if (!count){
Arturo Espinosa's avatar
Arturo Espinosa committed
345 346 347 348
		value_release (sum);
		return NULL;
	}

Arturo Espinosa's avatar
Arturo Espinosa committed
349
	c = value_get_as_double (count);
350 351 352 353 354 355 356
	
	if (c == 0.0){
		*error_string = "Division by zero";
		value_release (sum);
		return NULL;
	}
	
Arturo Espinosa's avatar
Arturo Espinosa committed
357
	result = value_float (value_get_as_double (sum) / c);
358

Arturo Espinosa's avatar
Arturo Espinosa committed
359 360 361 362 363 364
	value_release (count);
	value_release (sum);
	
	return result;
}

365 366
static char *help_ceil = {
	N_("@FUNCTION=CEIL\n"
367
	   "@SYNTAX=CEIL(x)\n"
368

369 370
	   "@DESCRIPTION=The CEIL function rounds x up to the next nearest "
	   "integer.\n"
371 372 373 374 375 376 377

	   "Performing this function on a string or empty cell simply does nothing."
	   "\n"
	   
	   "@SEEALSO=ABS, FLOOR, INT")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
378
static Value *
379
gnumeric_ceil (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
380
{
381 382 383 384
	return value_float (ceil (value_get_as_double (argv [0])));
}

static char *help_bin2dec = {
385 386
	N_("@FUNCTION=BIN2DEC\n"
	   "@SYNTAX=BIN2DEC(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
387

388
	   "@DESCRIPTION="
389 390
	   "The BIN2DEC function converts a binary number "
	   "in string or number to its decimal equivalent."
391
	   "\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
392

393 394 395 396
	   "Performing this function on a string or empty cell simply does nothing."
	   "\n"
	   "@SEEALSO=DEC2BIN")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
397 398

static Value *
399
gnumeric_bin2dec (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
{
	int  result, v, n, bit;
	char *p;

	result = 0;
	switch (argv [0]->type){
	case VALUE_INTEGER:
		v = argv [0]->v.v_int;
		n = 0;
		for (n = 0; v; n++){
			bit = v % 10;
			v   = v / 10;
			result |= bit << n;
		}
		break;
		
	case VALUE_STRING:
		p = argv [0]->v.str->str;
418
		for (;*p; p++){
Arturo Espinosa's avatar
Arturo Espinosa committed
419 420 421 422
			if (!(*p == '0' || *p == '1')){
				*error_string = "#NUM!";
				return NULL;
			}
423
			result = result << 1 | (*p - '0');
Arturo Espinosa's avatar
Arturo Espinosa committed
424 425 426 427 428 429 430
		}
		break;
		
	default:
		*error_string = "#NUM!";
		return NULL;
	}
431
	return value_int (result);
Arturo Espinosa's avatar
Arturo Espinosa committed
432 433
}

434 435
static char *help_cos = {
	N_("@FUNCTION=COS\n"
436
	   "@SYNTAX=COS(x)\n"
437 438

	   "@DESCRIPTION="
439
	   "The  COS  function  returns  the cosine of x, where x is "
440 441 442 443 444 445 446 447
           "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
448
static Value *
449
gnumeric_cos (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
450
{
451 452
	return value_float (cos (value_get_as_double (argv [0])));
}
Arturo Espinosa's avatar
Arturo Espinosa committed
453

454 455
static char *help_cosh = {
	N_("@FUNCTION=COSH\n"
456
	   "@SYNTAX=COSH(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
457

458
	   "@DESCRIPTION="
459 460 461
	   "The COSH  function  returns the hyperbolic cosine of x, "
	   " which is defined mathematically as (exp(x) + exp(-x)) / 2.   "
	   " x is in radians. "
462 463 464 465 466 467
	   "\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
468 469

static Value *
470
gnumeric_cosh (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
471
{
472
	return value_float (cosh (value_get_as_double (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
}

static int
callback_function_count (Sheet *sheet, Value *value, char **error_string, void *closure)
{
	Value *result = (Value *) closure;

	switch (value->type){
	case VALUE_INTEGER:
		result->v.v_int++;
		break;
		
	case VALUE_FLOAT:
		result->v.v_int++;
		break;
		
	default:
		break;
	}		
	return TRUE;
}

495 496 497 498 499 500 501 502 503 504 505 506
static char *help_count = {
	N_("@FUNCTION=COUNT\n"
	   "@SYNTAX=COUNT(b1, b2, ...)\n"

	   "@DESCRIPTION="
	   "Returns the total number of arguments passed."
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing."
	   "\n"
	   "@SEEALSO=AVERAGE")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
static Value *
gnumeric_count (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
	Value *result;
	Sheet *sheet = (Sheet *) tsheet;

	result = g_new (Value, 1);
	result->type = VALUE_INTEGER;
	result->v.v_int = 0;
	
	function_iterate_argument_values (sheet, callback_function_count, result, expr_node_list,
					  eval_col, eval_row, error_string);

	return result;
}

523 524
static char *help_degrees = {
	N_("@FUNCTION=DEGREES\n"
525
	   "@SYNTAX=DEGREES(x)\n"
526 527

	   "@DESCRIPTION="
528 529
	   "Computes the number of degrees equivalent to "
	   " x radians."
530 531 532 533 534 535 536 537
	   "\n"

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

Arturo Espinosa's avatar
Arturo Espinosa committed
538
static Value *
539
gnumeric_degrees (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
540
{
541 542
	return value_float ((value_get_as_double (argv [0]) * 180.0) / M_PI);
}
Arturo Espinosa's avatar
Arturo Espinosa committed
543

544 545
static char *help_exp = {
	N_("@FUNCTION=EXP\n"
546
	   "@SYNTAX=EXP(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
547

548 549
	   "@DESCRIPTION="
	   "Computes the value of e(the base of natural logarithmns) raised "
550
	   "to the power of x. "
551 552 553 554 555
	   "\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
556 557

static Value *
558
gnumeric_exp (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
559
{
560
	return value_float (exp (value_get_as_double (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
561 562
}

563 564 565 566 567 568 569 570
static float_t
fact (int n)
{
	if (n == 0)
		return 1;
	return (n * fact (n - 1));
}

571 572
static char *help_fact = {
	N_("@FUNCTION=FACT\n"
573
	   "@SYNTAX=FACT(x)\n"
574 575

	   "@DESCRIPTION="
576
	   "Computes the factorial of x. ie, x!"
577 578 579 580 581 582 583
	   "\n"
	   "Performing this function on a string or empty cell returns an error"
	   "\n"
	   "\n"
	   "@SEEALSO=")
};

584
static Value *
585
gnumeric_fact (struct FunctionDefinition *id, Value *argv [], char **error_string)
586 587
{
	Value *res;
588
	float i;
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607

	switch (argv [0]->type){
	case VALUE_FLOAT:
		i = argv [0]->v.v_float;
		break;
	case VALUE_INTEGER:
		i = argv [0]->v.v_int;
		break;
	default:
		*error_string = "#NUM!";
		return NULL;
	}

	if (i < 0){
		*error_string = "#NUM!";
		return NULL;
	}
	
	res = g_new (Value, 1);
608 609 610 611 612 613
	if (i > 12){
		res->type = VALUE_FLOAT;
		res->v.v_float = exp (lgamma (i + 1));
	} else {
		res->type = VALUE_INTEGER;
		res->v.v_int = fact ((int)i);
614 615 616 617
	}
	return res;
}

618 619
static char *help_floor = {
	N_("@FUNCTION=FLOOR\n"
620
	   "@SYNTAX=FLOOR(x)\n"
621

622
	   "@DESCRIPTION=The FLOOR function rounds x down to the next nearest "
623 624 625 626 627 628 629 630
	   "integer."
	   "\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
631
static Value *
632
gnumeric_floor (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
633
{
634 635
	return value_float (floor (value_get_as_double (argv [0])));
}
Arturo Espinosa's avatar
Arturo Espinosa committed
636

637 638 639
static char *help_int = {
	N_("@FUNCTION=INT\n"
	   "@SYNTAX=INT(b1, b2, ...)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
640

641 642 643
	   "@DESCRIPTION="
	   "The INT function round b1 now to the nearest int. "
	   "Where 'nearest' implies being closer to zero. "
644
	   "Equivalent to FLOOR(b1) for b1 >0, amd CEIL(b1) "
645 646 647 648 649 650 651
	   "for b1 < 0. " 
	   "\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
652 653

static Value *
654
gnumeric_int (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
655 656 657 658 659
{
	float_t t;

	t = value_get_as_double (argv [0]);
	
660
	return value_float (t > 0.0 ? floor (t) : ceil (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
661 662
}

663 664
static char *help_log = {
	N_("@FUNCTION=LOG\n"
665
	   "@SYNTAX=LOG(x)\n"
666 667

	   "@DESCRIPTION="
668
	   "Computes the natural logarithm  of x. "
669 670 671 672 673 674
	   "\n"
	   "Performing this function on a string or empty cell returns an error. "
	   "\n"
	   "@SEEALSO=EXP, LOG2, LOG10")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
675
static Value *
676
gnumeric_log (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
677 678 679 680
{
	float_t t;

	t = value_get_as_double (argv [0]);
681
	if (t <= 0.0){
Arturo Espinosa's avatar
Arturo Espinosa committed
682 683 684
		*error_string = _("log: domain error");
		return NULL;
	}
685
	return value_float (log (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
686 687
}

688
static char *help_log2 = {
689
	N_("@FUNCTION=LOG2\n"
690
	   "@SYNTAX=LOG2(x)\n"
691 692

	   "@DESCRIPTION="
693
	   "Computes the base-2 logarithm  of x. "
694 695 696 697 698 699
	   "\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
700
static Value *
701
gnumeric_log2 (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
702 703 704 705
{
	float_t t;

	t = value_get_as_double (argv [0]);
706
	if (t <= 0.0){
Arturo Espinosa's avatar
Arturo Espinosa committed
707 708 709
		*error_string = _("log2: domain error");
		return NULL;
	}
710
	return value_float (log (t) / M_LN2);
Arturo Espinosa's avatar
Arturo Espinosa committed
711 712
}

713
static char *help_log10 = {
714
	N_("@FUNCTION=LOG10\n"
715
	   "@SYNTAX=LOG10(x)\n"
716 717

	   "@DESCRIPTION="
718
	   "Computes the base-10 logarithm  of x. "
719 720 721 722 723 724 725
	   "\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
726
static Value *
727
gnumeric_log10 (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
728 729 730 731
{
	float_t t;

	t = value_get_as_double (argv [0]);
732
	if (t <= 0.0){
Arturo Espinosa's avatar
Arturo Espinosa committed
733 734 735
		*error_string = _("log10: domain error");
		return NULL;
	}
736
	return value_float (log10 (t));
Arturo Espinosa's avatar
Arturo Espinosa committed
737 738
}

739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
static char *help_min = {
	N_("@FUNCTION=MIN\n"
	   "@SYNTAX=MIN(b1, b2, ...)\n"

	   "@DESCRIPTION="
	   "MIN returns the value of the element of the values passed "
	   "that has the smallest value. With negative numbers considered "
	   "smaller than positive numbers."
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing."
	   "\n"
	   "@SEEALSO=MAX,ABS")
};

static char *help_max = {
	N_("@FUNCTION=MAX\n"
	   "@SYNTAX=MAX(b1, b2, ...)\n"

	   "@DESCRIPTION="
	   "MAX returns the value of the element of the values passed "
	   "that has the largest value. With negative numbers considered "
	   "smaller than positive numbers."
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing."
	   "\n"
	   "@SEEALSO=MIN,ABS")
};

767
enum {
768 769
	OPER_MIN,
	OPER_MAX
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785
};

typedef struct {
	int   operation;
	int   found;
	Value *result;
} min_max_closure_t;

static int
callback_function_min_max (Sheet *sheet, Value *value, char **error_string, void *closure)
{
	min_max_closure_t *mm = closure;
	
	switch (value->type){
	case VALUE_INTEGER:
		if (mm->found){
786
			if (mm->operation == OPER_MIN){
787 788 789 790 791 792 793 794 795 796 797 798 799 800
				if (value->v.v_int < mm->result->v.v_float)
					mm->result->v.v_float = value->v.v_int;
			} else {
				if (value->v.v_int > mm->result->v.v_float)
					mm->result->v.v_float = value->v.v_int;
			}
		} else {
			mm->found = 1;
			mm->result->v.v_float = value->v.v_int;
		}
		break;

	case VALUE_FLOAT:
		if (mm->found){
801
			if (mm->operation == OPER_MIN){
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
				if (value->v.v_float < mm->result->v.v_float)
					mm->result->v.v_float = value->v.v_float;
			} else {
				if (value->v.v_float > mm->result->v.v_float)
					mm->result->v.v_float = value->v.v_float;
			}
		} else {
			mm->found = 1;
			mm->result->v.v_float = value->v.v_float;
		}

	default:
		/* ignore strings */
	}
	
	return TRUE;
}

static Value *
gnumeric_min (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
	min_max_closure_t closure;
	Sheet *sheet = (Sheet *) tsheet;

826
	closure.operation = OPER_MIN;
827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
	closure.found  = 0;
	closure.result = g_new (Value, 1);
	closure.result->type = VALUE_FLOAT;
	closure.result->v.v_float = 0;

	function_iterate_argument_values (sheet, callback_function_min_max,
					  &closure, expr_node_list,
					  eval_col, eval_row, error_string);

	return 	closure.result;
}

static Value *
gnumeric_max (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
	min_max_closure_t closure;
	Sheet *sheet = (Sheet *) tsheet;

845
	closure.operation = OPER_MAX;
846 847 848 849 850 851 852 853 854 855 856
	closure.found  = 0;
	closure.result = g_new (Value, 1);
	closure.result->type = VALUE_FLOAT;
	closure.result->v.v_float = 0;

	function_iterate_argument_values (sheet, callback_function_min_max,
					  &closure, expr_node_list,
					  eval_col, eval_row, error_string);
	return 	closure.result;
}

857 858
static char *help_or = {
	N_("@FUNCTION=OR\n"
859
	   "@SYNTAX=OR(b1, b2, ...)\n"
860 861

	   "@DESCRIPTION="
862
	   "Implements the logical OR function: the result is TRUE if any of the "
863
	   "values evaluated to TRUE.\n"
864 865
	   "b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
	   "If an integer or floating point value is provided zero is considered "
866 867 868 869 870 871 872 873
	   "FALSE and anything else is TRUE.\n"
	   "If the values contain strings or empty cells those values are "
	   "ignored.  If no logical values are provided, then the error '#VALUE!'"
	   "is returned.\n"

	   "@SEEALSO=AND")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
874 875 876 877 878 879 880
static int
callback_function_or (Sheet *sheet, Value *value, char **error_string, void *closure)
{
	Value *result = closure;
	
	switch (value->type){
	case VALUE_INTEGER:
881
		if (value->v.v_int != 0){
Arturo Espinosa's avatar
Arturo Espinosa committed
882 883 884 885 886 887 888
			result->v.v_int = 1;
			return FALSE;
		} else
			result->v.v_int = 0;
		break;

	case VALUE_FLOAT:
889
		if (value->v.v_float != 0.0){
Arturo Espinosa's avatar
Arturo Espinosa committed
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924
			result->v.v_int = 1;
			return FALSE;
		} else
			result->v.v_int = 0;

	default:
		/* ignore strings */
	}
	
	return TRUE;
}

static Value *
gnumeric_or (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
	Value *result;
	Sheet *sheet = (Sheet *) tsheet;

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

	function_iterate_argument_values (sheet, callback_function_or,
					  result, expr_node_list,
					  eval_col, eval_row, error_string);

	/* See if there was any value worth using */
	if (result->v.v_int == -1){
		value_release (result);
		*error_string = _("#VALUE");
		return NULL;
	}
	return result;
}

925 926
static char *help_radians = {
	N_("@FUNCTION=RADIANS\n"
927
	   "@SYNTAX=RADIANS(x)\n"
928 929

	   "@DESCRIPTION="
930 931
	   "Computes the number of radians equivalent to  "
	   "x degrees. "
932 933 934 935 936 937 938
	   "\n"

	   "Performing this function on a string or empty cell simply does nothing. "
	   "\n"
	   
	   "@SEEALSO=PI,DEGREES")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
939 940

static Value *
941
gnumeric_radians (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
942
{
943 944
	return value_float ((value_get_as_double (argv [0]) * M_PI) / 180);
}
Arturo Espinosa's avatar
Arturo Espinosa committed
945

946 947
static char *help_sin = {
	N_("@FUNCTION=SIN\n"
948
	   "@SYNTAX=SIN(x)\n"
Arturo Espinosa's avatar
Arturo Espinosa committed
949

950
	   "@DESCRIPTION="
951
	   "The SIN function returns the sine of x, where x is given "
952 953 954 955 956 957 958
           " in radians. "
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=COS, COSH, SINH, TAN, TANH, RADIANS, DEGREES")
};
Arturo Espinosa's avatar
Arturo Espinosa committed
959 960

static Value *
961
gnumeric_sin (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
962
{
963
	return value_float (sin (value_get_as_double (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
964 965
}

966 967
static char *help_sinh = {
	N_("@FUNCTION=SINH\n"
968
	   "@SYNTAX=SINH(x)\n"
969 970

	   "@DESCRIPTION="
971 972 973
	   "The SINH  function  returns  the  hyperbolic sine of x, "
	   "which is defined mathematically as (exp(x) - exp(-x)) / 2. "
	   " x is in radians. "
974 975 976 977 978 979 980
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=SIN, COS, COSH, TAN, TANH, DEGREES, RADIANS, EXP")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
981
static Value *
982
gnumeric_sinh (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
983
{
984
	return value_float (sinh (value_get_as_double (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
985 986
}

987 988 989 990 991 992 993 994 995 996 997 998
static char *help_sum = {
	N_("@FUNCTION=SUM\n"
	   "@SYNTAX=SUM(value1, value2, ...)\n"

	   "@DESCRIPTION="
	   "Computes the sum of all the values and cells referenced in the "
	   "argument list. " 
	   "\n"

	   "@SEEALSO=AVERAGE, COUNT")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
999 1000 1001 1002 1003 1004 1005
static int
callback_function_sum (Sheet *sheet, Value *value, char **error_string, void *closure)
{
	Value *result = (Value *) closure;

	switch (value->type){
	case VALUE_INTEGER:
1006 1007 1008 1009
		if (result->type == VALUE_INTEGER)
			result->v.v_int += value->v.v_int;
		else
			result->v.v_float += value->v.v_int;
Arturo Espinosa's avatar
Arturo Espinosa committed
1010 1011 1012
		break;
		
	case VALUE_FLOAT:
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
		if (result->type == VALUE_FLOAT)
			result->v.v_float += value->v.v_float;
		else {
			double v = result->v.v_int;

			/* cast to float */
			
			result->type = VALUE_FLOAT;
			result->v.v_float = v + value->v.v_float;
		}
Arturo Espinosa's avatar
Arturo Espinosa committed
1023
		break;
1024 1025 1026

	case VALUE_STRING:
		break;
Arturo Espinosa's avatar
Arturo Espinosa committed
1027 1028
		
	default:
1029 1030 1031 1032
		g_warning ("Unimplemented value->type in callback_function_sum : %s (%d)",
			   (value->type == VALUE_CELLRANGE) ? "CELLRANGE" :
			   (value->type == VALUE_ARRAY) ? "ARRAY" :
			   "UNKOWN!", value->type);
Arturo Espinosa's avatar
Arturo Espinosa committed
1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044
		break;
	}		
	return TRUE;
}

static Value *
gnumeric_sum (void *tsheet, GList *expr_node_list, int eval_col, int eval_row, char **error_string)
{
	Value *result;
	Sheet *sheet = (Sheet *) tsheet;

	result = g_new (Value, 1);
1045 1046
	result->type = VALUE_INTEGER;
	result->v.v_int = 0;
Arturo Espinosa's avatar
Arturo Espinosa committed
1047 1048 1049 1050 1051 1052 1053
	
	function_iterate_argument_values (sheet, callback_function_sum, result, expr_node_list,
					  eval_col, eval_row, error_string);

	return result;
}

1054 1055
static char *help_tan = {
	N_("@FUNCTION=TAN\n"
1056
	   "@SYNTAX=TAN(x)\n"
1057 1058

	   "@DESCRIPTION="
1059
	   "The TAN function  returns the tangent of x, where x is "
1060 1061 1062 1063 1064 1065 1066 1067
	   "given in radians. "
	   "\n"
	   "Performing this function on a string or empty cell simply does nothing. "
	   "This function only takes one argument."
	   "\n"
	   "@SEEALSO=TANH, COS, COSH, SIN, SINH, DEGREES, RADIANS")
};

Arturo Espinosa's avatar
Arturo Espinosa committed
1068
static Value *
1069
gnumeric_tan (struct FunctionDefinition *i, Value *argv [], char **error_string)
Arturo Espinosa's avatar
Arturo Espinosa committed
1070
{
1071
	return value_float (tan (value_get_as_double (argv [0])));
Arturo Espinosa's avatar
Arturo Espinosa committed
1072 1073
}