예제 #1
0
파일: collect.c 프로젝트: paulfitz/gnumeric
/**
 * float_range_function2d:
 * @val0:
 * @val1:
 * @ei:
 * @func: (scope call):
 * @flags:
 * @func_error:
 *
 * Returns: (transfer full):
 **/
GnmValue *
float_range_function2d (GnmValue const *val0, GnmValue const *val1,
			GnmFuncEvalInfo *ei,
			float_range_function2d_t func,
			CollectFlags flags,
			GnmStdError func_error,
			gpointer data)
{
	gnm_float *vals0, *vals1;
	int n;
	GnmValue *res;
	gnm_float fres;
	gboolean constp = FALSE;

	res = collect_float_pairs (val0, val1, ei->pos, flags,
				   &vals0, &vals1, &n, &constp);
	if (res)
		return res;

	if (n <= 0)
		return value_new_error_std (ei->pos, func_error);

	if (func (vals0, vals1, n, &fres, data))
		res = value_new_error_std (ei->pos, func_error);
	else
		res = value_new_float (fres);

	if (!constp) {
		g_free (vals0);
		g_free (vals1);
	}
	return res;
}
예제 #2
0
파일: collect.c 프로젝트: paulfitz/gnumeric
/**
 * float_range_function:
 * @argc:
 * @argv:
 * @ei:
 * @func: (scope call):
 * @flags:
 * @func_error:
 *
 * Returns: (transfer full):
 **/
GnmValue *
float_range_function (int argc, GnmExprConstPtr const *argv,
		      GnmFuncEvalInfo *ei,
		      float_range_function_t func,
		      CollectFlags flags,
		      GnmStdError func_error)
{
	GnmValue *error = NULL;
	gnm_float *vals, res;
	int n, err;
	gboolean constp;

	vals = collect_floats (argc, argv, ei->pos, flags, &n, &error,
			       NULL, &constp);
	if (!vals)
		return error;

	err = func (vals, n, &res);
	if (!constp) g_free (vals);

	if (err)
		return value_new_error_std (ei->pos, func_error);
	else
		return value_new_float (res);
}
예제 #3
0
파일: collect.c 프로젝트: paulfitz/gnumeric
/**
 * string_range_function:
 * @argc:
 * @argv:
 * @ei:
 * @func: (scope call):
 * @flags:
 * @func_error:
 *
 * Returns: (transfer full):
 **/
