Commit 65afc9f4 authored by Michael Meeks's avatar Michael Meeks
Browse files

GESTEP, SQRTPI, format conversion functions...

parent 7ea3ce64
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Implemented
* src/fn-eng.c (val_to_base, val_to_base_place),
(bin/oct/dec/hex 2 bin/oct/dec/hex):
Implemented - pending fixes to number storage.
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta, gnumeric_sqrtpi),
(gnumeric_gestep): Implemented
* src/fn-math.c (sqrt): Implemented.
1999-03-13 Michael Meeks <michael@imaginator.com>
......@@ -46,7 +55,7 @@
* src/fn-stat.c (gnumeric_expondist, gnumeric_geomean):
Implemented.
1999-03-10 Vladimir Vuksan (vuksan@veus.hr)
1999-03-10 Vladimir Vuksan <vuksan@veus.hr>
* src/fn-financial.c: New file.
......
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Implemented
* src/fn-eng.c (val_to_base, val_to_base_place),
(bin/oct/dec/hex 2 bin/oct/dec/hex):
Implemented - pending fixes to number storage.
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta, gnumeric_sqrtpi),
(gnumeric_gestep): Implemented
* src/fn-math.c (sqrt): Implemented.
1999-03-13 Michael Meeks <michael@imaginator.com>
......@@ -46,7 +55,7 @@
* src/fn-stat.c (gnumeric_expondist, gnumeric_geomean):
Implemented.
1999-03-10 Vladimir Vuksan (vuksan@veus.hr)
1999-03-10 Vladimir Vuksan <vuksan@veus.hr>
* src/fn-financial.c: New file.
......
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Implemented
* src/fn-eng.c (val_to_base, val_to_base_place),
(bin/oct/dec/hex 2 bin/oct/dec/hex):
Implemented - pending fixes to number storage.
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta, gnumeric_sqrtpi),
(gnumeric_gestep): Implemented
* src/fn-math.c (sqrt): Implemented.
1999-03-13 Michael Meeks <michael@imaginator.com>
......@@ -46,7 +55,7 @@
* src/fn-stat.c (gnumeric_expondist, gnumeric_geomean):
Implemented.
1999-03-10 Vladimir Vuksan (vuksan@veus.hr)
1999-03-10 Vladimir Vuksan <vuksan@veus.hr>
* src/fn-financial.c: New file.
......
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta): Implemented
* src/fn-eng.c (val_to_base, val_to_base_place),
(bin/oct/dec/hex 2 bin/oct/dec/hex):
Implemented - pending fixes to number storage.
1999-03-13 Michael Meeks <michael@imaginator.com>
* src/fn-eng.c (gnumeric_delta, gnumeric_sqrtpi),
(gnumeric_gestep): Implemented
* src/fn-math.c (sqrt): Implemented.
1999-03-13 Michael Meeks <michael@imaginator.com>
......@@ -46,7 +55,7 @@
* src/fn-stat.c (gnumeric_expondist, gnumeric_geomean):
Implemented.
1999-03-10 Vladimir Vuksan (vuksan@veus.hr)
1999-03-10 Vladimir Vuksan <vuksan@veus.hr>
* src/fn-financial.c: New file.
......
......@@ -36,6 +36,130 @@ static char *help_ = {
#endif
/**
* 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)
{
int lp, max, bit, neg ;
char *p, *ans ;
char *err="\0", buffer[40], *str ;
gint32 v ;
if (src_base<=1 || dest_base<=1) {
*error_string = _("Base error") ;
return NULL ;
}
/* printf ("Type: %d\n", value->type) ; */
switch (value->type){
case VALUE_STRING:
str = value->v.str->str ;
break ;
case VALUE_INTEGER:
snprintf (buffer, sizeof (buffer)-1, "%d", value->v.v_int);
str = buffer ;
break;
case VALUE_FLOAT:
snprintf (buffer, sizeof (buffer)-1, "%8.0f", value->v.v_float);
str = buffer ;
break;
default:
*error_string = _("#NUM!") ;
return NULL ;
}
v = strtol (str, &err, src_base) ;
if (*err) {
*error_string = _("#NUM!") ;
return NULL ;
}
if ((float_t)v >= (pow (src_base, 10)/2.0)) /* N's complement */
v = -v ;
if (dest_base == 10)
return (value_int(v)) ;
if (v<0) {
neg = 1 ;
v = -v+1 ;
}
else
neg = 0 ;
if (v==0)
max = 1 ;
else
max = (int)(log(v)/log(dest_base)) + 1 ;
if (places>max)
max = places ;
if (v<0 || max > 15) { /* Think '-0' */
*error_string = _("Unimplemented") ;
return NULL ;
}
ans = buffer ;
p = &ans[max-1] ;
for (lp = 0; lp < max; lp++) {
bit = v % dest_base ;
v = v / dest_base ;
if (neg)
bit = dest_base-bit ;
if (bit>=0 && bit <= 9)
*p-- = '0'+bit ;
else
*p-- = 'A'+bit-10 ;
if (places>0 && lp>=places) {
if (v == 0)
break ;
else {
*error_string = _("#NUM!") ;
return NULL ;
}
}
}
ans[max] = '\0' ;
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"
......@@ -44,8 +168,6 @@ static char *help_bin2dec = {
"The BIN2DEC function converts a binary number "
"in string or number to its decimal equivalent."
"\n"
"Performing this function on a string or empty cell simply does nothing."
"\n"
"@SEEALSO=DEC2BIN")
};
......@@ -53,37 +175,223 @@ static char *help_bin2dec = {
static Value *
gnumeric_bin2dec (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
int result, v, n, bit;
char *p;
return val_to_base (argv[0], 2, 10, -1, error_string) ;
}
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;
for (;*p; p++){
if (!(*p == '0' || *p == '1')){
*error_string = "#NUM!";
return NULL;
}
result = result << 1 | (*p - '0');
}
break;
default:
*error_string = "#NUM!";
return NULL;
}
return value_int (result);
static char *help_bin2oct = {
N_("@FUNCTION=BIN2OCT\n"
"@SYNTAX=BIN2OCT(number,places)\n"
"@DESCRIPTION="
"The BIN2OCT function converts a binary number to an octal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=OCT2BIN")
};
static Value *
gnumeric_bin2oct (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
2, 8) ;
}
static char *help_bin2hex = {
N_("@FUNCTION=BIN2HEX\n"
"@SYNTAX=BIN2HEX(number,places)\n"
"@DESCRIPTION="
"The BIN2HEX function converts a binary number to a hexadecimal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=HEX2BIN")
};
static Value *
gnumeric_bin2hex (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
2, 16) ;
}
static char *help_dec2bin = {
N_("@FUNCTION=DEC2BIN\n"
"@SYNTAX=DEC2BIN(number,places)\n"
"@DESCRIPTION="
"The DEC2BIN function converts a binary number to an octal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=BIN2DEC")
};
static Value *
gnumeric_dec2bin (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
10, 2) ;
}
static char *help_dec2oct = {
N_("@FUNCTION=DEC2OCT\n"
"@SYNTAX=DEC2OCT(number,places)\n"
"@DESCRIPTION="
"The DEC2OCT function converts a binary number to an octal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=OCT2DEC")
};
static Value *
gnumeric_dec2oct (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
10, 8) ;
}
static char *help_dec2hex = {
N_("@FUNCTION=DEC2HEX\n"
"@SYNTAX=DEC2HEX(number,places)\n"
"@DESCRIPTION="
"The DEC2HEX function converts a binary number to an octal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=HEX2DEC")
};
static Value *
gnumeric_dec2hex (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
10, 16) ;
}
static char *help_oct2dec = {
N_("@FUNCTION=OCT2DEC\n"
"@SYNTAX=OCT2DEC(x)\n"
"@DESCRIPTION="
"The OCT2DEC function converts an octal number "
"in a string or number to its decimal equivalent."
"\n"
"\n"
"@SEEALSO=DEC2OCT")
};
static Value *
gnumeric_oct2dec (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base (argv[0], 8, 10, -1, error_string) ;
}
static char *help_oct2bin = {
N_("@FUNCTION=OCT2BIN\n"
"@SYNTAX=OCT2BIN(number,places)\n"
"@DESCRIPTION="
"The OCT2BIN function converts a binary number to a hexadecimal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=BIN2OCT")
};
static Value *
gnumeric_oct2bin (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
8, 2) ;
}
static char *help_oct2hex = {
N_("@FUNCTION=OCT2HEX\n"
"@SYNTAX=OCT2HEX(number,places)\n"
"@DESCRIPTION="
"The OCT2HEX function converts a binary number to a hexadecimal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=OCT2HEX")
};
static Value *
gnumeric_oct2hex (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
8, 16) ;
}
static char *help_hex2bin = {
N_("@FUNCTION=HEX2BIN\n"
"@SYNTAX=HEX2BIN(number,places)\n"
"@DESCRIPTION="
"The HEX2BIN function converts a binary number to a hexadecimal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=BIN2HEX")
};
static Value *
gnumeric_hex2bin (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
16, 2) ;
}
static char *help_hex2oct = {
N_("@FUNCTION=HEX2OCT\n"
"@SYNTAX=HEX2OCT(number,places)\n"
"@DESCRIPTION="
"The HEX2OCT function converts a binary number to a hexadecimal number."
"places is an optional field, specifying to zero pad to that number of spaces."
"\n"
"if places is too small or negative #NUM! error is returned."
"\n"
"@SEEALSO=BIN2HEX")
};
static Value *
gnumeric_hex2oct (void *sheet, GList *l, int eval_col, int eval_row, char **error_string)
{
return val_to_base_place (sheet, l, eval_col, eval_row, error_string,
16, 8) ;
}
static char *help_hex2dec = {
N_("@FUNCTION=HEX2DEC\n"
"@SYNTAX=HEX2DEC(x)\n"
"@DESCRIPTION="
"The HEX2DEC function converts a binary number "
"in string or number to its decimal equivalent."
"\n"
"\n"
"@SEEALSO=DEC2HEX")
};
static Value *
gnumeric_hex2dec (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
return val_to_base (argv[0], 16, 10, -1, error_string) ;
}
static char *help_besselj = {
......@@ -233,11 +541,6 @@ static Value *
gnumeric_erfc (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
float_t x ;
if (argv[0]->type != VALUE_INTEGER &&
argv[0]->type != VALUE_FLOAT) {
*error_string = _("#VALUE!") ;
return NULL ;
}
if ((x=value_get_as_double(argv[0]))<0) {
*error_string = _("#NUM!") ;
return NULL ;
......@@ -334,16 +637,141 @@ gnumeric_delta (void *sheet, GList *l, int eval_col, int eval_row, char **error_
return value_int (ans) ;
}
static char *help_gestep = {
N_("@FUNCTION=GESTEP\n"
"@SYNTAX=GESTEP(x,y)\n"
"@DESCRIPTION="
"The GESTEP function test for if x is >= y, returning 1 if it is so, and 0 otherwise "
"y is optional, and defaults to 0"
"\n"
"if either argument is non-numeric returns a #VALUE! error"
"\n"
"@SEEALSO=DELTA")
};
static Value *
gnumeric_gestep (void *sheet, GList *l, int eval_col, int eval_row, 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 ;
}
}
else
vy = value_int (0) ;
switch (vx->type)
{
case VALUE_INTEGER:
switch (vy->type)
{
case VALUE_INTEGER:
if (vx->v.v_int >= vy->v.v_int)
ans = 1 ;
break ;
case VALUE_FLOAT:
if (vy->v.v_float < (float_t)vx->v.v_int)
ans = 1 ;
break ;
default:
*error_string = _("Impossible") ;
return NULL ;
}
break ;
case VALUE_FLOAT:
switch (vy->type)
{
case VALUE_INTEGER:
if (vx->v.v_float >= (float_t)vy->v.v_int)
ans = 1 ;
break ;
case VALUE_FLOAT:
if (vy->v.v_float < vx->v.v_float)
ans = 1 ;
break ;
default:
*error_string = _("Impossible") ;
return NULL ;
}
break ;
default:
*error_string = _("Impossible") ;
return NULL ;
}
value_release (vx) ;
value_release (vy) ;
return value_int (ans) ;
}
static char *help_sqrtpi = {
N_("@FUNCTION=SQRTPI\n"
"@SYNTAX=SQRTPI(x)\n"
"@DESCRIPTION="
"The SQRTPI returns the square root of PI * x. "
"\n"
"if x < 0 a #NUM! error is returned."
"\n"
"@SEEALSO=ERF")
};
static Value *
gnumeric_sqrtpi (struct FunctionDefinition *i, Value *argv [], char **error_string)
{
float_t x ;
if ((x=value_get_as_double(argv[0]))<0) {
*error_string = _("#NUM!") ;
return NULL ;
}
return value_float (sqrt (M_PI*x)) ;
}
FunctionDefinition eng_functions [] = {