Commit f1b88ce2 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

new routine. This looks ugly. We should be able to avoid replicating this


2001-05-25  Jody Goldberg <jgoldberg@home.com>

	* src/value.c (value_diff) : new routine.  This looks ugly.  We should
	  be able to avoid replicating this code.

	* src/cell.c (cell_eval_content) : support iteration.

	* src/format.c (render_number) : make the buffer big enough.
	  The assumtion that mantissa and exp are both maxed should leave
	  enough room for thousand separators.
parent a34cb69d
......@@ -8,21 +8,18 @@ release, and longer term bugs.
Release Critical
----------------
Long term breakage
------------------
- smarter support for unicode characters that do not convert to the
current encoding during XL import. (Vlad is looking at this)
Apply Vlads patch for 0.66
Long term breakage
------------------
- outline mode
: finish implementing optionally putting markers above/left
: implement group/ungroup menu items (with undo, Almer is working on this)
: connect the hide/show menu items
- defining file patterns in plugin spec overrides 'has_probe' flag silently.
(Zbigniew is working on it)
- It is possible to navigate to hidden cols/rows at the start/end of the sheet.
- clean up the range_list codes to differentiate a list of ranges from a list
......@@ -110,10 +107,6 @@ Names :
: nor are spans
- SheetObjects
: Add data member to Class to indicate 'simple' object
types that can be rubber banded directly.
: Add data member to Class to indicate 'invertable' object
types that allow for top below bottom or left after right.
: Add acetate_create virtual to handle shaped objects.
: config dialog for arrows and graphic objects (set colour and arrow dir)
: Other anchor types for sheet objects
......
2001-05-25 Jody Goldberg <jgoldberg@home.com>
* src/value.c (value_diff) : new routine. This looks ugly. We should
be able to avoid replicating this code.
* src/cell.c (cell_eval_content) : support iteration.
* src/format.c (render_number) : make the buffer big enough.
The assumtion that mantissa and exp are both maxed should leave
enough room for thousand separators.
2001-05-25 Jon K Hellan <hellan@acm.org>
* src/workbook-control-gui.c (wbcg_sheet_add): Bugfix: Connect
......
2001-05-25 Jody Goldberg <jgoldberg@home.com>
* src/value.c (value_diff) : new routine. This looks ugly. We should
be able to avoid replicating this code.
* src/cell.c (cell_eval_content) : support iteration.
* src/format.c (render_number) : make the buffer big enough.
The assumtion that mantissa and exp are both maxed should leave
enough room for thousand separators.
2001-05-25 Jon K Hellan <hellan@acm.org>
* src/workbook-control-gui.c (wbcg_sheet_add): Bugfix: Connect
......
2001-05-25 Jody Goldberg <jgoldberg@home.com>
* src/value.c (value_diff) : new routine. This looks ugly. We should
be able to avoid replicating this code.
* src/cell.c (cell_eval_content) : support iteration.
* src/format.c (render_number) : make the buffer big enough.
The assumtion that mantissa and exp are both maxed should leave
enough room for thousand separators.
2001-05-25 Jon K Hellan <hellan@acm.org>
* src/workbook-control-gui.c (wbcg_sheet_add): Bugfix: Connect
......
2001-05-25 Jody Goldberg <jgoldberg@home.com>
* src/value.c (value_diff) : new routine. This looks ugly. We should
be able to avoid replicating this code.
* src/cell.c (cell_eval_content) : support iteration.
* src/format.c (render_number) : make the buffer big enough.
The assumtion that mantissa and exp are both maxed should leave
enough room for thousand separators.
2001-05-25 Jon K Hellan <hellan@acm.org>
* src/workbook-control-gui.c (wbcg_sheet_add): Bugfix: Connect
......
2001-05-25 Jody Goldberg <jgoldberg@home.com>
* src/value.c (value_diff) : new routine. This looks ugly. We should
be able to avoid replicating this code.
* src/cell.c (cell_eval_content) : support iteration.
* src/format.c (render_number) : make the buffer big enough.
The assumtion that mantissa and exp are both maxed should leave
enough room for thousand separators.
2001-05-25 Jon K Hellan <hellan@acm.org>
* src/workbook-control-gui.c (wbcg_sheet_add): Bugfix: Connect
......
......@@ -2060,8 +2060,8 @@ gnumeric_fv (FunctionEvalInfo *ei, Value **argv)
rate = value_get_as_float (argv[0]);
nper = value_get_as_float (argv[1]);
pmt = value_get_as_float (argv[2]);
pv = value_get_as_float (argv[3]);
type = !!value_get_as_int (argv[4]);
pv = (NULL != argv[3]) ? value_get_as_float (argv[3]) : 0.;
type = (NULL != argv[4] && 0 != value_get_as_int (argv[4])) ? 1 : 0;
pvif = calculate_pvif (rate, nper);
fvifa = calculate_fvifa (rate, nper);
......@@ -3007,7 +3007,7 @@ finance_functions_init (void)
def = function_add_args (cat, "euro", "s", "currency",
&help_euro, gnumeric_euro);
def = function_add_args (cat, "fv", "fffff", "rate,nper,pmt,pv,type",
def = function_add_args (cat, "fv", "fff|ff", "rate,nper,pmt,pv,type",
&help_fv, gnumeric_fv);
auto_format_function_result (def, AF_MONETARY);
......
/* vim: set sw=8: */
/*
* cell.c: Cell management of the Gnumeric spreadsheet.
*
* Author:
* Jdy Goldberg 2000 (jgoldberg@home.com)
* Jody Goldberg 2000, 2001 (jgoldberg@home.com)
* Miguel de Icaza 1998, 1999 (miguel@kernel.org)
*/
#include "config.h"
......@@ -149,64 +150,114 @@ cell_destroy (Cell *cell)
gboolean
cell_eval_content (Cell *cell)
{
static Cell *iterating = NULL;
Value *v;
EvalPos pos;
/* This _must_ start as a positive number */
int max_iterate = 100;
if (!cell_has_expr (cell))
return TRUE;
#ifdef DEBUG_EVALUATION
if (dependency_debugging > 1) {
{
ParsePos pp;
char *exprtxt = expr_decode_tree
(cell->base.expression, parse_pos_init_cell (&pp, cell));
printf ("Evaluating %s: %s ->\n", cell_name (cell), exprtxt);
g_free (exprtxt);
char *str = expr_tree_as_string (cell->base.expression,
parse_pos_init_cell (&pp, cell));
printf ("{\nEvaluating(%d) %s: %s;\n", max_iterate, cell_name (cell), str);
g_free (str);
}
#endif
/* This is the bottom of a cycle */
if (cell->base.flags & DEPENDENT_BEING_CALCULATED) {
/* Init to 0 */
if (cell->value->type == VALUE_ERROR) {
value_release (cell->value);
cell->value = value_new_int (0);
} else if (cell->value == NULL)
cell->value = value_new_int (0);
cell->base.flags &= ~DEPENDENT_BEING_CALCULATED;
puts ("bottom iterate");
return FALSE;
/* but not the first bottom */
if (cell->base.flags & CELL_BEING_ITERATED) {
#ifdef DEBUG_EVALUATION
printf ("}; /* already-iterate (%d) */\n", iterating == NULL);
#endif
return iterating == NULL;
}
/* if we are still marked as iterating then make this the last
* time through.
*/
if (iterating == cell) {
#ifdef DEBUG_EVALUATION
puts ("}; /* NO-iterate (1) */");
#endif
return TRUE;
} else if (iterating == NULL) {
cell->base.flags |= CELL_BEING_ITERATED;
iterating = cell;
#ifdef DEBUG_EVALUATION
puts ("}; /* START iterate = TRUE (0) */");
#endif
return FALSE;
} else {
#ifdef DEBUG_EVALUATION
puts ("}; /* other-iterate (0) */");
#endif
return FALSE;
}
}
/* Prepare to calculate */
eval_pos_init_cell (&pos, cell);
iterate :
cell->base.flags |= DEPENDENT_BEING_CALCULATED;
v = eval_expr (&pos, cell->base.expression, EVAL_STRICT);
if (cell->base.flags & DEPENDENT_BEING_CALCULATED)
cell->base.flags &= ~DEPENDENT_BEING_CALCULATED;
else if (max_iterate-- > 0) {
printf ("start iterate %d\n", max_iterate);
goto iterate;
}
iterate :
v = eval_expr (&pos, cell->base.expression, EVAL_STRICT);
if (v == NULL)
v = value_new_error (&pos, "Internal error");
#ifdef DEBUG_EVALUATION
if (dependency_debugging > 1) {
{
char *valtxt = v
? value_get_as_string (v)
: g_strdup ("NULL");
printf ("Evaluating %s: -> %s\n", cell_name (cell), valtxt);
printf ("Evaluation(%d) %s := %s\n", max_iterate, cell_name (cell), valtxt);
g_free (valtxt);
}
#endif
if (v == NULL)
v = value_new_error (&pos, "Internal error");
/* The top of a cycle */
if (cell->base.flags & CELL_BEING_ITERATED) {
cell->base.flags &= ~CELL_BEING_ITERATED;
cell_assign_value (cell, v, NULL);
/* We just completed the last iteration, don't change things */
if (iterating && max_iterate-- > 0) {
/* If we are within bounds make this the last round */
if (value_diff (cell->value, v) < 0.001)
max_iterate = 0;
else {
#ifdef DEBUG_EVALUATION
puts ("/* iterate == NULL */");
#endif
iterating = NULL;
}
value_release (cell->value);
cell->value = v;
#ifdef DEBUG_EVALUATION
puts ("/* LOOP */");
#endif
goto iterate;
}
g_return_val_if_fail (iterating, TRUE);
iterating = NULL;
} else
cell_assign_value (cell, v, NULL);
if (iterating == cell)
iterating = NULL;
#ifdef DEBUG_EVALUATION
printf ("} (%d)\n", iterating == NULL);
#endif
cell->base.flags &= ~DEPENDENT_BEING_CALCULATED;
sheet_redraw_cell (cell);
return TRUE;
return iterating == NULL;
}
/*
......@@ -437,7 +488,7 @@ cell_set_expr_internal (Cell *cell, ExprTree *expr, StyleFormat *opt_fmt)
cell->base.flags |= CELL_HAS_EXPRESSION;
/* Until the value is recomputed, we put in this value. */
cell->value = value_new_error (NULL, gnumeric_err_RECALC);
cell->value = value_new_empty ();
}
/*
......@@ -615,10 +666,10 @@ cell_is_partial_array (Cell const *cell)
* @dynamic_width : Allow format to depend on column width.
*
* TODO :
* There is no reason currently for this to allocate the rendered value as
* seperate entity. However, in the future I'm thinking of referencing them
* akin to strings. We need to do some profiling of how frequently things
* are shared.
* The reason the rendered values are stored seperately from the Cell is
* that in the future only visible cells will be rendered. The render
* will be SheetControl specific to allow for multiple zooms and different
* display resolutions.
*/
void
cell_render_value (Cell *cell, gboolean dynamic_width)
......
......@@ -14,6 +14,9 @@ typedef enum {
/* Is the top left corner of a merged region */
CELL_IS_MERGED = 0x040000,
/* Cell is in the midst of a cyclic calculation */
CELL_BEING_ITERATED = 0x080000,
} CellFlags;
/* Definition of a Gnumeric Cell */
......
......@@ -1141,7 +1141,6 @@ workbook_recalc (Workbook *wb)
(*klass->eval) (dep);
dep->flags &= ~DEPENDENT_NEEDS_RECALC;
} else {
gboolean finished = cell_eval_content (DEP_TO_CELL (dep));
......
......@@ -1141,7 +1141,6 @@ workbook_recalc (Workbook *wb)
(*klass->eval) (dep);
dep->flags &= ~DEPENDENT_NEEDS_RECALC;
} else {
gboolean finished = cell_eval_content (DEP_TO_CELL (dep));
......
......@@ -678,8 +678,8 @@ render_number (GString *result,
double temp;
char thousands_sep;
int group = 0;
char num_buf [DBL_DIG*2 + 1];
char *num = num_buf + DBL_DIG*2;
char num_buf [(DBL_MANT_DIG + DBL_MAX_EXP)*2 + 1];
char *num = num_buf + sizeof(num_buf) - 1;
int digit_count = 0;
if (!beyond_precision)
......
2001-05-25 Jody Goldberg <jgoldberg@home.com>
* fn-financial.c (gnumeric_fv) : Make another few arguments optional.
2001-05-25 Morten Welinder <terra@diku.dk>
* fn-financial.c (gnumeric_pv): Make a few arguments optional.
......
......@@ -2060,8 +2060,8 @@ gnumeric_fv (FunctionEvalInfo *ei, Value **argv)
rate = value_get_as_float (argv[0]);
nper = value_get_as_float (argv[1]);
pmt = value_get_as_float (argv[2]);
pv = value_get_as_float (argv[3]);
type = !!value_get_as_int (argv[4]);
pv = (NULL != argv[3]) ? value_get_as_float (argv[3]) : 0.;
type = (NULL != argv[4] && 0 != value_get_as_int (argv[4])) ? 1 : 0;
pvif = calculate_pvif (rate, nper);
fvifa = calculate_fvifa (rate, nper);
......@@ -3007,7 +3007,7 @@ finance_functions_init (void)
def = function_add_args (cat, "euro", "s", "currency",
&help_euro, gnumeric_euro);
def = function_add_args (cat, "fv", "fffff", "rate,nper,pmt,pv,type",
def = function_add_args (cat, "fv", "fff|ff", "rate,nper,pmt,pv,type",
&help_fv, gnumeric_fv);
auto_format_function_result (def, AF_MONETARY);
......
......@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <errno.h>
#include <math.h>
#include <gnome.h>
Value *
......@@ -734,17 +735,94 @@ compare_float_float (Value const *va, Value const *vb)
}
/**
* value_compare :
* value_diff :
*
* @a : value a
* @b : value b
* @case_sensitive : are string comparisons case sensitive.
*
* Compares two (Value *) and returns one of ValueCompare
* Returns a positive difference between 2 values
*/
double
value_diff (Value const *a, Value const *b)
{
ValueType ta, tb;
/* Handle trivial and double NULL case */
if (a == b)
return 0.;
ta = VALUE_IS_EMPTY (a) ? VALUE_EMPTY : a->type;
tb = VALUE_IS_EMPTY (b) ? VALUE_EMPTY : b->type;
/* string > empty */
if (ta == VALUE_STRING) {
switch (tb) {
/* Strings are > (empty, or number) */
case VALUE_EMPTY :
if (*a->v_str.val->str == '\0')
return 0.;
return DBL_MAX;
/* If both are strings compare as string */
case VALUE_STRING :
{
gint t = strcoll (a->v_str.val->str, b->v_str.val->str);
if (t == 0)
return 0.;
}
case VALUE_INTEGER : case VALUE_FLOAT : case VALUE_BOOLEAN :
default :
return DBL_MAX;
}
} else if (tb == VALUE_STRING) {
switch (ta) {
/* (empty, or number) < String */
case VALUE_EMPTY :
if (*b->v_str.val->str == '\0')
return 0.;
case VALUE_INTEGER : case VALUE_FLOAT : case VALUE_BOOLEAN :
default :
return DBL_MAX;
}
}
/* Booleans > all numbers (Why did excel do this ??) */
if (ta == VALUE_BOOLEAN && (tb == VALUE_INTEGER || tb == VALUE_FLOAT))
return DBL_MAX;
if (tb == VALUE_BOOLEAN && (ta == VALUE_INTEGER || ta == VALUE_FLOAT))
return DBL_MAX;
switch ((ta > tb) ? ta : tb) {
case VALUE_EMPTY: /* Empty Empty compare */
return 0.;
case VALUE_BOOLEAN:
return (compare_bool_bool (a, b) == IS_EQUAL) ? 0. : DBL_MAX;
case VALUE_INTEGER: {
int const ia = value_get_as_int (a);
int const ib = value_get_as_int (b);
return abs (ia-ib);
}
case VALUE_FLOAT: {
double const da = value_get_as_float (a);
double const db = value_get_as_float (b);
return fabs (da-db);
}
default:
return TYPE_MISMATCH;
}
}
/**
* value_compare :
*
* if pos is non null it will perform implict intersection for
* cellranges. if case_sensitive is true, be case sensitive on string
* comparisons.
* @a : value a
* @b : value b
* @case_sensitive : are string comparisons case sensitive.
*/
ValueCompare
value_compare (Value const *a, Value const *b, gboolean case_sensitive)
......
......@@ -99,6 +99,7 @@ Value *value_new_from_string (ValueType t, char const *str);
void value_release (Value *v);
void value_dump (Value const *v);
Value *value_duplicate (Value const *v);
double value_diff (Value const *a, Value const *b);
ValueCompare value_compare (Value const *a, Value const *b,
gboolean case_sensitive);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment