852
852
GnmValue const *a, *b;
853
853
BinOpImplicitIteratorFunc func;
855
/* multiply by 0 in unused dimensions.
856
* this is simpler than lots of conditions
857
* state->use_x.a ? x : 0
854
862
gpointer user_data;
855
863
} BinOpImplicitIteratorState;
857
865
static GnmValue *
858
cb_implicit_iter_a_to_b (GnmValue const *v, GnmEvalPos const *ep,
866
cb_implicit_iter_a_and_b (GnmValue const *v, GnmEvalPos const *ep,
859
867
int x, int y, BinOpImplicitIteratorState const *state)
861
869
state->res->v_array.vals [x][y] = (*state->func) (ep,
862
v, value_area_get_x_y (state->b, x, y, ep), state->user_data);
870
value_area_get_x_y (state->a, state->x.a * x, state->y.a * y, ep),
871
value_area_get_x_y (state->b, state->x.b * x, state->y.b * y, ep),
865
875
static GnmValue *
870
880
v, state->b, state->user_data);
884
/* This is only triggered if something returns an array or a range which can
885
* only happen if we are in array eval mode. */
887
bin_array_iter_a (GnmEvalPos const *ep,
888
GnmValue *a, GnmValue *b,
889
BinOpImplicitIteratorFunc func,
892
BinOpImplicitIteratorState iter_info;
894
/* a must be a cellrange or array, it can not be NULL */
895
iter_info.func = func;
896
iter_info.user_data = (gpointer) expr;
901
* Use matching positions unless the dimension is singular, in which
902
* case use the zero item
903
* res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
905
* If both items have non-singular sizes for
906
* the same dimension use the min size (see samples/array.xls) */
908
(b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)) {
909
int sa, sb, w = 1, h = 1;
911
sa = value_area_get_width (a, ep);
912
sb = value_area_get_width (b, ep);
913
if ((iter_info.x.a = (sa == 1) ? 0 : 1))
915
if ((iter_info.x.b = (sb == 1) ? 0 : 1) && (w > sb || w == 1))
918
sa = value_area_get_height (a, ep);
919
sb = value_area_get_height (b, ep);
920
if ((iter_info.y.a = (sa == 1) ? 0 : 1))
922
if ((iter_info.y.b = (sb == 1) ? 0 : 1) && (h > sb || h == 1))
925
iter_info.res = value_new_array_empty (w, h);
926
value_area_foreach (iter_info.res, ep, CELL_ITER_ALL,
927
(ValueAreaFunc) cb_implicit_iter_a_and_b, &iter_info);
929
iter_info.res = value_new_array_empty (
930
value_area_get_width (a, ep),
931
value_area_get_height (a, ep));
932
value_area_foreach (a, ep, CELL_ITER_ALL,
933
(ValueAreaFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
939
return iter_info.res;
873
942
static GnmValue *
874
943
cb_implicit_iter_b_to_scalar_a (GnmValue const *v, GnmEvalPos const *ep,
875
944
int x, int y, BinOpImplicitIteratorState const *state)
878
947
state->a, v, state->user_data);
882
950
static GnmValue *
883
bin_array_op (GnmEvalPos const *ep, const GnmValue *sizer,
884
GnmValue *a, GnmValue *b,
885
BinOpImplicitIteratorFunc func, gpointer user_data)
951
bin_array_iter_b (GnmEvalPos const *ep,
952
GnmValue *a, GnmValue *b,
953
BinOpImplicitIteratorFunc func,
887
956
BinOpImplicitIteratorState iter_info;
889
if (sizer != a || b == NULL || !VALUE_IS_ERROR (b)) {
890
iter_info.func = func;
891
iter_info.user_data = user_data;
894
iter_info.res = value_new_array_empty (
895
value_area_get_width (sizer, ep),
896
value_area_get_height (sizer, ep));
898
value_area_foreach (b, ep, CELL_ITER_ALL,
899
(ValueAreaFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
900
else if (b != NULL &&
901
(b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY))
902
value_area_foreach (a, ep, CELL_ITER_ALL,
903
(ValueAreaFunc) cb_implicit_iter_a_to_b, &iter_info);
905
value_area_foreach (a, ep, CELL_ITER_ALL,
906
(ValueAreaFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
908
/* you have to love the asymmetry of MS XL */
909
iter_info.res = value_new_error_VALUE (ep);
958
iter_info.func = func;
959
iter_info.user_data = (gpointer) expr;
963
/* b must be a cellrange or array, it can not be NULL */
964
iter_info.res = value_new_array_empty (
965
value_area_get_width (b, ep),
966
value_area_get_height (b, ep));
967
value_area_foreach (b, ep, CELL_ITER_ALL,
968
(ValueAreaFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
911
970
value_release (a);
914
973
return iter_info.res;
1712
1779
static GnmExpr const *
1713
cellrange_relocate (GnmValue const *v, GnmExprRelocateInfo const *rinfo)
1780
relocate_cellrange (GnmExprRelocateInfo const *rinfo, gboolean ignore_rel,
1781
GnmValueRange const *v)
1783
GnmCellRef ref_a = v->cell.a;
1784
GnmCellRef ref_b = v->cell.b;
1785
int reloc_a, reloc_b;
1787
if (rinfo->reloc_type == GNM_EXPR_RELOCATE_INVALIDATE_SHEET) {
1788
Sheet const *sheet_a = ref_a.sheet;
1789
Sheet const *sheet_b = ref_b.sheet;
1791
gboolean hit_a = sheet_a && sheet_a->being_invalidated;
1792
gboolean hit_b = sheet_b && sheet_b->being_invalidated;
1795
if (!hit_a && !hit_b)
1798
if (sheet_a == NULL || sheet_b == NULL ||
1799
sheet_a->workbook != sheet_b->workbook)
1800
/* A 3D reference between workbooks? */
1801
return gnm_expr_new_constant (value_new_error_REF (NULL));
1803
/* Narrow the sheet range. */
1804
wb = sheet_a->workbook;
1805
dir = (sheet_a->index_in_wb < sheet_b->index_in_wb) ? +1 : -1;
1806
while (sheet_a != sheet_b && sheet_a->being_invalidated)
1807
sheet_a = workbook_sheet_by_index (wb, sheet_a->index_in_wb + dir);
1808
while (sheet_a != sheet_b && sheet_b->being_invalidated)
1809
sheet_b = workbook_sheet_by_index (wb, sheet_b->index_in_wb - dir);
1811
if (sheet_a->being_invalidated)
1812
return gnm_expr_new_constant (value_new_error_REF (NULL));
1814
ref_a.sheet = (Sheet *)sheet_a;
1815
ref_b.sheet = (Sheet *)sheet_b;
1816
return gnm_expr_new_constant (value_new_cellrange_unsafe (&ref_a, &ref_b));
1819
/* FIXME : should not be necessary. We need to audit the code to
1820
* define whether both refs need a sheet, or just ref_a for normal
1821
* non-3d references */
1822
if (ref_b.sheet == NULL && ref_a.sheet != NULL)
1823
ref_b.sheet = ref_a.sheet;
1825
reloc_a = relocate_cellref (rinfo, ignore_rel, &ref_a);
1826
reloc_b = relocate_cellref (rinfo, ignore_rel, &ref_b);
1716
1829
* If either end is an error then the whole range is an error.
1717
1830
* If both ends need to relocate -> relocate
1721
1834
* in only 1 dimension, and the
1722
1835
* otherwise remain static
1724
GnmCellRef ref_a = v->v_range.cell.a;
1725
GnmCellRef ref_b = v->v_range.cell.b;
1728
/* FIXME : should not be necessary. We need to audit the code to
1729
* define whether both refs need a sheet, or just ref_a for normal
1730
* non-3d references */
1731
if (ref_b.sheet == NULL && ref_a.sheet != NULL)
1732
ref_b.sheet = ref_a.sheet;
1734
switch (cellref_relocate (&ref_a, rinfo)) {
1735
case CELLREF_NO_RELOCATE : break;
1736
case CELLREF_RELOCATE_FROM_IN : needs = 0x4; break;
1737
case CELLREF_RELOCATE_FROM_OUT : needs = 0x1; break;
1738
case CELLREF_RELOCATE_ERR : return gnm_expr_new_constant (
1739
value_new_error_REF (NULL));
1741
switch (cellref_relocate (&ref_b, rinfo)) {
1742
case CELLREF_NO_RELOCATE : break;
1743
case CELLREF_RELOCATE_FROM_IN : needs = 0x4; break;
1744
case CELLREF_RELOCATE_FROM_OUT : needs |= 0x2; break;
1745
case CELLREF_RELOCATE_ERR :
1748
(rinfo->col_offset == 0 || rinfo->row_offset == 0)) {
1751
return gnm_expr_new_constant (
1752
value_new_error_REF (NULL));
1840
* C3 : =sum(a$1:b$2)
1842
* Paste to the right or diagonal.
1843
* range changes when it should not.
1845
if (!reloc_a || !reloc_b) {
1757
1847
Sheet const *sheet_a = ref_a.sheet;
1758
1848
Sheet const *sheet_b = ref_b.sheet;
1766
1856
/* Dont allow creation of 3D references */
1767
1857
if (sheet_a == sheet_b) {
1768
1858
/* If just 1 end is moving do not change the reference */
1769
if ((needs == 0x1 && cellref_shift (&ref_b, rinfo)) ||
1770
(needs == 0x2 && cellref_shift (&ref_a, rinfo)))
1859
if ((reloc_a == CELLREF_RELOCATE_FROM_OUT &&
1860
cellref_shift (&ref_b, rinfo)) ||
1861
(reloc_b == CELLREF_RELOCATE_FROM_OUT &&
1862
cellref_shift (&ref_a, rinfo)))
1772
1864
res = value_new_cellrange (&ref_a, &ref_b,
1773
rinfo->pos.eval.col,
1774
rinfo->pos.eval.row);
1865
rinfo->pos.eval.col + rinfo->col_offset,
1866
rinfo->pos.eval.row + rinfo->row_offset);
1776
1868
res = value_new_error_REF (NULL);
1785
* gnm_expr_rewrite :
1786
* @expr : Expression to fixup
1787
* @pos : Location of the cell containing @expr.
1788
* @rwinfo : State information required to rewrite the reference.
1792
* GNM_EXPR_REWRITE_INVALIDATE_SHEETS:
1794
* Find any references to sheets marked being_invalidated and
1795
* re-write them to #REF!
1799
* GNM_EXPR_REWRITE_RELOCATE:
1801
* Find any references to the specified area and adjust them by the
1802
* supplied deltas. Check for out of bounds conditions. Return NULL if
1803
* no change is required.
1805
* If the expression is within the range to be moved, its relative
1806
* references to cells outside the range are adjusted to reference the
1807
* same cell after the move.
1809
1876
static GnmExpr const *
1810
gnm_expr_rewrite (GnmExpr const *expr, GnmExprRewriteInfo const *rwinfo)
1877
gnm_expr_relocate (GnmExpr const *expr, GnmExprRelocateInfo const *rinfo,
1878
gboolean ignore_rel)
1812
1880
g_return_val_if_fail (expr != NULL, NULL);
1941
2008
case GNM_EXPR_OP_CELLREF:
1942
switch (rwinfo->rw_type) {
1943
case GNM_EXPR_REWRITE_INVALIDATE_SHEETS:
2009
switch (rinfo->reloc_type) {
2010
case GNM_EXPR_RELOCATE_INVALIDATE_SHEET:
1944
2011
if (expr->cellref.ref.sheet &&
1945
2012
expr->cellref.ref.sheet->being_invalidated)
1946
2013
return gnm_expr_new_constant (value_new_error_REF (NULL));
1949
case GNM_EXPR_REWRITE_NAME:
1951
2017
GnmCellRef res = expr->cellref.ref; /* Copy */
1953
switch (cellref_relocate (&res, &rwinfo->u.relocate)) {
2019
switch (relocate_cellref (rinfo, ignore_rel, &res)) {
1954
2020
case CELLREF_NO_RELOCATE :
1956
2022
case CELLREF_RELOCATE_FROM_IN :
1966
case GNM_EXPR_OP_CONSTANT: {
1967
GnmValue const *v = expr->constant.value;
1969
if (v->type == VALUE_CELLRANGE) {
1970
GnmCellRef const *ref_a = &v->v_range.cell.a;
1971
GnmCellRef const *ref_b = &v->v_range.cell.b;
1973
if (rwinfo->rw_type == GNM_EXPR_REWRITE_INVALIDATE_SHEETS) {
1974
Sheet *sheet_a = ref_a->sheet;
1975
Sheet *sheet_b = ref_b->sheet;
1977
gboolean hit_a = sheet_a && sheet_a->being_invalidated;
1978
gboolean hit_b = sheet_b && sheet_b->being_invalidated;
1981
if (!hit_a && !hit_b)
1984
if (sheet_a == NULL || sheet_b == NULL ||
1985
sheet_a->workbook != sheet_b->workbook)
1986
/* A 3D reference between workbooks? */
1987
return gnm_expr_new_constant (value_new_error_REF (NULL));
1989
wb = sheet_a->workbook;
1990
dir_a = (sheet_a->index_in_wb < sheet_b->index_in_wb) ? +1 : -1;
1992
/* Narrow the sheet range. */
1993
while (sheet_a != sheet_b && sheet_a->being_invalidated)
1994
sheet_a = workbook_sheet_by_index (wb, sheet_a->index_in_wb + dir_a);
1995
while (sheet_a != sheet_b && sheet_b->being_invalidated)
1996
sheet_b = workbook_sheet_by_index (wb, sheet_b->index_in_wb + dir_b);
1998
if (sheet_a->being_invalidated)
1999
return gnm_expr_new_constant (value_new_error_REF (NULL));
2001
GnmCellRef new_a = *ref_a;
2002
GnmCellRef new_b = *ref_b;
2004
new_a.sheet = sheet_a;
2005
new_b.sheet = sheet_b;
2006
return gnm_expr_new_constant (value_new_cellrange_unsafe (&new_a, &new_b));
2009
return cellrange_relocate (v, &rwinfo->u.relocate);
2032
case GNM_EXPR_OP_CONSTANT:
2033
if (expr->constant.value->type == VALUE_CELLRANGE)
2034
return relocate_cellrange (rinfo, ignore_rel,
2035
&expr->constant.value->v_range);
2015
2038
case GNM_EXPR_OP_ARRAY_ELEM:
2018
2041
case GNM_EXPR_OP_ARRAY_CORNER: {
2020
gnm_expr_rewrite (expr->array_corner.expr, rwinfo);
2042
GnmExpr const *e = gnm_expr_relocate (expr->array_corner.expr, rinfo, ignore_rel);
2022
return gnm_expr_new_array_corner
2023
(expr->array_corner.cols,
2024
expr->array_corner.rows,
2044
return gnm_expr_new_array_corner (
2045
expr->array_corner.cols,
2046
expr->array_corner.rows, e);
2469
2490
g_string_append_c (target, ')');
2472
/***************************************************************************/
2475
* Special hash function for expressions that assumes that equal
2476
* sub-expressions are pointer-equal. (Thus no need for recursion.)
2479
ets_hash (gconstpointer key)
2494
gnm_expr_hash (GnmExpr const *expr)
2481
GnmExpr const *expr = (GnmExpr const *)key;
2482
2496
guint h = (guint)(GNM_EXPR_GET_OPER (expr));
2484
2498
switch (GNM_EXPR_GET_OPER (expr)){
2485
2499
case GNM_EXPR_OP_INTERSECT:
2486
2500
case GNM_EXPR_OP_RANGE_CTOR:
2487
2501
case GNM_EXPR_OP_ANY_BINARY:
2488
return ((GPOINTER_TO_UINT (expr->binary.value_a) * 7) ^
2489
(GPOINTER_TO_UINT (expr->binary.value_b) * 3) ^
2502
return ((gnm_expr_hash (expr->binary.value_a) * 7) ^
2503
(gnm_expr_hash (expr->binary.value_b) * 3) ^
2492
2506
case GNM_EXPR_OP_ANY_UNARY:
2493
return ((GPOINTER_TO_UINT (expr->unary.value) * 7) ^
2507
return ((gnm_expr_hash (expr->unary.value) * 7) ^
2496
2510
case GNM_EXPR_OP_FUNCALL: {
2498
2512
for (i = 0; i < expr->func.argc; i++)
2499
h = (h * 3) ^ (GPOINTER_TO_UINT (expr->func.argv[i]));
2513
h = (h * 3) ^ gnm_expr_hash (expr->func.argv[i]);
2503
2517
case GNM_EXPR_OP_SET: {
2505
2519
for (i = 0; i < expr->set.argc; i++)
2506
h = (h * 3) ^ (GPOINTER_TO_UINT (expr->set.argv[i]));
2520
h = (h * 3) ^ gnm_expr_hash (expr->set.argv[i]);
2513
2527
case GNM_EXPR_OP_NAME:
2514
2528
/* all we need is a somewhat unique hash, ignore int != ptr */
2515
return (guint)(expr->name.name);
2529
return GPOINTER_TO_UINT (expr->name.name);
2517
2531
case GNM_EXPR_OP_CELLREF:
2518
2532
return gnm_cellref_hash (&expr->cellref.ref);
2520
2534
case GNM_EXPR_OP_ARRAY_CORNER:
2521
return ((GPOINTER_TO_UINT (expr->array_corner.expr) * 7) ^
2535
return gnm_expr_hash (expr->array_corner.expr);
2524
2537
case GNM_EXPR_OP_ARRAY_ELEM:
2525
return ((expr->array_elem.x * 7) ^
2526
(expr->array_elem.y * 3));
2538
return ((expr->array_elem.x << 16) ^
2539
(expr->array_elem.y));
2532
* Special equality function for expressions that assumes that equal
2533
* sub-expressions are pointer-equal. (Thus no need for recursion.)
2536
ets_equal (gconstpointer _a, gconstpointer _b)
2538
GnmExpr const *ea = _a;
2539
GnmExpr const *eb = _b;
2541
if (GNM_EXPR_GET_OPER (ea) != GNM_EXPR_GET_OPER (eb))
2544
switch (GNM_EXPR_GET_OPER (ea)) {
2545
case GNM_EXPR_OP_RANGE_CTOR:
2546
case GNM_EXPR_OP_INTERSECT:
2547
case GNM_EXPR_OP_ANY_BINARY:
2548
return (ea->binary.value_a == eb->binary.value_a &&
2549
ea->binary.value_b == eb->binary.value_b);
2550
case GNM_EXPR_OP_ANY_UNARY:
2551
return (ea->unary.value == eb->unary.value);
2552
case GNM_EXPR_OP_FUNCALL: {
2555
if (ea->func.func != eb->func.func ||
2556
ea->func.argc != eb->func.argc)
2559
for (i = 0; i < ea->func.argc; i++)
2560
if (ea->func.argv[i] != eb->func.argv[i])
2565
case GNM_EXPR_OP_SET: {
2568
if (ea->set.argc != eb->set.argc)
2571
for (i = 0; i < ea->set.argc; i++)
2572
if (ea->set.argv[i] != eb->set.argv[i])
2578
/* No sub-expressions. */
2579
return gnm_expr_equal (ea, eb);
2585
expr_tree_sharer_new (void)
2587
ExprTreeSharer *es = g_new (ExprTreeSharer, 1);
2588
es->nodes_in = es->nodes_stored = 0;
2589
es->exprs = g_hash_table_new (ets_hash, ets_equal);
2590
es->ptrs = g_hash_table_new (g_direct_hash, g_direct_equal);
2546
/***************************************************************************/
2549
gnm_expr_sharer_new (void)
2551
GnmExprSharer *es = g_new (GnmExprSharer, 1);
2553
es->nodes_stored = 0;
2554
es->nodes_killed = 0;
2555
es->exprs = g_hash_table_new_full
2556
((GHashFunc)gnm_expr_top_hash,
2557
(GEqualFunc)gnm_expr_top_equal,
2558
(GDestroyNotify)gnm_expr_top_unref,
2595
cb_ets_unref_key (gpointer key, G_GNUC_UNUSED gpointer value,
2596
G_GNUC_UNUSED gpointer user_data)
2604
expr_tree_sharer_destroy (ExprTreeSharer *es)
2564
gnm_expr_sharer_destroy (GnmExprSharer *es)
2606
g_hash_table_foreach (es->exprs, cb_ets_unref_key, NULL);
2607
2566
g_hash_table_destroy (es->exprs);
2608
g_hash_table_foreach (es->ptrs, cb_ets_unref_key, NULL);
2609
g_hash_table_destroy (es->ptrs);
2614
expr_tree_sharer_share (ExprTreeSharer *es, GnmExpr const *e)
2571
gnm_expr_sharer_share (GnmExprSharer *es, GnmExprTop const *texpr)
2573
GnmExprTop const *shared;
2575
g_return_val_if_fail (es != NULL, texpr);
2576
g_return_val_if_fail (texpr != NULL, NULL);
2580
/* Corners must not get shared. */
2581
if (GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_CORNER)
2584
shared = g_hash_table_lookup (es->exprs, texpr);
2586
gnm_expr_top_ref (shared);
2587
if (texpr->refcount == 1)
2589
gnm_expr_top_unref (texpr);
2593
gnm_expr_top_ref (texpr);
2594
g_hash_table_insert (es->exprs, (gpointer)texpr, (gpointer)texpr);
2619
2600
/***************************************************************************/
2735
2731
g_return_val_if_fail (IS_GNM_EXPR_TOP (te1), FALSE);
2736
2732
g_return_val_if_fail (IS_GNM_EXPR_TOP (te2), FALSE);
2734
if (te1->hash && te2->hash && te1->hash != te2->hash)
2738
2737
return gnm_expr_equal (te1->expr, te2->expr);
2741
* gnm_expr_top_relocate :
2742
* @expr : #GnmExprTop to fixup
2743
* @rinfo : #GnmExprRelocateInfo details of relocation
2744
* @ignore_rel : Do not adjust relative refs (for internal use when
2745
* relocating named expressions. Most callers will want FALSE.
2747
* GNM_EXPR_RELOCATE_INVALIDATE_SHEET :
2748
* Convert any references to sheets marked being_invalidated into #REF!
2749
* GNM_EXPR_RELOCATE_MOVE_RANGE,
2750
* Find any references to the specified area and adjust them by the
2751
* supplied deltas. Check for out of bounds conditions. Return NULL if
2752
* no change is required.
2753
* If the expression is within the range to be moved, its relative
2754
* references to cells outside the range are adjusted to reference the
2755
* same cell after the move.
2756
* GNM_EXPR_RELOCATE_COLS
2757
* GNM_EXPR_RELOCATE_ROWS
2741
2760
GnmExprTop const *
2742
gnm_expr_top_rewrite (GnmExprTop const *texpr,
2743
GnmExprRewriteInfo const *rwinfo)
2761
gnm_expr_top_relocate (GnmExprTop const *texpr,
2762
GnmExprRelocateInfo const *rinfo,
2763
gboolean ignore_rel)
2745
2765
g_return_val_if_fail (IS_GNM_EXPR_TOP (texpr), NULL);
2747
return gnm_expr_top_new (gnm_expr_rewrite (texpr->expr, rwinfo));
2767
return gnm_expr_top_new (gnm_expr_relocate (texpr->expr, rinfo, ignore_rel));
2862
2882
return GNM_EXPR_GET_OPER (texpr->expr) == GNM_EXPR_OP_ARRAY_ELEM;
2886
gnm_expr_top_transpose (GnmExprTop const *texpr)
2888
g_return_val_if_fail (IS_GNM_EXPR_TOP (texpr), NULL);
2889
switch (GNM_EXPR_GET_OPER (texpr->expr)) {
2890
case GNM_EXPR_OP_ARRAY_CORNER:
2891
/* Transpose size */
2892
return gnm_expr_top_new_array_corner
2893
(texpr->expr->array_corner.rows,
2894
texpr->expr->array_corner.cols,
2895
gnm_expr_copy (texpr->expr));
2896
case GNM_EXPR_OP_ARRAY_ELEM:
2897
/* Transpose coordinates */
2898
return gnm_expr_top_new_array_elem
2899
(texpr->expr->array_elem.y,
2900
texpr->expr->array_elem.x);
2865
2906
/****************************************************************************/
2867
2908
#if USE_EXPR_POOLS