Commit cb43a83a authored by Michael Meeks's avatar Michael Meeks

v/h lookup, cleaned functions...

parent 71a4d158
1999-03-26 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Fix memory leak
(gnumeric_gestep): Cleaned to better arg. model
(bin/oct/dec/hex2...): Cleaned similarly
* src/fn-stat.c (gnumeric_poisson): Cleaned
* src/fn-string.c (string_and_optional_int): Removed.
(gnumeric_left, gnumeric_right, gnumeric_find),
(gnumeric_fixed, gnumeric_dollar, gnumeric_substitute):
Updated to optional argument types.
(gnumeric_clean): Moved from fn-misc.c
* src/fn-misc.c (gnumeric_clean): Moved to fn-string.c
* src/expr.c (cell_ref_make_absolute): Makes a CellRef
absolute.
(eval_funcall): Added range token 'r' for lookup
functions, makes reference absolute so can be used
downstream without trouble.
* src/expr.h: Added range comments
* src/fn-lookup.c: Created
(lookup_simliar, gnumeric_vlookup):
Implements VLOOKUP.
(gnumeric_hlookup): Implements HLOOKUP.
1999-03-25 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-financial.c: dollarde, dollarfr, and npv added.
......
1999-03-26 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Fix memory leak
(gnumeric_gestep): Cleaned to better arg. model
(bin/oct/dec/hex2...): Cleaned similarly
* src/fn-stat.c (gnumeric_poisson): Cleaned
* src/fn-string.c (string_and_optional_int): Removed.
(gnumeric_left, gnumeric_right, gnumeric_find),
(gnumeric_fixed, gnumeric_dollar, gnumeric_substitute):
Updated to optional argument types.
(gnumeric_clean): Moved from fn-misc.c
* src/fn-misc.c (gnumeric_clean): Moved to fn-string.c
* src/expr.c (cell_ref_make_absolute): Makes a CellRef
absolute.
(eval_funcall): Added range token 'r' for lookup
functions, makes reference absolute so can be used
downstream without trouble.
* src/expr.h: Added range comments
* src/fn-lookup.c: Created
(lookup_simliar, gnumeric_vlookup):
Implements VLOOKUP.
(gnumeric_hlookup): Implements HLOOKUP.
1999-03-25 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-financial.c: dollarde, dollarfr, and npv added.
......
1999-03-26 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Fix memory leak
(gnumeric_gestep): Cleaned to better arg. model
(bin/oct/dec/hex2...): Cleaned similarly
* src/fn-stat.c (gnumeric_poisson): Cleaned
* src/fn-string.c (string_and_optional_int): Removed.
(gnumeric_left, gnumeric_right, gnumeric_find),
(gnumeric_fixed, gnumeric_dollar, gnumeric_substitute):
Updated to optional argument types.
(gnumeric_clean): Moved from fn-misc.c
* src/fn-misc.c (gnumeric_clean): Moved to fn-string.c
* src/expr.c (cell_ref_make_absolute): Makes a CellRef
absolute.
(eval_funcall): Added range token 'r' for lookup
functions, makes reference absolute so can be used
downstream without trouble.
* src/expr.h: Added range comments
* src/fn-lookup.c: Created
(lookup_simliar, gnumeric_vlookup):
Implements VLOOKUP.
(gnumeric_hlookup): Implements HLOOKUP.
1999-03-25 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-financial.c: dollarde, dollarfr, and npv added.
......
1999-03-26 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Fix memory leak
(gnumeric_gestep): Cleaned to better arg. model
(bin/oct/dec/hex2...): Cleaned similarly
* src/fn-stat.c (gnumeric_poisson): Cleaned
* src/fn-string.c (string_and_optional_int): Removed.
(gnumeric_left, gnumeric_right, gnumeric_find),
(gnumeric_fixed, gnumeric_dollar, gnumeric_substitute):
Updated to optional argument types.
(gnumeric_clean): Moved from fn-misc.c
* src/fn-misc.c (gnumeric_clean): Moved to fn-string.c
* src/expr.c (cell_ref_make_absolute): Makes a CellRef
absolute.
(eval_funcall): Added range token 'r' for lookup
functions, makes reference absolute so can be used
downstream without trouble.
* src/expr.h: Added range comments
* src/fn-lookup.c: Created
(lookup_simliar, gnumeric_vlookup):
Implements VLOOKUP.
(gnumeric_hlookup): Implements HLOOKUP.
1999-03-25 Jukka-Pekka Iivonen <iivonen@iki.fi>
* src/fn-financial.c: dollarde, dollarfr, and npv added.
......
1999-03-26 Michael Meeks <michael@imaginator.com>
* ms-formula.c: Removed duplicate for fn 0x65
1999-03-24 Thomas Meeks <thomas@imaginator.com>
* ms-formula.c: Added mappings for Address, Area, Hyperlink,
......
......@@ -153,7 +153,6 @@ FORMULA_FUNC_DATA formula_func_data[] =
{ 0x62, "ASIN (", 0, ")", 1, 0 },
{ 0x63, "ACOS (", 0, ")", 1, 0 },
{ 0x64, "0x64 (", 0, ")", 8, 0 },
{ 0x65, "0x65 (", 0, ")", 8, 0 },
{ 0x65, "HLOOKUP (", 0, ")", -1, 0 },
{ 0x66, "VLOOKUP (", 0, ")", -1, 0 },
{ 0x67, "0x67 (", 0, ")", 8, 0 },
......
......@@ -153,7 +153,6 @@ FORMULA_FUNC_DATA formula_func_data[] =
{ 0x62, "ASIN (", 0, ")", 1, 0 },
{ 0x63, "ACOS (", 0, ")", 1, 0 },
{ 0x64, "0x64 (", 0, ")", 8, 0 },
{ 0x65, "0x65 (", 0, ")", 8, 0 },
{ 0x65, "HLOOKUP (", 0, ")", -1, 0 },
{ 0x66, "VLOOKUP (", 0, ")", -1, 0 },
{ 0x67, "0x67 (", 0, ")", 8, 0 },
......
......@@ -40,9 +40,9 @@ static char *help_ = {
* FIXME: In the long term this needs optimising.
**/
static Value *
val_to_base (Value *value, int src_base, int dest_base, int places ,char **error_string)
val_to_base (Value *value, Value *val_places, int src_base, int dest_base, char **error_string)
{
int lp, max, bit, neg ;
int lp, max, bit, neg, places ;
char *p, *ans ;
char *err="\0", buffer[40], *str ;
double v ;
......@@ -52,6 +52,17 @@ val_to_base (Value *value, int src_base, int dest_base, int places ,char **error
return NULL ;
}
if (val_places) {
if (val_places->type != VALUE_INTEGER &&
val_places->type != VALUE_FLOAT) {
*error_string = _("#VALUE!") ;
return NULL ;
}
places = value_get_as_int (val_places) ;
}
else
places = 0 ;
/* printf ("Type: %d\n", value->type) ; */
switch (value->type){
case VALUE_STRING:
......@@ -130,41 +141,6 @@ val_to_base (Value *value, int src_base, int dest_base, int places ,char **error
return value_str(ans) ;
}
static Value *
val_to_base_place (void *sheet, GList *l, int eval_col, int eval_row, char **error_string,
int src_base, int dest_base)
{
int argc = g_list_length (l) ;
Value *ans, *num, *val_places=0 ;
int places = -1 ;
if (argc < 1 || argc > 2 || !l->data) {
*error_string = _("Invalid number of arguments") ;
return NULL ;
}
if (!(num = eval_expr (sheet, l->data, eval_col, eval_row, error_string)))
return NULL ;
l = g_list_next(l) ;
if (l && l->data) {
val_places = eval_expr (sheet, l->data, eval_col, eval_row, error_string) ;
if (!val_places)
return NULL ;
else if (val_places->type != VALUE_INTEGER &&
val_places->type != VALUE_FLOAT) {
*error_string = _("#VALUE!") ;
return NULL ;
}
places = value_get_as_int (val_places) ;
value_release (val_places) ;
}
ans = val_to_base (num, src_base, dest_base, places, error_string) ;
value_release (num) ;
return ans ;
}
static char *help_bin2dec = {
N_("@FUNCTION=BIN2DEC\n"
"@SYNTAX=BIN2DEC(x)\n"
......@@ -180,7 +156,7 @@ static char *help_bin2dec = {
static Value *
gnumeric_bin2dec (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base (argv[0], 2, 10, -1, error_string) ;
return val_to_base (argv[0], NULL, 2, 10, error_string) ;
}
static char *help_bin2oct = {
......@@ -197,10 +173,9 @@ static char *help_bin2oct = {
};
static Value *
gnumeric_bin2oct (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_bin2oct (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
2, 8) ;
return val_to_base (argv[0], argv[1], 2, 8, error_string) ;
}
static char *help_bin2hex = {
......@@ -217,10 +192,9 @@ static char *help_bin2hex = {
};
static Value *
gnumeric_bin2hex (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_bin2hex (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
2, 16) ;
return val_to_base (argv[0], argv[1], 2, 16, error_string) ;
}
static char *help_dec2bin = {
......@@ -237,10 +211,9 @@ static char *help_dec2bin = {
};
static Value *
gnumeric_dec2bin (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_dec2bin (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
10, 2) ;
return val_to_base (argv[0], argv[1], 10, 2, error_string) ;
}
static char *help_dec2oct = {
......@@ -257,10 +230,9 @@ static char *help_dec2oct = {
};
static Value *
gnumeric_dec2oct (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_dec2oct (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
10, 8) ;
return val_to_base (argv[0], argv[1], 10, 8, error_string) ;
}
static char *help_dec2hex = {
......@@ -277,10 +249,9 @@ static char *help_dec2hex = {
};
static Value *
gnumeric_dec2hex (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_dec2hex (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
10, 16) ;
return val_to_base (argv[0], argv[1], 10, 16, error_string) ;
}
static char *help_oct2dec = {
......@@ -298,7 +269,7 @@ static char *help_oct2dec = {
static Value *
gnumeric_oct2dec (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base (argv[0], 8, 10, -1, error_string) ;
return val_to_base (argv[0], NULL, 8, 10, error_string) ;
}
static char *help_oct2bin = {
......@@ -315,10 +286,9 @@ static char *help_oct2bin = {
};
static Value *
gnumeric_oct2bin (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_oct2bin (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
8, 2) ;
return val_to_base (argv[0], argv[1], 8, 2, error_string) ;
}
static char *help_oct2hex = {
......@@ -335,10 +305,9 @@ static char *help_oct2hex = {
};
static Value *
gnumeric_oct2hex (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_oct2hex (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
8, 16) ;
return val_to_base (argv[0], argv[1], 8, 16, error_string) ;
}
static char *help_hex2bin = {
......@@ -355,10 +324,9 @@ static char *help_hex2bin = {
};
static Value *
gnumeric_hex2bin (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_hex2bin (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
16, 2) ;
return val_to_base (argv[0], argv[1], 16, 2, error_string) ;
}
static char *help_hex2oct = {
......@@ -375,10 +343,9 @@ static char *help_hex2oct = {
};
static Value *
gnumeric_hex2oct (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_hex2oct (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
16, 8) ;
return val_to_base (argv[0], argv[1], 16, 8, error_string) ;
}
static char *help_hex2dec = {
......@@ -396,7 +363,7 @@ static char *help_hex2dec = {
static Value *
gnumeric_hex2dec (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base (argv[0], 16, 10, -1, error_string) ;
return val_to_base (argv[0], NULL, 16, 10, error_string) ;
}
static char *help_besselj = {
......@@ -595,6 +562,8 @@ gnumeric_delta (struct FunctionDefinition *i, Value *argv [], char **error_strin
return NULL ;
}
if (!argv[1])
value_release (vy) ;
return value_int (ans) ;
}
......@@ -614,35 +583,17 @@ static char *help_gestep = {
static Value *
gnumeric_gestep (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
gnumeric_gestep (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
int ans = 0 ;
int argc = g_list_length (l) ;
Value *vx, *vy ;
if (argc < 1 || argc > 2 || !l->data) {
*error_string = _("Invalid number of arguments") ;
return NULL ;
}
vx = eval_expr (sheet, l->data, eval_col, eval_row, error_string) ;
if (vx->type != VALUE_INTEGER &&
vx->type != VALUE_FLOAT) {
*error_string = _("#VALUE!") ;
return NULL ;
}
l = g_list_next(l) ;
if (l && l->data) {
vy = eval_expr (sheet, l->data, eval_col, eval_row, error_string) ;
if (vy->type != VALUE_INTEGER &&
vy->type != VALUE_FLOAT) {
*error_string = _("#VALUE!") ;
return NULL ;
}
}
vx = argv[0] ;
if (argv[1])
vy = argv[1] ;
else
vy = value_int (0) ;
switch (vx->type)
{
case VALUE_INTEGER:
......@@ -682,8 +633,8 @@ gnumeric_gestep (void *sheet, GList *l, int eval_col, int eval_row, char **error
return NULL ;
}
value_release (vx) ;
value_release (vy) ;
if (!argv[1])
value_release (vy) ;
return value_int (ans) ;
}
......@@ -692,7 +643,7 @@ static char *help_sqrtpi = {
"@SYNTAX=SQRTPI(x)\n"
"@DESCRIPTION="
"The SQRTPI returns the square root of PI * x. "
"The SQRTPI function returns the square root of PI * x. "
"\n"
"if x < 0 a #NUM! error is returned."
......@@ -715,21 +666,21 @@ FunctionDefinition eng_functions [] = {
{ "bessely", "ff", "xnum,ynum", &help_bessely, NULL, gnumeric_bessely },
{ "besselj", "ff", "xnum,ynum", &help_besselj, NULL, gnumeric_besselj },
{ "bin2dec", "?", "number", &help_bin2dec, NULL, gnumeric_bin2dec },
{ "bin2hex", 0, "xnum,ynum", &help_bin2hex, gnumeric_bin2hex, NULL },
{ "bin2oct", 0, "xnum,ynum", &help_bin2oct, gnumeric_bin2oct, NULL },
{ "dec2bin", 0, "xnum,ynum", &help_dec2bin, gnumeric_dec2bin, NULL },
{ "dec2oct", 0, "xnum,ynum", &help_dec2oct, gnumeric_dec2oct, NULL },
{ "dec2hex", 0, "xnum,ynum", &help_dec2hex, gnumeric_dec2hex, NULL },
{ "bin2hex", "?|f", "xnum,ynum", &help_bin2hex, NULL, gnumeric_bin2hex },
{ "bin2oct", "?|f", "xnum,ynum", &help_bin2oct, NULL, gnumeric_bin2oct },
{ "dec2bin", "?|f", "xnum,ynum", &help_dec2bin, NULL, gnumeric_dec2bin },
{ "dec2oct", "?|f", "xnum,ynum", &help_dec2oct, NULL, gnumeric_dec2oct },
{ "dec2hex", "?|f", "xnum,ynum", &help_dec2hex, NULL, gnumeric_dec2hex },
{ "delta", "f|f", "xnum,ynum", &help_delta, NULL, gnumeric_delta },
{ "erf", "f|f", "lower,upper", &help_erf, NULL, gnumeric_erf },
{ "erfc", "f", "number", &help_erfc, NULL, gnumeric_erfc },
{ "gestep", 0, "xnum,ynum", &help_gestep, gnumeric_gestep, NULL },
{ "hex2bin", 0, "xnum,ynum", &help_hex2bin, gnumeric_hex2bin, NULL },
{ "gestep", "f|f", "xnum,ynum", &help_gestep, NULL, gnumeric_gestep },
{ "hex2bin", "?|f", "xnum,ynum", &help_hex2bin, NULL, gnumeric_hex2bin },
{ "hex2dec", "?", "number", &help_hex2dec, NULL, gnumeric_hex2dec },
{ "hex2oct", 0, "xnum,ynum", &help_hex2oct, gnumeric_hex2oct, NULL },
{ "oct2bin", 0, "xnum,ynum", &help_oct2bin, gnumeric_oct2bin, NULL },
{ "hex2oct", "?|f", "xnum,ynum", &help_hex2oct, NULL, gnumeric_hex2oct },
{ "oct2bin", "?|f", "xnum,ynum", &help_oct2bin, NULL, gnumeric_oct2bin },
{ "oct2dec", "?", "number", &help_oct2dec, NULL, gnumeric_oct2dec },
{ "oct2hex", 0, "xnum,ynum", &help_oct2hex, gnumeric_oct2hex, NULL },
{ "oct2hex", "?|f", "xnum,ynum", &help_oct2hex, NULL, gnumeric_oct2hex },
{ "sqrtpi", "f", "number", &help_sqrtpi, NULL, gnumeric_sqrtpi },
/* besseli */
/* besselk */
......@@ -740,5 +691,4 @@ FunctionDefinition eng_functions [] = {
/*
* Mode, Median: Use large hash table :-)
*
* Engineering: Bessel functions: use C fns: j0, y0 etc.
*/
/*
* fn-lookup.c: Built in lookup functions and functions registration
*
* Author:
* Michael Meeks <michael@imaginator.com>
*/
#include <config.h>
#include <gnome.h>
#include "math.h"
#include "numbers.h"
#include "gnumeric.h"
#include "gnumeric-sheet.h"
#include "utils.h"
#include "func.h"
static char *help_vlookup = {
N_("@FUNCTION=VLOOKUP\n"
"@SYNTAX=VLOOKUP(value,range,column,[approximate])\n"
"@DESCRIPTION="
"The VLOOKUP function finds the row in range that has a first column similar to value. "
"if approximate is not true it finds the row with an exact equivilance. "
"if approximate is true, then the values must be sorted in order of ascending value for "
"correct function; in this case it finds the row with value less than value. "
"it returns the value in the row found at a 1 based offset in column columns into the range."
"\n"
"Returns #NUM! if column < 0."
"Returns #REF! if column falls outside range."
"\n"
"@SEEALSO=HLOOKUP")
};
static int
lookup_similar (Value *data, Value *templ, Value *next_largest, int approx)
{
int ans ;
g_return_val_if_fail (data != NULL, 0) ;
g_return_val_if_fail (templ != NULL, 0) ;
switch (templ->type)
{
case VALUE_INTEGER:
case VALUE_FLOAT:
{
float_t a,b ;
a = value_get_as_double (data) ;
b = value_get_as_double (templ) ;
/* printf ("Num: %f %f %f\n", a, b, next_largest?value_get_as_double(next_largest):9999.0) ; */
if (a == b)
return 1 ;
else if (approx && a < b) {
if (!next_largest)
return -1 ;
else if (value_get_as_double(next_largest) <= a)
return -1 ;
}
return 0 ;
break ;
}
case VALUE_STRING:
default:
{
char *a, *b ;
a = value_string (data) ;
b = value_string (templ) ;
if (approx)
{
ans = strcasecmp (a,b) ;
if (approx && ans < 0) {
if (next_largest) {
char *c = value_string (next_largest) ;
int cmp = strcasecmp(a,c) ;
g_free (c) ;
if (cmp >= 0)
return -1 ;
}
else
return -1 ;
}
}
else
ans = strcmp (a,b) ;
g_free (a) ;
g_free (b) ;
return (ans==0) ;
break ;
}
}
return 0 ;
}
static Value *
gnumeric_vlookup (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
CellRef *a, *b ;
Value *next_largest = NULL ;
int height, lp, approx, col_idx, next_largest_row=0 ;
a = &argv[1]->v.cell_range.cell_a ;
b = &argv[1]->v.cell_range.cell_b ;
g_return_val_if_fail (a->sheet != NULL, NULL) ;
g_return_val_if_fail (a->sheet == b->sheet, NULL) ;
g_return_val_if_fail (!a->col_relative, NULL) ;
g_return_val_if_fail (!b->col_relative, NULL) ;
g_return_val_if_fail (!a->row_relative, NULL) ;
g_return_val_if_fail (!b->row_relative, NULL) ;
g_return_val_if_fail (a->col<=b->col, NULL) ;
g_return_val_if_fail (a->row<=b->row, NULL) ;
col_idx = value_get_as_int (argv[2]) ;
if (col_idx<=0) {
*error_string = _("#NUM!") ;
return NULL ;
}
if (col_idx>b->col-a->col+1) {
*error_string = _("#REF!") ;
return NULL ;
}
if (argv[3]) {
int err ;
approx = value_get_bool (argv[3], &err) ;
if (err) {
*error_string = _("#VALUE!") ;
return NULL ;
}
}
else
approx = 1 ;
height = b->row - a->row + 1 ;
for (lp=0;lp<height;lp++) {
int compare ;
Cell *cell = sheet_cell_get (a->sheet, a->col, a->row+lp) ;
g_return_val_if_fail (cell != NULL, NULL) ;
g_return_val_if_fail (cell->value != NULL, NULL) ;
compare = lookup_similar (cell->value, argv[0], next_largest, approx) ;
/* printf ("Compare '%s' with '%s' : %d (%d)\n", value_string(cell->value), value_string(argv[0]), compare, approx) ; */
if (compare == 1) {
Cell *cell = sheet_cell_get (a->sheet, a->col+col_idx-1, a->row+lp) ;
g_return_val_if_fail (cell != NULL, NULL) ;
g_return_val_if_fail (cell->value != NULL, NULL) ;
return value_duplicate (cell->value) ;
}
if (compare < 0) {
next_largest = cell->value ;
next_largest_row = lp ;
}