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

Fixes #361074 (bin_array_iter_a) : split out of the old bin_array_op, and

2006-10-16  Jody Goldberg <jody@gnome.org>

	* src/expr.c : Fixes #361074
	(bin_array_iter_a) : split out of the old bin_array_op, and handle the
	  more complex iteration cases of different shaped arguments.  See
	  samples/array.xls for details.
	(bin_array_iter_b) : split from bin_array_op and handle the simple
	  case of f(scalar,array).
	(gnm_expr_eval) : adjust to new binary array iterator functions.
parent b80de3c3
2006-10-16 Jody Goldberg <jody@gnome.org>
* src/expr.c : Fixes #361074
(bin_array_iter_a) : split out of the old bin_array_op, and handle the
more complex iteration cases of different shaped arguments. See
samples/array.xls for details.
(bin_array_iter_b) : split from bin_array_op and handle the simple
case of f(scalar,array).
(gnm_expr_eval) : adjust to new binary array iterator functions.
2006-10-16 Jon K Hellan <hellan@acm.org> 2006-10-16 Jon K Hellan <hellan@acm.org>
* src/main-application.c (main): Increase stack limit. * src/main-application.c (main): Increase stack limit.
......
...@@ -5,6 +5,7 @@ Emmanuel : ...@@ -5,6 +5,7 @@ Emmanuel :
Jody : Jody :
* Fix off by one pt, printing vertical borders in RTL mode. [#317662] * Fix off by one pt, printing vertical borders in RTL mode. [#317662]
* Handle the last (we hope) MS XL array iteration. [#361074]
Jon Kåre: Jon Kåre:
* Fix import of certain hyperlinks from Excel. * Fix import of certain hyperlinks from Excel.
......
No preview for this file type
...@@ -851,15 +851,25 @@ typedef struct { ...@@ -851,15 +851,25 @@ typedef struct {
GnmValue *res; GnmValue *res;
GnmValue const *a, *b; GnmValue const *a, *b;
BinOpImplicitIteratorFunc func; BinOpImplicitIteratorFunc func;
/* multiply by 0 in unused dimensions.
* this is simpler than lots of conditions
* state->use_x.a ? x : 0
**/
struct {
int a, b;
} x, y;
gpointer user_data; gpointer user_data;
} BinOpImplicitIteratorState; } BinOpImplicitIteratorState;
static GnmValue * static GnmValue *
cb_implicit_iter_a_to_b (GnmValue const *v, GnmEvalPos const *ep, cb_implicit_iter_a_and_b (GnmValue const *v, GnmEvalPos const *ep,
int x, int y, BinOpImplicitIteratorState const *state) int x, int y, BinOpImplicitIteratorState const *state)
{ {
state->res->v_array.vals [x][y] = (*state->func) (ep, state->res->v_array.vals [x][y] = (*state->func) (ep,
v, value_area_get_x_y (state->b, x, y, ep), state->user_data); value_area_get_x_y (state->a, state->x.a * x, state->y.a * y, ep),
value_area_get_x_y (state->b, state->x.b * x, state->y.b * y, ep),
state->user_data);
return NULL; return NULL;
} }
static GnmValue * static GnmValue *
...@@ -870,6 +880,65 @@ cb_implicit_iter_a_to_scalar_b (GnmValue const *v, GnmEvalPos const *ep, ...@@ -870,6 +880,65 @@ cb_implicit_iter_a_to_scalar_b (GnmValue const *v, GnmEvalPos const *ep,
v, state->b, state->user_data); v, state->b, state->user_data);
return NULL; return NULL;
} }
/* This is only triggered if something returns an array or a range which can
* only happen if we are in array eval mode. */
static GnmValue *
bin_array_iter_a (GnmEvalPos const *ep,
GnmValue *a, GnmValue *b,
BinOpImplicitIteratorFunc func,
GnmExpr const *expr)
{
BinOpImplicitIteratorState iter_info;
/* a must be a cellrange or array, it can not be NULL */
iter_info.func = func;
iter_info.user_data = (gpointer) expr;
iter_info.a = a;
iter_info.b = b;
/* matrix to matrix
* Use matching positions unless the dimension is singular, in which
* case use the zero item
* res[x][y] = f(a[singular.a.x ? 0 : x, b[singular.b.x ? 0 : x)
*
* If both items have non-singular sizes for
* the same dimension use the min size (see samples/array.xls) */
if (b != NULL &&
(b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)) {
int sa, sb, w = 1, h = 1;
sa = value_area_get_width (a, ep);
sb = value_area_get_width (b, ep);
if ((iter_info.x.a = (sa == 1) ? 0 : 1))
w = sa;
if ((iter_info.x.b = (sb == 1) ? 0 : 1) && (w > sb || w == 1))
w = sb;
sa = value_area_get_height (a, ep);
sb = value_area_get_height (b, ep);
if ((iter_info.y.a = (sa == 1) ? 0 : 1))
h = sa;
if ((iter_info.y.b = (sb == 1) ? 0 : 1) && (h > sb || h == 1))
h = sb;
iter_info.res = value_new_array_empty (w, h);
value_area_foreach (iter_info.res, ep, CELL_ITER_ALL,
(ValueAreaFunc) cb_implicit_iter_a_and_b, &iter_info);
} else {
iter_info.res = value_new_array_empty (
value_area_get_width (a, ep),
value_area_get_height (a, ep));
value_area_foreach (a, ep, CELL_ITER_ALL,
(ValueAreaFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
}
value_release (a);
if (b != NULL)
value_release (b);
return iter_info.res;
}
static GnmValue * static GnmValue *
cb_implicit_iter_b_to_scalar_a (GnmValue const *v, GnmEvalPos const *ep, cb_implicit_iter_b_to_scalar_a (GnmValue const *v, GnmEvalPos const *ep,
int x, int y, BinOpImplicitIteratorState const *state) int x, int y, BinOpImplicitIteratorState const *state)
...@@ -878,39 +947,29 @@ cb_implicit_iter_b_to_scalar_a (GnmValue const *v, GnmEvalPos const *ep, ...@@ -878,39 +947,29 @@ cb_implicit_iter_b_to_scalar_a (GnmValue const *v, GnmEvalPos const *ep,
state->a, v, state->user_data); state->a, v, state->user_data);
return NULL; return NULL;
} }
static GnmValue * static GnmValue *
bin_array_op (GnmEvalPos const *ep, GnmValue const *sizer, bin_array_iter_b (GnmEvalPos const *ep,
GnmValue *a, GnmValue *b, GnmValue *a, GnmValue *b,
BinOpImplicitIteratorFunc func, gpointer user_data) BinOpImplicitIteratorFunc func,
GnmExpr const *expr)
{ {
BinOpImplicitIteratorState iter_info; BinOpImplicitIteratorState iter_info;
if (sizer != a || b == NULL || !VALUE_IS_ERROR (b)) { iter_info.func = func;
iter_info.func = func; iter_info.user_data = (gpointer) expr;
iter_info.user_data = user_data; iter_info.a = a;
iter_info.a = a; iter_info.b = b;
iter_info.b = b;
iter_info.res = value_new_array_empty ( /* b must be a cellrange or array, it can not be NULL */
value_area_get_width (sizer, ep), iter_info.res = value_new_array_empty (
value_area_get_height (sizer, ep)); value_area_get_width (b, ep),
if (sizer == b) value_area_get_height (b, ep));
value_area_foreach (b, ep, CELL_ITER_ALL, value_area_foreach (b, ep, CELL_ITER_ALL,
(ValueAreaFunc) cb_implicit_iter_b_to_scalar_a, &iter_info); (ValueAreaFunc) cb_implicit_iter_b_to_scalar_a, &iter_info);
else if (b != NULL &&
(b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY))
value_area_foreach (a, ep, CELL_ITER_ALL,
(ValueAreaFunc) cb_implicit_iter_a_to_b, &iter_info);
else
value_area_foreach (a, ep, CELL_ITER_ALL,
(ValueAreaFunc) cb_implicit_iter_a_to_scalar_b, &iter_info);
} else
/* you have to love the asymmetry of MS XL */
iter_info.res = value_new_error_VALUE (ep);
if (a != NULL) if (a != NULL)
value_release (a); value_release (a);
if (b != NULL) value_release (b);
value_release (b);
return iter_info.res; return iter_info.res;
} }
...@@ -1052,10 +1111,10 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos, ...@@ -1052,10 +1111,10 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
if (VALUE_IS_ERROR (a)) if (VALUE_IS_ERROR (a))
return a; return a;
if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY) if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)
return bin_array_op (pos, a, a, return bin_array_iter_a (pos, a,
gnm_expr_eval (expr->binary.value_b, pos, flags), gnm_expr_eval (expr->binary.value_b, pos, flags),
(BinOpImplicitIteratorFunc) cb_bin_cmp, (BinOpImplicitIteratorFunc) cb_bin_cmp,
(gpointer) expr); expr);
} }
b = gnm_expr_eval (expr->binary.value_b, pos, flags); b = gnm_expr_eval (expr->binary.value_b, pos, flags);
...@@ -1066,9 +1125,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos, ...@@ -1066,9 +1125,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
return b; return b;
} }
if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY) if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
return bin_array_op (pos, b, a, b, return bin_array_iter_b (pos, a, b,
(BinOpImplicitIteratorFunc) cb_bin_cmp, (BinOpImplicitIteratorFunc) cb_bin_cmp,
(gpointer) expr); expr);
} }
res = bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), pos); res = bin_cmp (GNM_EXPR_GET_OPER (expr), value_compare (a, b, FALSE), pos);
...@@ -1117,9 +1176,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos, ...@@ -1117,9 +1176,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
value_release (b); value_release (b);
b = (res == NULL) ? value_new_error_VALUE (pos) : res; b = (res == NULL) ? value_new_error_VALUE (pos) : res;
} }
return bin_array_op (pos, a, a, b, return bin_array_iter_a (pos, a, b,
(BinOpImplicitIteratorFunc) cb_bin_arith, (BinOpImplicitIteratorFunc) cb_bin_arith,
(gpointer) expr); expr);
} else if (!VALUE_IS_NUMBER (a)) { } else if (!VALUE_IS_NUMBER (a)) {
value_release (a); value_release (a);
return value_new_error_VALUE (pos); return value_new_error_VALUE (pos);
...@@ -1144,9 +1203,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos, ...@@ -1144,9 +1203,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
} }
b = tmp; b = tmp;
} else if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY) } else if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
return bin_array_op (pos, b, a, b, return bin_array_iter_b (pos, a, b,
(BinOpImplicitIteratorFunc) cb_bin_arith, (BinOpImplicitIteratorFunc) cb_bin_arith,
(gpointer) expr); expr);
else if (!VALUE_IS_NUMBER (b)) { else if (!VALUE_IS_NUMBER (b)) {
value_release (a); value_release (a);
value_release (b); value_release (b);
...@@ -1209,10 +1268,10 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos, ...@@ -1209,10 +1268,10 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
if (VALUE_IS_ERROR (a)) if (VALUE_IS_ERROR (a))
return a; return a;
if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY) if (a->type == VALUE_CELLRANGE || a->type == VALUE_ARRAY)
return bin_array_op (pos, a, a, return bin_array_iter_a (pos, a,
gnm_expr_eval (expr->binary.value_b, pos, flags), gnm_expr_eval (expr->binary.value_b, pos, flags),
(BinOpImplicitIteratorFunc) cb_bin_cat, (BinOpImplicitIteratorFunc) cb_bin_cat,
(gpointer) expr); expr);
} }
b = gnm_expr_eval (expr->binary.value_b, pos, flags); b = gnm_expr_eval (expr->binary.value_b, pos, flags);
if (b != NULL) { if (b != NULL) {
...@@ -1222,9 +1281,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos, ...@@ -1222,9 +1281,9 @@ gnm_expr_eval (GnmExpr const *expr, GnmEvalPos const *pos,
return b; return b;
} }
if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY) if (b->type == VALUE_CELLRANGE || b->type == VALUE_ARRAY)
return bin_array_op (pos, b, a, b, return bin_array_iter_b (pos, a, b,
(BinOpImplicitIteratorFunc) cb_bin_cat, (BinOpImplicitIteratorFunc) cb_bin_cat,
(gpointer) expr); expr);
} }
if (a == NULL) { if (a == NULL) {
......
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