GnmValue *
string_range_function (int argc, GnmExprConstPtr const *argv,
		       GnmFuncEvalInfo *ei,
		       string_range_function_t func,
		       CollectFlags flags,
		       GnmStdError func_error)
{
	GnmValue *error = NULL;
	GPtrArray *vals;
	char *res = NULL;
	int err;

	vals = collect_strings (argc, argv, ei->pos, flags, &error);
	if (!vals)
		return error;

	err = func (vals, &res);

	collect_strings_free (vals);

	if (err) {
		g_free (res);
		return value_new_error_std (ei->pos, func_error);
	} else {
		return value_new_string_nocopy (res);
	}
}
예제 #4
0
GnmValue *
gnm_ifs_func (GPtrArray *data, GPtrArray *crits, GnmValue const *vals,
	      float_range_function_t fun, GnmStdError err,
	      GnmEvalPos const *ep, CollectFlags flags)
{
	int sx, sy, x, y;
	unsigned ui, N = 0, nalloc = 0;
	gnm_float *xs = NULL;
	GnmValue *res = NULL;
	gnm_float fres;

	g_return_val_if_fail (data->len == crits->len, NULL);

	if (flags & ~(COLLECT_IGNORE_STRINGS |
		      COLLECT_IGNORE_BOOLS |
		      COLLECT_IGNORE_BLANKS |
		      COLLECT_IGNORE_ERRORS)) {
		g_warning ("unsupported flags in gnm_ifs_func %x", flags);
	}

	sx = value_area_get_width (vals, ep);
	sy = value_area_get_height (vals, ep);
	for (ui = 0; ui < data->len; ui++) {
		GnmValue const *datai = g_ptr_array_index (data, ui);
		if (value_area_get_width (datai, ep) != sx ||
		    value_area_get_height (datai, ep) != sy)
			return value_new_error_VALUE (ep);
	}

	for (y = 0; y < sy; y++) {
		for (x = 0; x < sx; x++) {
			GnmValue const *v;
			gboolean match = TRUE;

			for (ui = 0; match && ui < crits->len; ui++) {
				GnmCriteria *crit = g_ptr_array_index (crits, ui);
				GnmValue const *datai = g_ptr_array_index (data, ui);
				v = value_area_get_x_y (datai, x, y, ep);

				match = crit->fun (v, crit);
			}
			if (!match)
				continue;

			// Match.  Maybe collect the data point.

			v = value_area_get_x_y (vals, x, y, ep);
			if ((flags & COLLECT_IGNORE_STRINGS) && VALUE_IS_STRING (v))
				continue;
			if ((flags & COLLECT_IGNORE_BOOLS) && VALUE_IS_BOOLEAN (v))
				continue;
			if ((flags & COLLECT_IGNORE_BLANKS) && VALUE_IS_EMPTY (v))
				continue;
			if ((flags & COLLECT_IGNORE_ERRORS) && VALUE_IS_ERROR (v))
				continue;

			if (VALUE_IS_ERROR (v)) {
				res = value_dup (v);
				goto out;
			}

			if (N >= nalloc) {
				nalloc = (2 * nalloc) + 100;
				xs = g_renew (gnm_float, xs, nalloc);
			}
			xs[N++] = value_get_as_float (v);
		}
	}

	if (fun (xs, N, &fres)) {
		res = value_new_error_std (ep, err);
	} else
		res = value_new_float (fres);

out:
	g_free (xs);
	return res;
}
예제 #5
0
static GnmValue *
new_gnm_value_from_xloper (const XLOPER*x)
{
	GnmValue * g = NULL;
	if (NULL != x) {
		switch (x->xltype & xltypeType) {
		case xltypeNum:
			g = value_new_float (x->val.num);
			break;
		case xltypeStr: {
			char *o = NULL;
			const char *s = x->val.str;
			if (NULL != s) {
				guint m = ((unsigned char)s[0]) + 1U;
				o = g_new (char, m);
				g_strlcpy (o, s + 1, m);
			}
			g = value_new_string_nocopy (o);
			break;
		}
		case xltypeBool:
			g = value_new_bool (x->val.boolean);
			break;
		case xltypeRef:
			unsupported_xloper_type (x);
			break;
		case xltypeErr:
			g = value_new_error_std (NULL, gnm_value_error_from_xloper (x));
			break;
		case xltypeFlow:
			unsupported_xloper_type (x);
			break;
		case xltypeMulti: {
			guint m = x->val.array.columns;
			guint n = x->val.array.rows;
			if (m > 0 && n > 0) {
				guint i;
				g = value_new_array_empty (m,n);
				for (i = 0; i < m; ++i) {
					guint j;
					for (j = 0; j < n; ++j) {
						g->v_array.vals[i][j] =
							new_gnm_value_from_xloper (x->val.array.lparray + i + j * m);
					}
				}
			} else {
				g = value_new_error_std (NULL, GNM_ERROR_VALUE);
			}
			break;
		}
		case xltypeMissing:
			break;
		case xltypeNil:
			g = value_new_empty ();
			break;
		case xltypeSRef:
			unsupported_xloper_type (x);
			break;
		case xltypeInt:
			g = value_new_int (x->val.w);
			break;
		default:
			unsupported_xloper_type (x);
		}
	} else {
예제 #6
0
파일: functions.c 프로젝트: GNOME/gnumeric
static GnmValue *
gnumeric_periodogram (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
{
	gnm_float *ord, *absc;
	int filter, interp;
	int n0, n1, nb;
	GnmValue *error = NULL;
	GnmValue *res;
	CollectFlags flags;
	GnmEvalPos const * const ep = ei->pos;
	GnmValue const * const Pt = argv[0];
	int i;
	GSList *missing0 = NULL, *missing1 = NULL;
	gnm_complex *in, *out = NULL;

	int const cols = value_area_get_width (Pt, ep);
	int const rows = value_area_get_height (Pt, ep);

	if (cols == 1)
		nb=rows;
	else {
		if (rows == 1)
			nb=cols;
		else
			nb=0;
	}

	if (nb == 0) {
		res = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
		return res;
	}

	flags=COLLECT_IGNORE_BLANKS | COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_BOOLS;

	ord = collect_floats_value_with_info (argv[0], ei->pos, flags,
					      &n0, &missing0, &error);
	if (error) {
		g_slist_free (missing0);
		return error;
	}

	if (n0 == 0) {
		res = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
		return res;
	}

	if (argv[1]) {
		filter = (int) gnm_floor (value_get_as_float (argv[1]));
		if (filter < 0 || filter > FILTER_WELCH) {
			g_slist_free (missing0);
			g_free (ord);
			res = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
			return res;
		}
	} else
		filter = FILTER_NONE;

	if (argv[2]) {
		gnm_float *interpolated, *new_ord, start, incr;
		int n2;
		INTERPPROC(interpproc) = NULL;
		absc = collect_floats_value_with_info (argv[2], ei->pos, flags,
						       &n1, &missing1, &error);
		if (n1 == 1) {
			g_slist_free (missing1);
			g_free (absc);
			goto no_absc;
		}
		if (error) {
			g_slist_free (missing0);
			g_slist_free (missing1);
			g_free (absc);
			return error;
		}
		if (n1 == 0) {
			g_slist_free (missing0);
			g_slist_free (missing1);
			g_free (absc);
			g_free (ord);
			return value_new_error_std (ei->pos, GNM_ERROR_VALUE);
		}
		if (argv[3]) {
			interp = (int) gnm_floor (value_get_as_float (argv[3]));
			if (interp < 0 || interp > INTERPOLATION_SPLINE_AVG) {
				g_slist_free (missing0);
				g_slist_free (missing1);
				g_free (absc);
				g_free (ord);
				return error;
			}
		} else
			interp = INTERPOLATION_LINEAR;

		if (missing0 || missing1) {
			GSList *missing = gnm_slist_sort_merge (missing0, missing1);
			gnm_strip_missing (ord, &n0, missing);
			gnm_strip_missing (absc, &n1, missing);
			g_slist_free (missing);

			if (n0 != n1)
				g_warning ("This should not happen. n0=%d n1=%d\n",
					   n0, n1);
		}
		n0 = n1 = MIN (n0, n1);
		/* here we test if there is abscissas are always increasing, if not,
		   an error is returned */
		if (n0 < 2 || !gnm_range_increasing (absc, n0) || n0 == 0) {
			g_free (absc);
			g_free (ord);
			return value_new_error_std (ei->pos, GNM_ERROR_VALUE);
		}
		if (argv[4]) {
			n1 = (int) gnm_floor (value_get_as_float (argv[4]));
			if (n1 < n0) {
				g_free (absc);
				g_free (ord);
				return value_new_error_std (ei->pos, GNM_ERROR_VALUE);
			}
			nb = 1;
			while (nb < n1)
				nb *= 2;
		} else {
			n1 = 1;
			while (n1 < n0)
				n1 *= 2;
			nb = n1;
		}
		incr = (absc[n0 - 1] - absc[0]) / n1;
		switch (interp) {
		case INTERPOLATION_LINEAR:
			interpproc = linear_interpolation;
			start = absc[0];
			n2 = n1;
			break;
		case INTERPOLATION_LINEAR_AVG:
			interpproc = linear_averaging;
			start = absc[0] - incr / 2.;
			n2 = n1 + 1;
			break;
		case INTERPOLATION_STAIRCASE:
			interpproc = staircase_interpolation;
			start = absc[0];
			n2 = n1;
			break;
		case INTERPOLATION_STAIRCASE_AVG:
			interpproc = staircase_averaging;
			start = absc[0] - incr / 2.;
			n2 = n1 + 1;
			break;
		case INTERPOLATION_SPLINE:
			interpproc = spline_interpolation;
			start = absc[0];
			n2 = n1;
			break;
		case INTERPOLATION_SPLINE_AVG:
			interpproc = spline_averaging;
			start = absc[0] - incr / 2.;
			n2 = n1 + 1;
			break;
		default:
			g_free (absc);
			g_free (ord);
			return value_new_error_std (ei->pos, GNM_ERROR_NA);
		}
		interpolated = g_new (gnm_float, n1);
		for (i = 0; i < n2; i++)
			interpolated[i] = start + i * incr;
		new_ord = interpproc (absc, ord, n0, interpolated, n1);
		g_free (ord);
		ord = new_ord;
		if (ord == NULL) {
			g_free (absc);
			g_free (interpolated);
			return value_new_error_std (ei->pos, GNM_ERROR_NA);
		}
		n0 = n1;
	} else {
no_absc:
		/* we have no interpolation to apply, so just take the values */
		if (missing0) {
			gnm_strip_missing (ord, &n0, missing0);
			g_slist_free (missing0);
		}
		nb = 1;
		while (nb < n0)
			nb *= 2;
	}

	/* Now apply the filter if any */
	if (filter != FILTER_NONE) {
		gnm_float factor;
		switch (filter) {
		case FILTER_BARTLETT:
			factor = n0 / 2.;
			for (i = 0; i < n0; i++)
				ord[i] *= 1. - gnm_abs ((i / factor - 1));
			break;
		case FILTER_HANN:
			factor = 2. * M_PIgnum / n0;
			for (i = 0; i < n0; i++)
				ord[i] *= 0.5 * (1 - gnm_cos (factor * i));
			break;
		case FILTER_WELCH:
			factor = n0 / 2.;
			for (i = 0; i < n0; i++)
				ord[i] *= 1. - (i / factor - 1.) * (i / factor - 1.);
			break;
		}
	}

	/* Transform and return the result */
	in = g_new0 (gnm_complex, nb);
	for (i = 0; i < n0; i++){
		in[i].re = ord[i];
	}
	g_free (ord);
	gnm_fourier_fft (in, nb, 1, &out, FALSE);
	g_free (in);
	nb /= 2;
	if (out && nb > 0) {
		res = value_new_array_non_init (1 , nb);
		res->v_array.vals[0] = g_new (GnmValue *, nb);
		for (i = 0; i < nb; i++)
			res->v_array.vals[0][i] =
				value_new_float (gnm_sqrt (
							 out[i].re * out[i].re +
							 out[i].im * out[i].im));
		g_free (out);
	} else
예제 #7
0
파일: functions.c 프로젝트: GNOME/gnumeric
static GnmValue *
gnumeric_interpolation (GnmFuncEvalInfo *ei, GnmValue const * const *argv)
{
	gnm_float *vals0, *vals1, *vals2, *fres;
	int n0, n2;
	int interp;
	GnmValue *error = NULL;
	GnmValue *res;
	CollectFlags flags;
	GnmEvalPos const * const ep = ei->pos;
	GnmValue const * const PtInterpolation = argv[2];
	int r, i;
	GSList *missing2 = NULL, *missing;
	INTERPPROC interpproc = NULL;
	gboolean constp = FALSE;

	/* argv[2] */

	int const cols = value_area_get_width (PtInterpolation, ep);
	int const rows = value_area_get_height (PtInterpolation, ep);

	if (rows == 0 || cols != 1) {
		res = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
		return res;
	}

	flags = COLLECT_IGNORE_BLANKS | COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_BOOLS | COLLECT_IGNORE_ERRORS;
	vals2 = collect_floats_value_with_info (PtInterpolation, ei->pos, flags,
						&n2, &missing2, &error);
	if (error) {
		g_slist_free (missing2);
		return error;
	}

	/* argv[3] */

	if (argv[3]) {
		interp = (int) gnm_floor (value_get_as_float (argv[3]));
		if (interp < 0 || interp > INTERPOLATION_SPLINE_AVG) {
			g_slist_free (missing2);
			g_free (vals2);
			return value_new_error_VALUE (ei->pos);
		}
	} else
		interp = INTERPOLATION_LINEAR;

	switch (interp) {
	case INTERPOLATION_LINEAR:
		interpproc = linear_interpolation;
		break;
	case INTERPOLATION_LINEAR_AVG:
		interpproc = linear_averaging;
		n2--;
		break;
	case INTERPOLATION_STAIRCASE:
		interpproc = staircase_interpolation;
		break;
	case INTERPOLATION_STAIRCASE_AVG:
		interpproc = staircase_averaging;
		n2--;
		break;
	case INTERPOLATION_SPLINE:
		interpproc = spline_interpolation;
		break;
	case INTERPOLATION_SPLINE_AVG:
		interpproc = spline_averaging;
		n2--;
		break;
	}

	if (n2 <= 0) {
		g_slist_free (missing2);
		g_free (vals2);
		return value_new_error_std (ei->pos, GNM_ERROR_VALUE);
	}

	/* argv[0] & argv[1] */

	flags = COLLECT_IGNORE_BLANKS | COLLECT_IGNORE_STRINGS | COLLECT_IGNORE_BOOLS;
	error = collect_float_pairs (argv[0], argv[1], ei->pos, flags, &vals0, &vals1,
				     &n0, &constp);

	if (error) {
		g_slist_free (missing2);
		g_free (vals2);
		return error;
	}

	/* Check whether the abscissae are increasing, if not order them */
	if (!gnm_range_increasing (vals0, n0)) {
		gboolean switched = TRUE;
		if (constp) {
			vals0 = g_memdup (vals0, sizeof(gnm_float) * n0);
			vals1 = g_memdup (vals1, sizeof(gnm_float) * n0);
			constp = FALSE;
		}
		while (switched) {
			gnm_float *val;
			switched = FALSE;
			for (i = 1, val = vals0; i < n0; i++, val++) {
				if (*val == *(val + 1)) {
					res = value_new_error_std (ei->pos, GNM_ERROR_VALUE) ;
					goto done;
				}
				if (*val > *(val + 1)) {
					gnm_float v = *val;
					*val = *(val + 1);
					*(val + 1) = v;
					v = *(vals1 + i);
					*(vals1 + i) = *(vals1 + i - 1);
					*(vals1 + i - 1) = v;
					switched = TRUE;
				}
			}
		}
	}

	{
		int n = n2;

		if (missing2)
			gnm_strip_missing (vals2, &n, missing2);
		res = value_new_array_non_init (1 , n2);
		i = 0;

		res->v_array.vals[0] = g_new (GnmValue *, n2);

		fres = interpproc (vals0, vals1, n0, vals2, n);
		missing = missing2;
		if (fres) {
			i = 0;
			for (r = 0 ; r < n2; ++r)
				if (missing && r == GPOINTER_TO_INT (missing->data)) {
					missing = missing->next;
					res->v_array.vals[0][r] = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
				} else
					res->v_array.vals[0][r] = value_new_float (fres[i++]);
			g_free (fres);
		} else {
			for( r = 0 ; r < n2; ++r)
				res->v_array.vals[0][r] = value_new_error_std (ei->pos, GNM_ERROR_VALUE);
		}

	}

 done:
	g_slist_free (missing2);
	if (!constp) {
		g_free (vals0);
		g_free (vals1);
	}
	g_free (vals2);
	return res;
}