Commit 6e7e4987 authored by Jukka-Pekka Iivonen's avatar Jukka-Pekka Iivonen Committed by jpekka

Moved logical functions into a new file.

1999-04-29  Jukka-Pekka Iivonen  <iivonen@iki.fi>

	* src/fn-{math,sheet,logical}.c, src/func.[ch]: Moved logical
 	functions into a new file.
parent 4fdb17f7
1999-04-29 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-{math,sheet,logical}.c, src/func.[ch]: Moved logical
functions into a new file.
* src/fn-math.c: Added ROUNDDOWN(), ROUNDUP(), SUMX2MY2(),
SUMX2PY2(), and SUMXMY2().
......
1999-04-29 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-{math,sheet,logical}.c, src/func.[ch]: Moved logical
functions into a new file.
* src/fn-math.c: Added ROUNDDOWN(), ROUNDUP(), SUMX2MY2(),
SUMX2PY2(), and SUMXMY2().
......
1999-04-29 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-{math,sheet,logical}.c, src/func.[ch]: Moved logical
functions into a new file.
* src/fn-math.c: Added ROUNDDOWN(), ROUNDUP(), SUMX2MY2(),
SUMX2PY2(), and SUMXMY2().
......
1999-04-29 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-{math,sheet,logical}.c, src/func.[ch]: Moved logical
functions into a new file.
* src/fn-math.c: Added ROUNDDOWN(), ROUNDUP(), SUMX2MY2(),
SUMX2PY2(), and SUMXMY2().
......
/*
* fn-logical.c: Built in logical functions and functions registration
*
* Authors:
* Miguel de Icaza (miguel@gnu.org)
* Jukka-Pekka Iivonen (iivonen@iki.fi)
*/
#include <config.h>
#include <gnome.h>
#include "math.h"
#include "gnumeric.h"
#include "gnumeric-sheet.h"
#include "utils.h"
#include "func.h"
static char *help_and = {
N_("@FUNCTION=AND\n"
"@SYNTAX=AND(b1, b2, ...)\n"
"@DESCRIPTION=Implements the logical AND function: the result is TRUE "
"if all of the expression evaluates to TRUE, otherwise it returns "
"FALSE.\n"
"b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
"If an integer or floating point value is provided zero is considered "
"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=OR, NOT")
};
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 */
break;
}
return TRUE;
}
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;
}
static char *help_not = {
N_("@FUNCTION=NOT\n"
"@SYNTAX=NOT(number)\n"
"@DESCRIPTION="
"Implements the logical NOT function: the result is TRUE if the "
"number is zero; othewise the result is FALSE.\n\n"
"@SEEALSO=AND, OR")
};
static Value *
gnumeric_not (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
int b;
b = value_get_as_int (argv [0]);
return value_int (!b);
}
static char *help_or = {
N_("@FUNCTION=OR\n"
"@SYNTAX=OR(b1, b2, ...)\n"
"@DESCRIPTION="
"Implements the logical OR function: the result is TRUE if any of the "
"values evaluated to TRUE.\n"
"b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
"If an integer or floating point value is provided zero is considered "
"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, NOT")
};
static int
callback_function_or (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 = 1;
return FALSE;
} else
result->v.v_int = 0;
break;
case VALUE_FLOAT:
if (value->v.v_float != 0.0){
result->v.v_int = 1;
return FALSE;
} else
result->v.v_int = 0;
default:
/* ignore strings */
break;
}
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;
}
static char *help_if = {
N_("@FUNCTION=IF\n"
"@SYNTAX=IF(condition[,if-true,if-false])\n"
"@DESCRIPTION="
"Use the IF statement to evaluate conditionally other expressions "
"IF evaluates @condition. If @condition returns a non-zero value "
"the result of the IF expression is the @if-true expression, otherwise "
"IF evaluates to the value of @if-false."
"If ommitted if-true defaults to TRUE and if-false to FALSE."
"\n"
"@SEEALSO=")
};
static Value *
gnumeric_if (void *tsheet, GList *expr_node_list,
int eval_col, int eval_row, char **error_string)
{
ExprTree *expr;
Value *value;
int err, ret, args;
/* Type checking */
args = g_list_length (expr_node_list);
if (args < 1 || args > 3){
*error_string = _("Invalid number of arguments");
return NULL;
}
/* Compute the if part */
value = eval_expr (tsheet, (ExprTree *) expr_node_list->data,
eval_col, eval_row, error_string);
if (value == NULL)
return NULL;
/* Choose which expression we will evaluate */
ret = value_get_bool (value, &err);
value_release (value);
if (err)
return NULL;
if (ret){
if (expr_node_list->next)
expr = (ExprTree *) expr_node_list->next->data;
else
return value_int (1);
} else {
if (expr_node_list->next &&
expr_node_list->next->next)
expr = (ExprTree *) expr_node_list->next->next->data;
else
return value_int (0);
}
/* Return the result */
return eval_expr (tsheet, (ExprTree *) expr, eval_col,
eval_row, error_string);
}
FunctionDefinition logical_functions [] = {
{ "and", 0, "", &help_and, gnumeric_and, NULL },
{ "if", 0, "logical_test,value_if_true,value_if_false", &help_if,
gnumeric_if, NULL },
{ "not", "f", "number", &help_not, NULL, gnumeric_not },
{ "or", 0, "", &help_or, gnumeric_or, NULL },
{ NULL, NULL },
};
......@@ -117,79 +117,6 @@ gnumeric_acosh (struct FunctionDefinition *i,
return value_float (acosh (t));
}
static char *help_and = {
N_("@FUNCTION=AND\n"
"@SYNTAX=AND(b1, b2, ...)\n"
"@DESCRIPTION=Implements the logical AND function: the result is TRUE "
"if all of the expression evaluates to TRUE, otherwise it returns "
"FALSE.\n"
"b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
"If an integer or floating point value is provided zero is considered "
"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=OR, NOT")
};
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 */
break;
}
return TRUE;
}
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;
}
static char *help_asin = {
N_("@FUNCTION=ASIN\n"
"@SYNTAX=ASIN(x)\n"
......@@ -770,99 +697,6 @@ gnumeric_mod (struct FunctionDefinition *i,
return value_int(a%b) ;
}
static char *help_not = {
N_("@FUNCTION=NOT\n"
"@SYNTAX=NOT(number)\n"
"@DESCRIPTION="
"Implements the logical NOT function: the result is TRUE if the "
"number is zero; othewise the result is FALSE.\n\n"
"@SEEALSO=AND, OR")
};
static Value *
gnumeric_not (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
int b;
b = value_get_as_int (argv [0]);
return value_int (!b);
}
static char *help_or = {
N_("@FUNCTION=OR\n"
"@SYNTAX=OR(b1, b2, ...)\n"
"@DESCRIPTION="
"Implements the logical OR function: the result is TRUE if any of the "
"values evaluated to TRUE.\n"
"b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
"If an integer or floating point value is provided zero is considered "
"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, NOT")
};
static int
callback_function_or (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 = 1;
return FALSE;
} else
result->v.v_int = 0;
break;
case VALUE_FLOAT:
if (value->v.v_float != 0.0){
result->v.v_int = 1;
return FALSE;
} else
result->v.v_int = 0;
default:
/* ignore strings */
break;
}
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;
}
static char *help_radians = {
N_("@FUNCTION=RADIANS\n"
"@SYNTAX=RADIANS(x)\n"
......@@ -1981,7 +1815,6 @@ FunctionDefinition math_functions [] = {
{ "abs", "f", "number", &help_abs, NULL, gnumeric_abs },
{ "acos", "f", "number", &help_acos, NULL, gnumeric_acos },
{ "acosh", "f", "number", &help_acosh, NULL, gnumeric_acosh },
{ "and", 0, "", &help_and, gnumeric_and, NULL },
{ "asin", "f", "number", &help_asin, NULL, gnumeric_asin },
{ "asinh", "f", "number", &help_asinh, NULL, gnumeric_asinh },
{ "atan", "f", "number", &help_atan, NULL, gnumeric_atan },
......@@ -2005,9 +1838,7 @@ FunctionDefinition math_functions [] = {
{ "log10", "f", "number", &help_log10, NULL, gnumeric_log10 },
{ "mod", "ff", "num,denom", &help_mod, NULL, gnumeric_mod },
{ "multinomial", 0, "", &help_multinomial, gnumeric_multinomial, NULL },
{ "not", "f", "number", &help_not, NULL, gnumeric_not },
{ "odd" , "f", "number", &help_odd, NULL, gnumeric_odd },
{ "or", 0, "", &help_or, gnumeric_or, NULL },
{ "power", "ff", "x,y", &help_power, NULL, gnumeric_power },
{ "product", 0, "number", &help_product, gnumeric_product, NULL },
{ "quotient" , "ff", "num,den", &help_quotient, NULL, gnumeric_quotient},
......
......@@ -75,6 +75,7 @@ GNUMERIC_BASE_SOURCES = \
fn-date.c \
fn-eng.c \
fn-financial.c \
fn-logical.c \
fn-lookup.c \
fn-math.c \
fn-misc.c \
......
/*
* fn-logical.c: Built in logical functions and functions registration
*
* Authors:
* Miguel de Icaza (miguel@gnu.org)
* Jukka-Pekka Iivonen (iivonen@iki.fi)
*/
#include <config.h>
#include <gnome.h>
#include "math.h"
#include "gnumeric.h"
#include "gnumeric-sheet.h"
#include "utils.h"
#include "func.h"
static char *help_and = {
N_("@FUNCTION=AND\n"
"@SYNTAX=AND(b1, b2, ...)\n"
"@DESCRIPTION=Implements the logical AND function: the result is TRUE "
"if all of the expression evaluates to TRUE, otherwise it returns "
"FALSE.\n"
"b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
"If an integer or floating point value is provided zero is considered "
"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=OR, NOT")
};
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 */
break;
}
return TRUE;
}
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;
}
static char *help_not = {
N_("@FUNCTION=NOT\n"
"@SYNTAX=NOT(number)\n"
"@DESCRIPTION="
"Implements the logical NOT function: the result is TRUE if the "
"number is zero; othewise the result is FALSE.\n\n"
"@SEEALSO=AND, OR")
};
static Value *
gnumeric_not (struct FunctionDefinition *i,
Value *argv [], char **error_string)
{
int b;
b = value_get_as_int (argv [0]);
return value_int (!b);
}
static char *help_or = {
N_("@FUNCTION=OR\n"
"@SYNTAX=OR(b1, b2, ...)\n"
"@DESCRIPTION="
"Implements the logical OR function: the result is TRUE if any of the "
"values evaluated to TRUE.\n"
"b1, trough bN are expressions that should evaluate to TRUE or FALSE. "
"If an integer or floating point value is provided zero is considered "
"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, NOT")
};
static int
callback_function_or (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 = 1;
return FALSE;
} else
result->v.v_int = 0;
break;
case VALUE_FLOAT:
if (value->v.v_float != 0.0){
result->v.v_int = 1;
return FALSE;
} else
result->v.v_int = 0;
default:
/* ignore strings */
break;
}
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;
}
static char *help_if = {
N_("@FUNCTION=IF\n"
"@SYNTAX=IF(condition[,if-true,if-false])\n"
"@DESCRIPTION="
"Use the IF statement to evaluate conditionally other expressions "
"IF evaluates @condition. If @condition returns a non-zero value "
"the result of the IF expression is the @if-true expression, otherwise "
"IF evaluates to the value of @if-false."
"If ommitted if-true defaults to TRUE and if-false to FALSE."
"\n"
"@SEEALSO=")
};
static Value *
gnumeric_if (void *tsheet, GList *expr_node_list,
int eval_col, int eval_row, char **error_string)
{
ExprTree *expr;
Value *value;
int err, ret, args;
/* Type checking */
args = g_list_length (expr_node_list);
if (args < 1 || args > 3){
*error_string = _("Invalid number of arguments");
return NULL;
}
/* Compute the if part */
value = eval_expr (tsheet, (ExprTree *) expr_node_list->data,
eval_col, eval_row, error_string);
if (value == NULL)
return NULL;
/* Choose which expression we will evaluate */
ret = value_get_bool (value, &err);
value_release (value);
if (err)
return NULL;
if (ret){
if (expr_node_list->next)
expr = (ExprTree *) expr_node_list->next->data;
else
return value_int (1);
} else {
if (expr_node_list->next &&
expr_node_list->next->next)
expr = (ExprTree *) expr_node_list->next->next->data;
else
return value_int (0);
}
/* Return the result */
return eval_expr (tsheet, (ExprTree *) expr, eval_col,
eval_row, error_string);
}
FunctionDefinition logical_functions [] = {
{ "and", 0, "", &help_and, gnumeric_and, NULL },
{ "if", 0, "logical_test,value_if_true,value_if_false", &help_if,
gnumeric_if, NULL },
{ "not", "f", "number", &help_not, NULL, gnumeric_not },
{ "or", 0, "", &help_or, gnumeric_or,