3
3
* dependent.c: Manage calculation dependencies between objects
5
* Copyright (C) 2000-2006
6
* Jody Goldberg (jody@gnome.org)
7
* Morten Welinder (terra@gnome.org)
5
* Copyright (C) 2000-2006 Jody Goldberg (jody@gnome.org)
6
* Copyright (C) 2006-2009 Morten Welinder (terra@gnome.org)
9
8
* This program is free software; you can redistribute it and/or modify it
10
9
* under the terms of version 2 of the GNU General Public License as published
599
g_print ("resize %p: %d [%d %.1f %.0f%%]\n",
602
hash_table->num_elements,
603
(double)totlen / nonzero,
604
100.0 * totlen / capacity);
600
g_printerr ("resize %p: %d [%d %.1f %.0f%%]\n",
603
hash_table->num_elements,
604
(double)totlen / nonzero,
605
100.0 * totlen / capacity);
846
847
DependencySingle *single;
847
848
GnmDepContainer *deps;
848
849
DependentFlags flag = DEPENDENT_NO_FLAG;
850
if (ref->sheet != NULL) {
851
if (ref->sheet != dep->sheet)
852
flag = (ref->sheet->workbook != dep->sheet->workbook)
853
? DEPENDENT_GOES_INTERBOOK : DEPENDENT_GOES_INTERSHEET;
854
deps = ref->sheet->deps;
856
deps = dep->sheet->deps;
850
Sheet const *sheet = eval_sheet (ref->sheet, dep->sheet);
852
if (sheet != dep->sheet)
853
flag = (sheet->workbook != dep->sheet->workbook)
854
? DEPENDENT_GOES_INTERBOOK
855
: DEPENDENT_GOES_INTERSHEET;
858
859
/* Inserts if it is not already there */
859
gnm_cellpos_init_cellref (&lookup.pos, ref, pos);
860
gnm_cellpos_init_cellref (&lookup.pos, ref, pos, sheet);
860
861
single = g_hash_table_lookup (deps->single_hash, &lookup);
861
862
if (single == NULL) {
862
863
single = go_mem_chunk_alloc (deps->single_pool);
875
876
DependencySingle lookup;
876
877
DependencySingle *single;
877
GnmDepContainer *deps = eval_sheet (a->sheet, dep->sheet)->deps;
878
Sheet const *sheet = eval_sheet (a->sheet, dep->sheet);
879
GnmDepContainer *deps = sheet->deps;
882
gnm_cellpos_init_cellref (&lookup.pos, a, pos);
884
gnm_cellpos_init_cellref (&lookup.pos, a, pos, sheet);
883
885
single = g_hash_table_lookup (deps->single_hash, &lookup);
884
886
if (single != NULL) {
885
887
micro_hash_remove (&single->deps, dep);
898
900
int i = BUCKET_OF_ROW (r->range.start.row);
899
901
int const end = BUCKET_OF_ROW (r->range.end.row);
902
DependencyRange r2 = *r;
901
904
for ( ; i <= end; i++) {
903
905
DependencyRange *result;
907
/* Restrict range to bucket. */
908
r2.range.start.row = MAX (r->range.start.row, BUCKET_START_ROW (i));
909
r2.range.end.row = MIN (r->range.end.row, BUCKET_END_ROW (i));
905
911
if (deps->range_hash[i] == NULL)
906
912
deps->range_hash[i] = g_hash_table_new (
907
913
(GHashFunc) deprange_hash,
908
914
(GEqualFunc) deprange_equal);
910
result = g_hash_table_lookup (deps->range_hash[i], r);
916
result = g_hash_table_lookup (deps->range_hash[i], &r2);
912
918
/* Inserts if it is not already there */
913
919
micro_hash_insert (&result->deps, dep);
930
936
int i = BUCKET_OF_ROW (r->range.start.row);
931
937
int const end = BUCKET_OF_ROW (r->range.end.row);
938
DependencyRange r2 = *r;
936
943
for ( ; i <= end; i++) {
937
DependencyRange *result =
938
g_hash_table_lookup (deps->range_hash[i], r);
944
DependencyRange *result;
946
/* Restrict range to bucket. */
947
r2.range.start.row = MAX (r->range.start.row, BUCKET_START_ROW (i));
948
r2.range.end.row = MIN (r->range.end.row, BUCKET_END_ROW (i));
950
result = g_hash_table_lookup (deps->range_hash[i], &r2);
940
952
micro_hash_remove (&result->deps, dep);
941
953
if (micro_hash_is_empty (&result->deps)) {
954
966
DependencyRange range;
955
967
DependentFlags flag = DEPENDENT_NO_FLAG;
957
gnm_cellpos_init_cellref (&range.range.start, a, pos);
958
gnm_cellpos_init_cellref (&range.range.end, b, pos);
969
gnm_cellpos_init_cellref (&range.range.start, a, pos, dep->sheet);
970
gnm_cellpos_init_cellref (&range.range.end, b, pos, dep->sheet);
959
971
range_normalize (&range.range);
961
973
if (a->sheet != NULL) {
992
1004
DependencyRange range;
994
gnm_cellpos_init_cellref (&range.range.start, a, pos);
995
gnm_cellpos_init_cellref (&range.range.end, b, pos);
1006
gnm_cellpos_init_cellref (&range.range.start, a, pos, dep->sheet);
1007
gnm_cellpos_init_cellref (&range.range.end, b, pos, dep->sheet);
996
1008
range_normalize (&range.range);
998
1010
if (a->sheet != NULL) {
1024
1036
case GNM_EXPR_OP_RANGE_CTOR: /* See #562363 */
1025
1037
case GNM_EXPR_OP_INTERSECT:
1026
1038
case GNM_EXPR_OP_ANY_BINARY:
1027
return link_expr_dep (ep, tree->binary.value_a) |
1028
link_expr_dep (ep, tree->binary.value_b);
1039
return link_expr_dep (ep, tree->binary.value_a) |
1040
link_expr_dep (ep, tree->binary.value_b);
1029
1041
case GNM_EXPR_OP_ANY_UNARY:
1030
1042
return link_expr_dep (ep, tree->unary.value);
1031
1043
case GNM_EXPR_OP_CELLREF:
1270
1281
g_hash_table_insert (dep->sheet->deps->dynamic_deps, dep, dyn);
1273
gnm_cellpos_init_cellref (&range.range.start, &rr->a, pos);
1274
gnm_cellpos_init_cellref (&range.range.end, &rr->b, pos);
1284
gnm_cellpos_init_cellref (&range.range.start, &rr->a, pos, dep->sheet);
1285
gnm_cellpos_init_cellref (&range.range.end, &rr->b, pos, dep->sheet);
1275
1286
if (range_is_singleton (&range.range)) {
1276
1287
flags = link_single_dep (&dyn->base, pos, &rr->a);
1277
1288
dyn->singles = g_slist_prepend (dyn->singles, gnm_rangeref_dup (rr));
1395
1407
#ifdef DEBUG_EVALUATION
1397
1409
GnmParsePos pp;
1398
char *str = gnm_expr_top_as_string (cell->base.texpr,
1399
parse_pos_init_cell (&pp, cell), gnm_conventions_default);
1400
g_print ("{\nEvaluating %s: %s;\n", cell_name (cell), str);
1410
char *str = gnm_expr_top_as_string
1412
parse_pos_init_cell (&pp, cell),
1414
g_printerr ("{\nEvaluating %s!%s: %s;\n",
1415
cell->base.sheet->name_quoted, cell_name (cell),
1454
1470
char *valtxt = v
1455
1471
? value_get_as_string (v)
1456
1472
: g_strdup ("NULL");
1457
g_print ("Evaluation(%d) %s := %s\n", max_iteration, cell_name (cell), valtxt);
1473
g_printerr ("Evaluation(%d) %s := %s\n",
1474
max_iteration, cell_name (cell), valtxt);
1458
1475
g_free (valtxt);
1593
1612
/* When things get slow this is a good test to enable */
1594
1613
static int counter = 0;
1595
1614
if ((++counter % 100000) == 0)
1596
g_print ("%d\n", counter / 100000);
1615
g_printerr ("%d\n", counter / 100000);
1599
1618
if (range_contains (range, c->col, c->row)) {
1730
1749
dependent_flag_recalc (dep););
1732
1751
/* look for things that depend on the sheet */
1733
for (i = BUCKET_LAST; i >= 0 ; i--) {
1752
for (i = sheet->deps->buckets - 1; i >= 0 ; i--) {
1734
1753
GHashTable *hash = sheet->deps->range_hash[i];
1735
1754
if (hash != NULL)
1736
1755
g_hash_table_foreach (hash,
1906
1925
*l = g_slist_prepend (*l, nexpr);
1928
struct cb_remote_names {
1934
cb_remote_names1 (G_GNUC_UNUSED const char *name,
1935
GnmNamedExpr *nexpr,
1936
struct cb_remote_names *data)
1938
data->names = g_slist_prepend (data->names, nexpr);
1942
cb_remote_names2 (GnmNamedExpr *nexpr,
1943
G_GNUC_UNUSED gpointer value,
1944
struct cb_remote_names *data)
1947
nexpr->pos.sheet ? nexpr->pos.sheet->workbook : nexpr->pos.wb;
1949
data->names = g_slist_prepend (data->names, nexpr);
1953
* Get a list of all names that (may) reference data in a given sheet.
1954
* This is approximated as all names in the sheet, all global names in
1955
* its workbook, and all external references that actually mention the
1959
names_referencing_sheet (Sheet *sheet)
1961
struct cb_remote_names data;
1964
data.wb = sheet->workbook;
1966
workbook_foreach_name (sheet->workbook, TRUE,
1967
(GHFunc)cb_remote_names1,
1969
gnm_sheet_foreach_name (sheet, (GHFunc)cb_remote_names1, &data);
1971
if (sheet->deps->referencing_names)
1972
g_hash_table_foreach (sheet->deps->referencing_names,
1973
(GHFunc)cb_remote_names2,
1910
1981
* dependents_relocate:
1911
1982
* @rinfo : the descriptor record for what is being moved where.
2041
2112
case GNM_EXPR_RELOCATE_COLS:
2042
2113
case GNM_EXPR_RELOCATE_ROWS: {
2043
GSList *names = NULL, *l;
2114
GSList *l, *names = names_referencing_sheet (sheet);
2115
GnmExprRelocateInfo rinfo2 = *rinfo;
2045
if (sheet->deps->referencing_names)
2046
g_hash_table_foreach (sheet->deps->referencing_names,
2047
(GHFunc)cb_collect_names,
2049
2117
for (l = names; l; l = l->next) {
2050
2118
GnmNamedExpr *nexpr = l->data;
2051
GnmExprTop const *newtree =
2052
gnm_expr_top_relocate (nexpr->texpr,
2119
GnmExprTop const *newtree;
2120
rinfo2.pos = nexpr->pos;
2121
newtree = gnm_expr_top_relocate (nexpr->texpr,
2055
2124
GOUndo *u = expr_name_set_expr_undo_new (nexpr);
2056
2125
u_names = go_undo_combine (u_names, u);
2593
g_signal_emit_by_name (gnm_app_get_app (), "recalc-finished");
2595
2666
WORKBOOK_FOREACH_SHEET (wb, sheet, {
2596
2667
SHEET_FOREACH_VIEW (sheet, sv, sv_flag_selection_change (sv););
2597
2668
sheet_redraw_all (sheet, FALSE);});
2650
2721
deps->head = deps->tail = NULL;
2652
deps->range_hash = g_new0 (GHashTable *, BUCKET_LAST + 1);
2723
deps->buckets = 1 + BUCKET_OF_ROW (gnm_sheet_get_last_row (sheet));
2724
deps->range_hash = g_new0 (GHashTable *, deps->buckets);
2653
2725
deps->range_pool = go_mem_chunk_new ("range pool",
2654
2726
sizeof (DependencyRange),
2655
2727
16 * 1024 - 100);
2743
gnm_dep_container_resize (GnmDepContainer *deps, int rows)
2745
int i, buckets = 1 + BUCKET_OF_ROW (rows - 1);
2747
for (i = buckets; i < deps->buckets; i++) {
2748
GHashTable *hash = deps->range_hash[i];
2750
int s = g_hash_table_size (hash);
2752
g_printerr ("Hash table size: %d\n", s);
2753
g_hash_table_destroy (hash);
2754
deps->range_hash[i] = NULL;
2758
deps->range_hash = g_renew (GHashTable *, deps->range_hash, buckets);
2760
for (i = deps->buckets; i < buckets; i++)
2761
deps->range_hash[i] = NULL;
2763
deps->buckets = buckets;
2670
2766
/****************************************************************************
2675
dump_range_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2676
G_GNUC_UNUSED gpointer closure)
2771
dependent_debug_name_for_sheet (GnmDependent const *dep, Sheet *sheet,
2774
if (sheet && sheet == dep->sheet && dependent_is_cell (dep))
2775
g_string_append (target, cell_name (GNM_DEP_TO_CELL (dep)));
2777
dependent_debug_name (dep, target);
2782
dump_range_dep (gpointer key, G_GNUC_UNUSED gpointer value, gpointer sheet_)
2678
2784
DependencyRange const *deprange = key;
2679
2785
GnmRange const *range = &(deprange->range);
2786
Sheet *sheet = sheet_;
2680
2787
GString *target = g_string_sized_new (10000);
2681
2788
gboolean first = TRUE;
2691
2798
g_string_append (target, ", ");
2692
dependent_debug_name (dep, target);
2799
dependent_debug_name_for_sheet (dep, sheet, target);
2694
2801
g_string_append_c (target, ')');
2696
g_print ("%s\n", target->str);
2803
g_printerr ("%s\n", target->str);
2697
2804
g_string_free (target, TRUE);
2701
dump_single_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2702
G_GNUC_UNUSED gpointer closure)
2808
dump_single_dep (gpointer key, G_GNUC_UNUSED gpointer value, gpointer sheet_)
2704
2810
DependencySingle *depsingle = key;
2811
Sheet *sheet = sheet_;
2705
2812
GString *target = g_string_sized_new (10000);
2706
2813
gboolean first = TRUE;
2716
2823
g_string_append (target, ", ");
2717
dependent_debug_name (dep, target);
2824
dependent_debug_name_for_sheet (dep, sheet, target);
2720
g_print ("%s\n", target->str);
2827
g_printerr ("%s\n", target->str);
2721
2828
g_string_free (target, TRUE);
2763
2870
g_string_append (out.accum, "] }");
2764
g_print ("%s\n", out.accum->str);
2871
g_printerr ("%s\n", out.accum->str);
2765
2872
g_string_free (out.accum, TRUE);
2769
cb_dump_name_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2772
GnmDependent *dep = key;
2773
GString *target = closure;
2775
if (target->str[target->len - 1] != '[')
2776
g_string_append (target, ", ");
2777
dependent_debug_name (dep, target);
2781
dump_name_dep (gpointer key, G_GNUC_UNUSED gpointer value,
2782
G_GNUC_UNUSED gpointer closure)
2784
GnmNamedExpr *nexpr = key;
2785
GString *target = g_string_new (NULL);
2787
g_string_append (target, " ");
2788
if (!nexpr->active) g_string_append_c (target, '(');
2789
g_string_append (target, nexpr->name->str);
2790
if (!nexpr->active) g_string_append_c (target, ')');
2791
g_string_append (target, " -> [");
2792
if (nexpr->dependents)
2793
g_hash_table_foreach (nexpr->dependents, cb_dump_name_dep, target);
2794
g_string_append (target, "]");
2796
g_print ("%s\n", target->str);
2797
g_string_free (target, TRUE);
2801
2876
* gnm_dep_container_dump :
2804
2879
* A useful utility for checking the state of the dependency data structures.
2807
gnm_dep_container_dump (GnmDepContainer const *deps)
2882
gnm_dep_container_dump (GnmDepContainer const *deps,
2810
Sheet *sheet = NULL;
2812
2887
g_return_if_fail (deps != NULL);
2814
2889
gnm_dep_container_sanity_check (deps);
2816
for (i = BUCKET_LAST; i >= 0 ; i--) {
2891
for (i = deps->buckets - 1; i >= 0 ; i--) {
2817
2892
GHashTable *hash = deps->range_hash[i];
2818
2893
if (hash != NULL && g_hash_table_size (hash) > 0) {
2819
g_print (" Bucket %d (%d-%d): Range hash size %d: range over which cells in list depend\n",
2821
BUCKET_START_ROW (i),
2823
g_hash_table_size (hash));
2894
g_printerr (" Bucket %d (rows %d-%d): Range hash size %d: range over which cells in list depend\n",
2896
BUCKET_START_ROW (i) + 1,
2897
BUCKET_END_ROW (i) + 1,
2898
g_hash_table_size (hash));
2824
2899
g_hash_table_foreach (hash,
2825
dump_range_dep, NULL);
2829
2905
if (deps->single_hash && g_hash_table_size (deps->single_hash) > 0) {
2830
g_print (" Single hash size %d: cell on which list of cells depend\n",
2831
g_hash_table_size (deps->single_hash));
2906
g_printerr (" Single hash size %d: cell on which list of cells depend\n",
2907
g_hash_table_size (deps->single_hash));
2832
2908
g_hash_table_foreach (deps->single_hash,
2833
dump_single_dep, NULL);
2836
2913
if (deps->dynamic_deps && g_hash_table_size (deps->dynamic_deps) > 0) {
2837
g_print (" Dynamic hash size %d: cells that depend on dynamic dependencies\n",
2838
g_hash_table_size (deps->dynamic_deps));
2914
g_printerr (" Dynamic hash size %d: cells that depend on dynamic dependencies\n",
2915
g_hash_table_size (deps->dynamic_deps));
2839
2916
g_hash_table_foreach (deps->dynamic_deps,
2840
2917
dump_dynamic_dep, NULL);
2843
2920
if (deps->referencing_names && g_hash_table_size (deps->referencing_names) > 0) {
2844
g_print (" Names whose expressions reference this sheet mapped to dependencies\n");
2921
GSList *l, *names = NULL;
2845
2923
g_hash_table_foreach (deps->referencing_names,
2846
dump_name_dep, NULL);
2924
(GHFunc)cb_collect_names,
2927
g_printerr (" Names whose expressions explicitly reference this sheet\n ");
2928
for (l = names; l; l = l->next) {
2929
GnmNamedExpr *nexpr = l->data;
2931
expr_name_name (nexpr),
2932
l->next ? ", " : "\n");
2934
g_slist_free (names);
2854
2942
GHashTable *seenb4;
2856
2944
if (deps->head && !deps->tail)
2857
g_warning ("Dependency container %p has head, but no tail.", deps);
2945
g_warning ("Dependency container %p has head, but no tail.", (void *)deps);
2858
2946
if (deps->tail && !deps->head)
2859
g_warning ("Dependency container %p has tail, but no head.", deps);
2947
g_warning ("Dependency container %p has tail, but no head.", (void *)deps);
2860
2948
if (deps->head && deps->head->prev_dep)
2861
g_warning ("Dependency container %p has head, but not at the beginning.", deps);
2949
g_warning ("Dependency container %p has head, but not at the beginning.", (void *)deps);
2862
2950
if (deps->tail && deps->tail->next_dep)
2863
g_warning ("Dependency container %p has tail, but not at the end.", deps);
2951
g_warning ("Dependency container %p has tail, but not at the end.", (void *)deps);
2865
2953
seenb4 = g_hash_table_new (g_direct_hash, g_direct_equal);
2866
2954
for (dep = deps->head; dep; dep = dep->next_dep) {
2867
2955
if (dep->prev_dep && (dep->prev_dep->next_dep != dep))
2868
g_warning ("Dependency container %p has left double-link failure at %p.", deps, dep);
2956
g_warning ("Dependency container %p has left double-link failure at %p.", (void *)deps, (void *)dep);
2869
2957
if (dep->next_dep && (dep->next_dep->prev_dep != dep))
2870
g_warning ("Dependency container %p has right double-link failure at %p.", deps, dep);
2958
g_warning ("Dependency container %p has right double-link failure at %p.", (void *)deps, (void *)dep);
2871
2959
if (!dep->next_dep && dep != deps->tail)
2872
g_warning ("Dependency container %p ends before its tail.", deps);
2960
g_warning ("Dependency container %p ends before its tail.", (void *)deps);
2873
2961
if (!dependent_is_linked (dep))
2874
g_warning ("Dependency container %p contains unlinked dependency %p.", deps, dep);
2962
g_warning ("Dependency container %p contains unlinked dependency %p.", (void *)deps, (void *)dep);
2875
2963
if (g_hash_table_lookup (seenb4, dep)) {
2876
g_warning ("Dependency container %p is circular.", deps);
2964
g_warning ("Dependency container %p is circular.", (void *)deps);
2879
2967
g_hash_table_insert (seenb4, (gpointer)dep, (gpointer)dep);