Commit c286b53c authored by Morten Welinder's avatar Morten Welinder

Recalculation improvements.

parent 77d7fe18
1999-06-02 Morten Welinder <terra@diku.dk>
* samples/datefuns.xls: New file from Nick Lamb.
* src/eval.c (workbook_recalc): If a cell has already been
computed, do not redo it. This should speed up things.
(cell_queue_recalc): Delete useless cast.
(cell_unqueue_from_recalc): Ditto.
(cell_queue_recalc_list): Ditto.
(cell_queue_recalc_list): Extra parameter freelist controls
whether list is freed. All callers changed.
(workbook_recalc_all): Use cell_queue_recalc_list.
* src/dialog-goal-seek.c (goal_seek_eval): Properly reevaluate.
* src/expr.c (eval_expr): Only evaluate references cells when they
are queued for recalculation.
* src/func.c (iterate_cellrange_callback): Ditto.
* src/fn-math.c (gnumeric_lcm): Remove useless (Sheet *) cast.
* src/fn-information.c (gnumeric_countblank): Ditto.
* src/fn-database.c (find_column_of_field): Ditto.
(parse_database_criteria): Ditto.
(find_cells_that_match): Ditto.
* src/cell.c (cell_comment_realize): Ditto.
1999-06-02 Michael Meeks <michael@edenproject.org>
* src/expr.c (do_expr_decode_tree): Added ARRAY support.
......
1999-06-02 Morten Welinder <terra@diku.dk>
* samples/datefuns.xls: New file from Nick Lamb.
* src/eval.c (workbook_recalc): If a cell has already been
computed, do not redo it. This should speed up things.
(cell_queue_recalc): Delete useless cast.
(cell_unqueue_from_recalc): Ditto.
(cell_queue_recalc_list): Ditto.
(cell_queue_recalc_list): Extra parameter freelist controls
whether list is freed. All callers changed.
(workbook_recalc_all): Use cell_queue_recalc_list.
* src/dialog-goal-seek.c (goal_seek_eval): Properly reevaluate.
* src/expr.c (eval_expr): Only evaluate references cells when they
are queued for recalculation.
* src/func.c (iterate_cellrange_callback): Ditto.
* src/fn-math.c (gnumeric_lcm): Remove useless (Sheet *) cast.
* src/fn-information.c (gnumeric_countblank): Ditto.
* src/fn-database.c (find_column_of_field): Ditto.
(parse_database_criteria): Ditto.
(find_cells_that_match): Ditto.
* src/cell.c (cell_comment_realize): Ditto.
1999-06-02 Michael Meeks <michael@edenproject.org>
* src/expr.c (do_expr_decode_tree): Added ARRAY support.
......
1999-06-02 Morten Welinder <terra@diku.dk>
* samples/datefuns.xls: New file from Nick Lamb.
* src/eval.c (workbook_recalc): If a cell has already been
computed, do not redo it. This should speed up things.
(cell_queue_recalc): Delete useless cast.
(cell_unqueue_from_recalc): Ditto.
(cell_queue_recalc_list): Ditto.
(cell_queue_recalc_list): Extra parameter freelist controls
whether list is freed. All callers changed.
(workbook_recalc_all): Use cell_queue_recalc_list.
* src/dialog-goal-seek.c (goal_seek_eval): Properly reevaluate.
* src/expr.c (eval_expr): Only evaluate references cells when they
are queued for recalculation.
* src/func.c (iterate_cellrange_callback): Ditto.
* src/fn-math.c (gnumeric_lcm): Remove useless (Sheet *) cast.
* src/fn-information.c (gnumeric_countblank): Ditto.
* src/fn-database.c (find_column_of_field): Ditto.
(parse_database_criteria): Ditto.
(find_cells_that_match): Ditto.
* src/cell.c (cell_comment_realize): Ditto.
1999-06-02 Michael Meeks <michael@edenproject.org>
* src/expr.c (do_expr_decode_tree): Added ARRAY support.
......
1999-06-02 Morten Welinder <terra@diku.dk>
* samples/datefuns.xls: New file from Nick Lamb.
* src/eval.c (workbook_recalc): If a cell has already been
computed, do not redo it. This should speed up things.
(cell_queue_recalc): Delete useless cast.
(cell_unqueue_from_recalc): Ditto.
(cell_queue_recalc_list): Ditto.
(cell_queue_recalc_list): Extra parameter freelist controls
whether list is freed. All callers changed.
(workbook_recalc_all): Use cell_queue_recalc_list.
* src/dialog-goal-seek.c (goal_seek_eval): Properly reevaluate.
* src/expr.c (eval_expr): Only evaluate references cells when they
are queued for recalculation.
* src/func.c (iterate_cellrange_callback): Ditto.
* src/fn-math.c (gnumeric_lcm): Remove useless (Sheet *) cast.
* src/fn-information.c (gnumeric_countblank): Ditto.
* src/fn-database.c (find_column_of_field): Ditto.
(parse_database_criteria): Ditto.
(find_cells_that_match): Ditto.
* src/cell.c (cell_comment_realize): Ditto.
1999-06-02 Michael Meeks <michael@edenproject.org>
* src/expr.c (do_expr_decode_tree): Added ARRAY support.
......
......@@ -123,7 +123,7 @@ find_column_of_field(Value *database, Value *field)
if (field->type != VALUE_STRING)
return -1;
sheet = (Sheet *) database->v.cell_range.cell_a.sheet;
sheet = database->v.cell_range.cell_a.sheet;
field_name = value_get_as_string (field);
column = -1;
......@@ -221,7 +221,7 @@ parse_database_criteria(Value *database, Value *criteria)
int b_col, b_row, e_col, e_row;
int field_ind;
sheet = (Sheet *) database->v.cell_range.cell_a.sheet;
sheet = database->v.cell_range.cell_a.sheet;
b_col = criteria->v.cell_range.cell_a.col;
b_row = criteria->v.cell_range.cell_a.row;
e_col = criteria->v.cell_range.cell_b.col;
......@@ -278,7 +278,7 @@ find_cells_that_match(Value *database, int field, GSList *criterias)
Sheet *sheet;
GSList *current, *conditions, *cells;
int row, first_row, last_row, add_flag;
sheet = (Sheet *) database->v.cell_range.cell_a.sheet;
sheet = database->v.cell_range.cell_a.sheet;
last_row = database->v.cell_range.cell_b.row;
cells = NULL;
first_row = database->v.cell_range.cell_a.row + 1;
......
......@@ -36,7 +36,7 @@ gnumeric_countblank (struct FunctionDefinition *n,
int count;
range = argv[0];
sheet = (Sheet *) range->v.cell_range.cell_a.sheet;
sheet = range->v.cell_range.cell_a.sheet;
col_a = range->v.cell_range.cell_a.col;
col_b = range->v.cell_range.cell_b.col;
row_a = range->v.cell_range.cell_a.row;
......
......@@ -208,11 +208,10 @@ callback_function_lcm (Sheet *sheet, Value *value,
}
static Value *
gnumeric_lcm (Sheet *tsheet, GList *expr_node_list,
gnumeric_lcm (Sheet *sheet, 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;
......
......@@ -298,7 +298,7 @@ cell_comment_realize (Cell *cell)
g_return_if_fail (cell->comment != NULL);
sheet_cell_comment_link (cell);
for (l = ((Sheet *)cell->sheet)->sheet_views; l; l = l->next){
for (l = cell->sheet->sheet_views; l; l = l->next){
SheetView *sheet_view = SHEET_VIEW (l->data);
GnomeCanvasItem *o;
......@@ -683,7 +683,7 @@ cell_content_changed (Cell *cell)
cell->col->pos,
cell->row->pos);
if (deps)
cell_queue_recalc_list (deps);
cell_queue_recalc_list (deps, TRUE);
}
/*
......
......@@ -167,7 +167,7 @@ do_clipboard_paste_cell_region (CellRegion *region, Sheet *dest_sheet,
dest_row + paste_height -1);
if (deps){
cell_queue_recalc_list (deps);
cell_queue_recalc_list (deps, TRUE);
formulas = 1;
}
......
......@@ -12,6 +12,8 @@
#include "utils.h"
#include "eval.h"
#undef DEBUG_EVALUATION
static GHashTable *dependency_hash;
void
......@@ -22,16 +24,40 @@ cell_eval (Cell *cell)
g_return_if_fail (cell != NULL);
#ifdef DEBUG_EVALUATION
{
char *exprtxt = expr_decode_tree
(cell->parsed_node, cell->sheet,
cell->col->pos, cell->row->pos);
printf ("Evaluating %s: %s ->\n",
cell_name (cell->col->pos, cell->row->pos),
exprtxt);
g_free (exprtxt);
}
#endif
v = eval_expr (cell->sheet, cell->parsed_node,
cell->col->pos,
cell->row->pos,
&error_msg);
#ifdef DEBUG_EVALUATION
{
char *valtxt = v
? value_get_as_string (v)
: g_strdup ("NULL");
printf ("Evaluating %s: -> %s\n",
cell_name (cell->col->pos, cell->row->pos),
valtxt);
g_free (valtxt);
}
#endif
if (cell->value){
value_release (cell->value);
cell->value = NULL;
}
if (v == NULL){
cell_set_rendered_text (cell, error_msg);
cell->value = NULL;
......@@ -43,7 +69,7 @@ cell_eval (Cell *cell)
}
cell_calc_dimensions (cell);
sheet_redraw_cell_region (cell->sheet,
cell->col->pos, cell->row->pos,
cell->col->pos, cell->row->pos);
......@@ -117,7 +143,7 @@ add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
result = g_hash_table_lookup (dependency_hash, &range);
if (result){
GList *cl;
result->ref_count++;
/* Is the cell already listed? */
......@@ -130,7 +156,7 @@ add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
return;
}
/* Create a new DependencyRange structure */
/* Create a new DependencyRange structure */
result = g_new (DependencyRange, 1);
*result = range;
result->ref_count = 1;
......@@ -151,12 +177,12 @@ add_value_deps (Cell *cell, const Value *value)
case VALUE_FLOAT:
/* Constants are no dependencies */
break;
/* Check every element of the array */
case VALUE_ARRAY:
{
int x, y;
for (x = 0; x < value->v.array.x; x++)
for (y = 0; y < value->v.array.y; y++)
add_value_deps (cell,
......@@ -180,7 +206,7 @@ static void
add_tree_deps (Cell *cell, ExprTree *tree)
{
GList *l;
switch (tree->oper){
case OPER_ANY_BINARY:
add_tree_deps (cell, tree->u.binary.value_a);
......@@ -190,8 +216,8 @@ add_tree_deps (Cell *cell, ExprTree *tree)
case OPER_ANY_UNARY:
add_tree_deps (cell, tree->u.value);
return;
case OPER_VAR:
case OPER_VAR:
add_cell_range_deps (
cell,
&tree->u.ref,
......@@ -202,7 +228,7 @@ add_tree_deps (Cell *cell, ExprTree *tree)
add_value_deps (cell, tree->u.constant);
return;
case OPER_FUNCALL:
case OPER_FUNCALL:
for (l = tree->u.function.arg_list; l; l = l->next)
add_tree_deps (cell, l->data);
return;
......@@ -262,21 +288,21 @@ cell_drop_dependencies (Cell *cell)
{
g_return_if_fail (cell != NULL);
g_return_if_fail (cell->parsed_node != NULL);
if (!dependency_hash)
return;
g_hash_table_foreach (dependency_hash, dependency_remove_cell, cell);
/* Drop any unused DependencyRanges (because their ref_count reached zero) */
if (remove_list){
GList *l = remove_list;
for (; l ; l = l->next){
g_hash_table_remove (dependency_hash, l->data);
g_free (l->data);
}
g_list_free (remove_list);
remove_list = NULL;
}
......@@ -329,7 +355,7 @@ region_get_dependencies (Sheet *sheet, int start_col, int start_row, int end_col
if (!dependency_hash)
dependency_hash_init ();
closure.start_col = start_col;
closure.start_row = start_row;
closure.end_col = end_col;
......@@ -349,7 +375,7 @@ cell_get_dependencies (Sheet *sheet, int col, int row)
if (!dependency_hash)
dependency_hash_init ();
closure.start_col = col;
closure.start_row = row;
closure.end_col = col;
......@@ -374,11 +400,11 @@ cell_queue_recalc (Cell *cell)
Workbook *wb;
g_return_if_fail (cell != NULL);
if (cell->flags & CELL_QUEUED_FOR_RECALC)
return;
wb = ((Sheet *)cell->sheet)->workbook;
wb = cell->sheet->workbook;
wb->eval_queue = g_list_prepend (wb->eval_queue, cell);
cell->flags |= CELL_QUEUED_FOR_RECALC;
}
......@@ -395,19 +421,19 @@ void
cell_unqueue_from_recalc (Cell *cell)
{
Workbook *wb;
g_return_if_fail (cell != NULL);
if (!(cell->flags & CELL_QUEUED_FOR_RECALC))
return;
wb = ((Sheet *)(cell->sheet))->workbook;
wb = cell->sheet->workbook;
wb->eval_queue = g_list_remove (wb->eval_queue, cell);
cell->flags &= ~CELL_QUEUED_FOR_RECALC;
}
void
cell_queue_recalc_list (GList *list)
cell_queue_recalc_list (GList *list, gboolean freelist)
{
Workbook *wb;
Cell *first_cell;
......@@ -417,7 +443,7 @@ cell_queue_recalc_list (GList *list)
return;
first_cell = list->data;
wb = ((Sheet *)(first_cell->sheet))->workbook;
wb = first_cell->sheet->workbook;
while (list) {
Cell *cell = list->data;
......@@ -431,7 +457,8 @@ cell_queue_recalc_list (GList *list)
cell->flags |= CELL_QUEUED_FOR_RECALC;
}
g_list_free (list0);
if (freelist)
g_list_free (list0);
}
static Cell *
......@@ -441,7 +468,7 @@ pick_next_cell_from_queue (Workbook *wb)
if (!wb->eval_queue)
return NULL;
cell = wb->eval_queue->data;
wb->eval_queue = g_list_remove (wb->eval_queue, cell);
if (!(cell->flags & CELL_QUEUED_FOR_RECALC))
......@@ -459,7 +486,7 @@ workbook_next_generation (Workbook *wb)
{
if (wb->generation == 255){
GList *cell_list = wb->formula_cell_list;
for (; cell_list; cell_list = cell_list->next){
Cell *cell = cell_list->data;
......@@ -479,12 +506,16 @@ workbook_recalc (Workbook *wb)
{
int generation;
Cell *cell;
GList *deps, *l;
workbook_next_generation (wb);
generation = wb->generation;
while ((cell = pick_next_cell_from_queue (wb))){
GList *deps, *l;
if (cell->generation == generation)
continue;
cell->generation = generation;
cell_eval (cell);
deps = cell_get_dependencies (cell->sheet, cell->col->pos, cell->row->pos);
......@@ -506,13 +537,6 @@ workbook_recalc (Workbook *wb)
void
workbook_recalc_all (Workbook *workbook)
{
GList *l;
for (l = workbook->formula_cell_list; l; l = l->next){
Cell *cell = l->data;
cell_queue_recalc (cell);
}
cell_queue_recalc_list (workbook->formula_cell_list, FALSE);
workbook_recalc (workbook);
}
......@@ -46,7 +46,7 @@ GList *region_get_dependencies (Sheet *sheet,
*/
void cell_queue_recalc (Cell *cell);
void cell_queue_recalc_list (GList *list);
void cell_queue_recalc_list (GList *list, gboolean freelist);
void cell_unqueue_from_recalc (Cell *cell);
......
......@@ -48,8 +48,7 @@ goal_seek_eval (float_t x, float_t *y, void *vevaldata)
cell_set_value_simple (evaldata->xcell, value_new_float (x));
cell_content_changed (evaldata->xcell);
cell_eval (evaldata->ycell);
workbook_recalc (evaldata->xcell->sheet->workbook);
if (evaldata->ycell->value) {
*y = value_get_as_float (evaldata->ycell->value) - evaldata->ytarget;
......
......@@ -48,8 +48,7 @@ goal_seek_eval (float_t x, float_t *y, void *vevaldata)
cell_set_value_simple (evaldata->xcell, value_new_float (x));
cell_content_changed (evaldata->xcell);
cell_eval (evaldata->ycell);
workbook_recalc (evaldata->xcell->sheet->workbook);
if (evaldata->ycell->value) {
*y = value_get_as_float (evaldata->ycell->value) - evaldata->ytarget;
......
......@@ -12,6 +12,8 @@
#include "utils.h"
#include "eval.h"
#undef DEBUG_EVALUATION
static GHashTable *dependency_hash;
void
......@@ -22,16 +24,40 @@ cell_eval (Cell *cell)
g_return_if_fail (cell != NULL);
#ifdef DEBUG_EVALUATION
{
char *exprtxt = expr_decode_tree
(cell->parsed_node, cell->sheet,
cell->col->pos, cell->row->pos);
printf ("Evaluating %s: %s ->\n",
cell_name (cell->col->pos, cell->row->pos),
exprtxt);
g_free (exprtxt);
}
#endif
v = eval_expr (cell->sheet, cell->parsed_node,
cell->col->pos,
cell->row->pos,
&error_msg);
#ifdef DEBUG_EVALUATION
{
char *valtxt = v
? value_get_as_string (v)
: g_strdup ("NULL");
printf ("Evaluating %s: -> %s\n",
cell_name (cell->col->pos, cell->row->pos),
valtxt);
g_free (valtxt);
}
#endif
if (cell->value){
value_release (cell->value);
cell->value = NULL;
}
if (v == NULL){
cell_set_rendered_text (cell, error_msg);
cell->value = NULL;
......@@ -43,7 +69,7 @@ cell_eval (Cell *cell)
}
cell_calc_dimensions (cell);
sheet_redraw_cell_region (cell->sheet,
cell->col->pos, cell->row->pos,
cell->col->pos, cell->row->pos);
......@@ -117,7 +143,7 @@ add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
result = g_hash_table_lookup (dependency_hash, &range);
if (result){
GList *cl;
result->ref_count++;
/* Is the cell already listed? */
......@@ -130,7 +156,7 @@ add_cell_range_deps (Cell *cell, const CellRef *a, const CellRef *b)
return;
}
/* Create a new DependencyRange structure */
/* Create a new DependencyRange structure */
result = g_new (DependencyRange, 1);
*result = range;
result->ref_count = 1;
......@@ -151,12 +177,12 @@ add_value_deps (Cell *cell, const Value *value)
case VALUE_FLOAT:
/* Constants are no dependencies */
break;
/* Check every element of the array */
case VALUE_ARRAY:
{
int x, y;
for (x = 0; x < value->v.array.x; x++)
for (y = 0; y < value->v.array.y; y++)
add_value_deps (cell,
......@@ -180,7 +206,7 @@ static void
add_tree_deps (Cell *cell, ExprTree *tree)
{
GList *l;
switch (tree->oper){
case OPER_ANY_BINARY:
add_tree_deps (cell, tree->u.binary.value_a);
......@@ -190,8 +216,8 @@ add_tree_deps (Cell *cell, ExprTree *tree)
case OPER_ANY_UNARY:
add_tree_deps (cell, tree->u.value);
return;
case OPER_VAR:
case OPER_VAR:
add_cell_range_deps (
cell,
&tree->u.ref,
......@@ -202,7 +228,7 @@ add_tree_deps (Cell *cell, ExprTree *tree)
add_value_deps (cell, tree->u.constant);
return;
case OPER_FUNCALL:
case OPER_FUNCALL:
for (l = tree->u.function.arg_list; l; l = l->next)
add_tree_deps (cell, l->data);
return;
......@@ -262,21 +288,21 @@ cell_drop_dependencies (Cell *cell)
{
g_return_if_fail (cell != NULL);
g_return_if_fail (cell->parsed_node != NULL);
if (!dependency_hash)
return;
g_hash_table_foreach (dependency_hash, dependency_remove_cell, cell);
/* Drop any unused DependencyRanges (because their ref_count reached zero) */
if (remove_list){
GList *l = remove_list;
for (; l ; l = l->next){
g_hash_table_remove (dependency_hash, l->data);
g_free (l->data);
}
g_list_free (remove_list);
remove_list = NULL;
}
......@@ -329,7 +355,7 @@ region_get_dependencies (Sheet *sheet, int start_col, int start_row, int end_col
if (!dependency_hash)
dependency_hash_init ();
closure.start_col = start_col;
closure.start_row = start_row;
closure.end_col = end_col;
......@@ -349,7 +375,7 @@ cell_get_dependencies (Sheet *sheet, int col, int row)
if (!dependency_hash)
dependency_hash_init ();
closure.start_col = col;
closure.start_row = row;
closure.end_col = col;
......@@ -374,11 +400,11 @@ cell_queue_recalc (Cell *cell)
Workbook *wb;
g_return_if_fail (cell != NULL);
if (cell->flags & CELL_QUEUED_FOR_RECALC)
return;
wb = ((Sheet *)cell->sheet)->workbook;
wb = cell->sheet->workbook;
wb->eval_queue = g_list_prepend (wb->eval_queue, cell);
cell->flags |= CELL_QUEUED_FOR_RECALC;
}
......@@ -395,19 +421,19 @@ void
cell_unqueue_from_recalc (Cell *cell)
{
Workbook *wb;
g_return_if_fail (cell != NULL);
if (!(cell->flags & CELL_QUEUED_FOR_RECALC))
return;
wb = ((Sheet *)(cell->sheet))->workbook;
wb = cell->sheet->workbook;
wb->eval_queue = g_list_remove (wb->eval_queue, cell);
cell->flags &= ~CELL_QUEUED_FOR_RECALC;
}
void
cell_queue_recalc_list (GList *list)
cell_queue_recalc_list (GList *list, gboolean freelist)
{
Workbook *wb;
Cell *first_cell;
......@@ -417,7 +443,7 @@ cell_queue_recalc_list (GList *list)
return;
first_cell = list->data;
wb = ((Sheet *)(first_cell->sheet))->workbook;
wb = first_cell->sheet->workbook;
while (list) {
Cell *cell = list->data;
......@@ -431,7 +457,8 @@ cell_queue_recalc_list (GList *list)
cell->flags |= CELL_QUEUED_FOR_RECALC;
}
g_list_free (list0);
if (freelist)
g_list_free (list0);
}
static Cell *
......@@ -441,7 +468,7 @@ pick_next_cell_from_queue (Workbook *wb)
if (!wb->eval_queue)
return NULL;
cell = wb->eval_queue->data;
wb->eval_queue = g_list_remove (wb->eval_queue, cell);
if (!(cell->flags & CELL_QUEUED_FOR_RECALC))
......@@ -459,7 +486,7 @@ workbook_next_generation (Workbook *wb)
{
if (wb->generation == 255){
GList *cell_list = wb->formula_cell_list;
for (; cell_list; cell_list = cell_list->next){
Cell *cell = cell_list->data;
......@@ -479,12 +506,16 @@ workbook_recalc (Workbook *wb)
{
int generation;
Cell *cell;
GList *deps, *l;
workbook_next_generation (wb);
generation = wb->generation;
while ((cell = pick_next_cell_from_queue (wb))){
GList *deps, *l;
if (cell->generation == generation)
continue;
cell->generation = generation;
cell_eval (cell);
deps = cell_get_dependencies (cell->sheet, cell->col->pos, cell->row->pos);
......@@ -506,13 +537,6 @@ workbook_recalc (Workbook *wb)
void
workbook_recalc_all (Workbook *workbook)