Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
GNOME
gnumeric
Commits
e7977dca
Commit
e7977dca
authored
Aug 07, 1998
by
Arturo Espinosa
Browse files
oooooopsie
parent
c875c8db
Changes
3
Hide whitespace changes
Inline
Side-by-side
plugins/fn-math/functions.c
0 → 100644
View file @
e7977dca
/*
* func.c: Built in mathematical functions and functions registration
* (C) 1998 The Free Software Foundation
*
* 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
);
static
Value
*
gnumeric_abs
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
fabs
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_acos
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
((
t
<
-
1
.
0
)
||
(
t
>
1
.
0
)){
*
error_string
=
_
(
"acos - domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
acos
(
t
);
return
v
;
}
static
Value
*
gnumeric_acosh
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
(
t
<
1
.
0
){
*
error_string
=
_
(
"acosh - domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
acosh
(
t
);
return
v
;
}
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
;
}
static
char
*
help_and
=
{
N_
(
"<function>AND</function>"
"<syntax>AND(b1, b2, ...)</syntax>n"
"<description>Implements the logical AND function: the result is TRUE "
"if all of the expression evaluate to TRUE, otherwise it returns "
"FALSE.<p>"
"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.<p>"
"If the values contain strings or empty cells those values are "
"ignored. If no logical values are provided, then the error '#VALUE!' "
"is returned. "
"</description>"
"<seealso>OR</seealso>"
)
};
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
Value
*
gnumeric_asin
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
((
t
<
-
1
.
0
)
||
(
t
>
1
.
0
)){
*
error_string
=
_
(
"asin - domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
asin
(
t
);
return
v
;
}
static
Value
*
gnumeric_asinh
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
asinh
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_atan
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
atan
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_atanh
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
((
t
<=
-
1
.
0
)
||
(
t
>=
1
.
0
)){
*
error_string
=
_
(
"atanh: domain error"
);
return
NULL
;
}
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
atanh
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_atan2
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
atan2
(
value_get_as_double
(
argv
[
0
]),
value_get_as_double
(
argv
[
1
]));
return
v
;
}
static
char
*
help_average
=
{
N_
(
"<function>AVERAGE</function>"
"<syntax>AVERAGE(value1, value2,...)</syntax>"
"<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."
"</description>"
"<seealso>SUM, COUNT</seealso>"
)
};
static
Value
*
gnumeric_average
(
void
*
tsheet
,
GList
*
expr_node_list
,
int
eval_col
,
int
eval_row
,
char
**
error_string
)
{
Value
*
result
;
Value
*
sum
,
*
count
;
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
);
if
(
!
count
){
value_release
(
sum
);
return
NULL
;
}
result
=
g_new
(
Value
,
1
);
result
->
type
=
VALUE_FLOAT
;
result
->
v
.
v_float
=
sum
->
v
.
v_float
/
count
->
v
.
v_int
;
value_release
(
count
);
value_release
(
sum
);
return
result
;
}
static
Value
*
gnumeric_ceil
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
ceil
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_bin2dec
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
value
;
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
;
while
(
*
p
){
if
(
!
(
*
p
==
'0'
||
*
p
==
'1'
)){
*
error_string
=
"#NUM!"
;
return
NULL
;
}
/* FIXME: implement */
result
=
*
p
;
}
break
;
default:
*
error_string
=
"#NUM!"
;
return
NULL
;
}
value
=
g_new
(
Value
,
1
);
value
->
type
=
VALUE_INTEGER
;
value
->
v
.
v_int
=
result
;
return
value
;
}
static
Value
*
gnumeric_cos
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
cos
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_cosh
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
cos
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
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
;
}
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
;
}
static
Value
*
gnumeric_degrees
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
(
value_get_as_double
(
argv
[
0
])
*
180
.
0
)
/
M_PI
;
return
v
;
}
static
Value
*
gnumeric_exp
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
exp
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_floor
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
floor
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_int
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
t
>
0
.
0
?
floor
(
t
)
:
ceil
(
t
);
return
v
;
}
static
Value
*
gnumeric_log
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
(
t
<
0
.
0
){
*
error_string
=
_
(
"log: domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
log
(
t
);
return
v
;
}
static
Value
*
gnumeric_log2
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
(
t
<
0
.
0
){
*
error_string
=
_
(
"log2: domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
log
(
t
)
/
M_LN2
;
return
v
;
}
static
Value
*
gnumeric_log10
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
;
float_t
t
;
t
=
value_get_as_double
(
argv
[
0
]);
if
(
t
<
0
.
0
){
*
error_string
=
_
(
"log10: domain error"
);
return
NULL
;
}
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
log10
(
t
);
return
v
;
}
static
char
*
help_or
=
{
N_
(
"<function>OR</function>"
"<syntax>OR(b1, b2, ...)</syntax>"
"<description>"
"Implements the logical OR function: the result is TRUE if any of the"
"values evaluated to TRUE.<p>"
"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.<p>"
"If the values contain strings or empty cells those values are "
"ignored. If no logical values are provided, then the error '#VALUE!'"
"is returned."
"</description>"
"<seealso>AND</seealso>"
)
};
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
==
1
){
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 */
}
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
Value
*
gnumeric_radians
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
(
value_get_as_double
(
argv
[
0
])
*
M_PI
)
/
180
;
return
v
;
}
static
Value
*
gnumeric_sin
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
sin
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_sinh
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
sinh
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
int
callback_function_sum
(
Sheet
*
sheet
,
Value
*
value
,
char
**
error_string
,
void
*
closure
)
{
Value
*
result
=
(
Value
*
)
closure
;
switch
(
value
->
type
){
case
VALUE_INTEGER
:
result
->
v
.
v_float
+=
value
->
v
.
v_int
;
break
;
case
VALUE_FLOAT
:
result
->
v
.
v_float
+=
value
->
v
.
v_float
;
break
;
case
VALUE_STRING
:
result
->
v
.
v_float
+=
atof
(
value
->
v
.
str
->
str
);
break
;
default:
g_warning
(
"Unknown VALUE type in callback_function_sum"
);
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
);
result
->
type
=
VALUE_FLOAT
;
result
->
v
.
v_float
=
0
.
0
;
function_iterate_argument_values
(
sheet
,
callback_function_sum
,
result
,
expr_node_list
,
eval_col
,
eval_row
,
error_string
);
return
result
;
}
static
Value
*
gnumeric_tan
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
tan
(
value_get_as_double
(
argv
[
0
]));
return
v
;
}
static
Value
*
gnumeric_tanh
(
Value
*
argv
[],
char
**
error_string
)
{
Value
*
v
=
g_new
(
Value
,
1
);
v
->
type
=
VALUE_FLOAT
;
v
->
v
.
v_float
=
tanh
(
value_get_as_double
(
argv
[
0
]));