Commit 8320f8c8 authored by Morten Welinder's avatar Morten Welinder Committed by Morten Welinder

New stuff.

2002-02-19  Morten Welinder  <terra@diku.dk>

	* src/numbers.h (modfgnum, strtgnum, GNUM_FORMAT_[eEfg],
 	GNUM_DIG): New stuff.

  	* .../*.[cy]: All relevant strtod changed to strtognum; modf to
 	modfgnum; DBL_DIG to GNUM_DIG; formats changed to use
 	GNUM_FORMAT_...

	* src/gutils.c (strtognum): If needed, define a version here.

	* src/complex.c (complex_to_string): Use right format for
 	imaginary part.

	* configure.in: Add support for --with-long-double.

	* acconfig.h: Add WITH_LONG_DOUBLE.
parent 95081efd
2002-02-19 Morten Welinder <terra@diku.dk>
* src/numbers.h (modfgnum, strtgnum, GNUM_FORMAT_[eEfg],
GNUM_DIG): New stuff.
* .../*.[cy]: All relevant strtod changed to strtognum; modf to
modfgnum; DBL_DIG to GNUM_DIG; formats changed to use
GNUM_FORMAT_...
* src/gutils.c (strtognum): If needed, define a version here.
* src/complex.c (complex_to_string): Use right format for
imaginary part.
* configure.in: Add support for --with-long-double.
* acconfig.h: Add WITH_LONG_DOUBLE.
2002-02-19 Jody Goldberg <jody@gnome.org>
http://bugzilla.gnome.org/show_bug.cgi?id=69362
......
......@@ -51,6 +51,7 @@ Morten:
* Fix validation's use of abs to be fabs.
* Improve random number generation using /dev/urandom device.
* Fix Oleo plugin's isdigit usage.
* Support for --with-long-double
--------------------------------------------------------------------------
Gnumeric 1.0.3
......
2002-02-19 Morten Welinder <terra@diku.dk>
* src/numbers.h (modfgnum, strtgnum, GNUM_FORMAT_[eEfg],
GNUM_DIG): New stuff.
* .../*.[cy]: All relevant strtod changed to strtognum; modf to
modfgnum; DBL_DIG to GNUM_DIG; formats changed to use
GNUM_FORMAT_...
* src/gutils.c (strtognum): If needed, define a version here.
* src/complex.c (complex_to_string): Use right format for
imaginary part.
* configure.in: Add support for --with-long-double.
* acconfig.h: Add WITH_LONG_DOUBLE.
2002-02-19 Jody Goldberg <jody@gnome.org>
http://bugzilla.gnome.org/show_bug.cgi?id=69362
......
2002-02-19 Morten Welinder <terra@diku.dk>
* src/numbers.h (modfgnum, strtgnum, GNUM_FORMAT_[eEfg],
GNUM_DIG): New stuff.
* .../*.[cy]: All relevant strtod changed to strtognum; modf to
modfgnum; DBL_DIG to GNUM_DIG; formats changed to use
GNUM_FORMAT_...
* src/gutils.c (strtognum): If needed, define a version here.
* src/complex.c (complex_to_string): Use right format for
imaginary part.
* configure.in: Add support for --with-long-double.
* acconfig.h: Add WITH_LONG_DOUBLE.
2002-02-19 Jody Goldberg <jody@gnome.org>
http://bugzilla.gnome.org/show_bug.cgi?id=69362
......
......@@ -22,5 +22,6 @@
#undef ENABLE_GNOME
#undef HAVE_PSPELL
#undef ENABLE_EVOLUTION
#undef WITH_LONG_DOUBLE
@BOTTOM@
......@@ -63,6 +63,37 @@ if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
unset option
fi
float_msg=double
have_ld=no
AC_ARG_WITH(long_double,
[--{with,without}-long-double Use long double for floating point],
[if test "x$withval" = xyes; then
AC_C_LONG_DOUBLE
if test "$ac_cv_c_long_double" != "yes"; then
AC_MSG_ERROR([Long double type is not available.])
fi
AC_CHECK_FUNCS(strtold modfl string_to_decimal decimal_to_quadruple)
AC_CHECK_HEADERS(floatingpoint.h)
if test "$ac_cv_func_strtold" = "yes"; then
true
elif test "$ac_cv_func_string_to_decimal" = "yes" -a \
"$ac_cv_func_decimal_to_quadruple" = "yes" -a \
"$ac_cv_header_floatingpoint_h" = "yes"; then
true
else
AC_MSG_WARN([You lack the strtold function -- precision will be impaired])
fi
if test "$ac_cv_func_modfl" != "yes"; then
AC_MSG_WARN([You lack the modfl function -- precision will be impaired])
fi
float_msg="long double (EXPERIMENTAL)"
AC_MSG_WARN([Long double support is experimental -- expect problems])
AC_DEFINE(WITH_LONG_DOUBLE)
fi]
)
dnl ****************************
dnl MS Excel (tm) Plugin
dnl ****************************
......@@ -541,9 +572,10 @@ WARNING WARNING WARNING
Configuration:
Source code location: ${srcdir}
Compiler: ${CC}
Compiler: ${CC}
Floating point type: ${float_msg}
MS Excel Support : ${excel_msg}
MS Excel Support: ${excel_msg}
GDA support: ${gda_msg}
GB support: ${gb_msg}
......
......@@ -561,9 +561,9 @@ value_new_complex (const complex_t *c, char imunit)
if (complex_real_p (c))
return value_new_float (c->re);
else {
char *s, f[5 + 4 * sizeof (int)];
char *s, f[5 + 4 * sizeof (int) + strlen (GNUM_FORMAT_g)];
Value *res;
sprintf (f, "%%.%dg", DBL_DIG);
sprintf (f, "%%.%d" GNUM_FORMAT_g, GNUM_DIG);
s = complex_to_string (c, f, f, imunit);
res = value_new_string (s);
g_free (s);
......
......@@ -44,7 +44,7 @@ complex_to_string (const complex_t *src, const char *reformat,
} else if (src->im == -1) {
sign = "-";
} else {
im_buffer = g_strdup_printf (reformat, src->im);
im_buffer = g_strdup_printf (imformat, src->im);
if (re_buffer && *im_buffer != '-' && *im_buffer != '+')
sign = (src->im >= 0) ? "+" : "-";
}
......@@ -95,7 +95,7 @@ complex_from_string (complex_t *dst, const char *src, char *imunit)
}
errno = 0;
x = strtod (src, &end);
x = strtognum (src, &end);
if (src == end || errno == ERANGE)
return -1;
src = end;
......@@ -120,7 +120,7 @@ complex_from_string (complex_t *dst, const char *src, char *imunit)
return 0;
}
y = strtod (src, &end);
y = strtognum (src, &end);
if (src == end || errno == ERANGE)
return -1;
src = end;
......
......@@ -71,7 +71,7 @@ format_get_decimal (void)
if (lc == NULL)
lc = localeconv ();
/* NOTE : Use decimal_point _not_ mon_decimal_point. strtod uses this
/* NOTE : Use decimal_point _not_ mon_decimal_point. strtognum uses this
* and we get very confused when they are different (eg ru_RU)
*/
res = lc->decimal_point[0];
......@@ -490,7 +490,7 @@ format_compile (StyleFormat *format)
/* fall back on 0 for errors */
errno = 0;
entry->restriction_value = strtod (begin, (char **)&end);
entry->restriction_value = strtognum (begin, (char **)&end);
if (errno == ERANGE || begin == end)
entry->restriction_value = 0.;
break;
......@@ -667,7 +667,7 @@ render_number (GString *result,
gnum_float delta = 5 * gpow10 (-right_allowed - 1);
number += delta;
}
frac_part = modf (gnumeric_add_epsilon (number), &int_part);
frac_part = modfgnum (gnumeric_add_epsilon (number), &int_part);
*num = '\0';
group = (info->group_thousands) ? 3 : -1;
......@@ -1084,7 +1084,7 @@ format_number (gnum_float number, int col_width, StyleFormatEntry const *entry)
else
break;
sprintf (buffer, is_lower ? "%s%.*e" : "%s%.*E",
sprintf (buffer, is_lower ? "%s%.*" GNUM_FORMAT_e : "%s%.*E" GNUM_FORMAT_E,
info.negative ? "-" :
shows_plus ? "+" : "",
prec, number);
......@@ -1418,7 +1418,7 @@ fmt_general_float (gnum_float val, float col_width)
int log_val, prec;
if (col_width < 0.)
return g_strdup_printf ("%.*g", DBL_DIG, val);
return g_strdup_printf ("%.*" GNUM_FORMAT_g, GNUM_DIG, val);
if (val < 0.) {
/* leave space for minus sign */
......@@ -1460,11 +1460,11 @@ fmt_general_float (gnum_float val, float col_width)
if (prec < 1)
prec = 1;
else if (prec > DBL_DIG)
prec = DBL_DIG;
else if (prec > GNUM_DIG)
prec = GNUM_DIG;
/* FIXME : glib bug. it does not handle G, use g (fixed in 1.2.9) */
return g_strdup_printf ("%.*g", prec, val);
return g_strdup_printf ("%.*" GNUM_FORMAT_g, prec, val);
}
/**
......@@ -1490,7 +1490,7 @@ fmt_general_int (int val, int col_width)
if (log_val > col_width)
/* FIXME : glib bug. it does not handle G, use g */
/* Decrease available width by 5 to account for .+E00 */
return g_strdup_printf ("%.*g", col_width - 5, (double)val);
return g_strdup_printf ("%.*" GNUM_FORMAT_g, col_width - 5, (double)val);
}
return g_strdup_printf ("%d", val);
}
......@@ -1597,7 +1597,7 @@ number_format_init (void)
{
style_format_hash = g_hash_table_new (g_str_hash, g_str_equal);
/* FIXME: should be related to gnum_float, not double: */
beyond_precision = gpow10 (DBL_DIG + 1);
beyond_precision = gpow10 (GNUM_DIG + 1);
}
void
......
......@@ -561,9 +561,9 @@ value_new_complex (const complex_t *c, char imunit)
if (complex_real_p (c))
return value_new_float (c->re);
else {
char *s, f[5 + 4 * sizeof (int)];
char *s, f[5 + 4 * sizeof (int) + strlen (GNUM_FORMAT_g)];
Value *res;
sprintf (f, "%%.%dg", DBL_DIG);
sprintf (f, "%%.%d" GNUM_FORMAT_g, GNUM_DIG);
s = complex_to_string (c, f, f, imunit);
res = value_new_string (s);
g_free (s);
......
......@@ -184,8 +184,8 @@ goal_seek_newton (GoalSeekFunction f, GoalSeekFunction df,
return status;
#ifdef DEBUG_GOAL_SEEK
printf ("x0 = %.20g\n", x0);
printf (" y0 = %.20g\n", y0);
printf ("x0 = %.20" GNUM_FORMAT_g "\n", x0);
printf (" y0 = %.20" GNUM_FORMAT_g "\n", y0);
#endif
if (update_data (x0, y0, data))
......@@ -223,8 +223,8 @@ goal_seek_newton (GoalSeekFunction f, GoalSeekFunction df,
stepsize = fabs (x1 - x0) / (fabs (x0) + fabs (x1));
#ifdef DEBUG_GOAL_SEEK
printf (" df0 = %.20g\n", df0);
printf (" ss = %.20g\n", stepsize);
printf (" df0 = %.20" GNUM_FORMAT_g "\n", df0);
printf (" ss = %.20" GNUM_FORMAT_g "\n", stepsize);
#endif
x0 = x1;
......@@ -272,7 +272,7 @@ goal_seek_bisection (GoalSeekFunction f, GoalSeekData *data, void *user_data)
/ (fabs (data->xpos) + fabs (data->xneg));
/* log_2 (10) = 3.3219 < 4. */
for (iterations = 0; iterations < 100 + DBL_DIG * 4; iterations++) {
for (iterations = 0; iterations < 100 + GNUM_DIG * 4; iterations++) {
gnum_float xmid, ymid;
GoalSeekStatus status;
enum { M_SECANT, M_RIDDER, M_NEWTON, M_MIDPOINT } method;
......@@ -376,8 +376,8 @@ goal_seek_bisection (GoalSeekFunction f, GoalSeekData *data, void *user_data)
default: themethod = "?";
}
printf ("xmid = %.20g (%s)\n", xmid, themethod);
printf (" ymid = %.20g\n", ymid);
printf ("xmid = %.20" GNUM_FORMAT_g " (%s)\n", xmid, themethod);
printf (" ymid = %.20" GNUM_FORMAT_g "\n", ymid);
}
#endif
......@@ -389,7 +389,7 @@ goal_seek_bisection (GoalSeekFunction f, GoalSeekData *data, void *user_data)
/ (fabs (data->xpos) + fabs (data->xneg));
#ifdef DEBUG_GOAL_SEEK
printf (" ss = %.20g\n", stepsize);
printf (" ss = %.20" GNUM_FORMAT_g "\n", stepsize);
#endif
if (stepsize < data->precision) {
......@@ -434,8 +434,8 @@ goal_seek_trawl_uniformly (GoalSeekFunction f,
continue;
#ifdef DEBUG_GOAL_SEEK
printf ("x = %.20g\n", x);
printf (" y = %.20g\n", y);
printf ("x = %.20" GNUM_FORMAT_g "\n", x);
printf (" y = %.20" GNUM_FORMAT_g "\n", y);
#endif
if (update_data (x, y, data))
......@@ -475,8 +475,8 @@ goal_seek_trawl_normally (GoalSeekFunction f,
continue;
#ifdef DEBUG_GOAL_SEEK
printf ("x = %.20g\n", x);
printf (" y = %.20g\n", y);
printf ("x = %.20" GNUM_FORMAT_g "\n", x);
printf (" y = %.20" GNUM_FORMAT_g "\n", y);
#endif
if (update_data (x, y, data))
......
......@@ -59,7 +59,7 @@ x_selection_to_cell_region (WorkbookControlGUI *wbcg, const guchar *src, int len
char *message;
message = g_strdup_printf (_("The data on the clipboard does not seem to be valid text.\nThe character '%c' (ASCII decimal %d) was encountered.\nMost likely your locale settings are wrong."),
*c, (int) *c);
*c, (int) ((unsigned char)*c));
g_warning (message);
g_free (message);
......
......@@ -25,6 +25,9 @@
#include <unistd.h>
#include <fcntl.h>
#include <gal/util/e-util.h>
#ifdef HAVE_FLOATINGPOINT_H
#include <floatingpoint.h>
#endif
/* ------------------------------------------------------------------------- */
......@@ -546,3 +549,60 @@ gnumeric_strescape (const char *string)
}
/* ------------------------------------------------------------------------- */
#ifdef NEED_FAKE_MODFL
gnum_float
fake_modfl (gnum_float x, gnum_float *iptr)
{
double di;
gnum_float res;
res = modf (x, &di);
*iptr = di;
return res;
}
#endif
/* ------------------------------------------------------------------------- */
#if defined(WITH_LONG_DOUBLE) && !defined(HAVE_STRTOLD)
gnum_float
strtognum (const char *str, char **end)
{
gnum_float res;
#if defined(HAVE_STRING_TO_DECIMAL) && defined(HAVE_DECIMAL_TO_QUADRUPLE)
decimal_record dr;
enum decimal_string_form form;
decimal_mode dm;
fp_exception_field_type excp;
char *echar;
string_to_decimal ((char **)&str, strlen (str),
0, &dr, &form, &echar);
if (end) *end = (char *)str;
if (form == invalid_form) {
errno = EINVAL;
return 0.0;
}
dm.rd = fp_nearest;
dm.df = floating_form;
dm.ndigits = GNUM_DIG;
decimal_to_quadruple (&res, &dm, &dr, &excp);
#else
static gboolean warned = FALSE;
if (!warned) {
warned = TRUE;
g_warning (_("This version of Gnumeric has been compiled with inadequate precision in strtognum."));
}
res = strtod (str, end);
#endif
return res;
}
#endif
/* ------------------------------------------------------------------------- */
......@@ -83,4 +83,12 @@ void gnumeric_set_le_double (void *p, double d);
char * gnumeric_strescape (const char *string);
#ifdef NEED_FAKE_MODFL
gnum_float fake_modfl (gnum_float x, gnum_float *iptr);
#endif
#if defined(WITH_LONG_DOUBLE) && !defined(HAVE_STRTOLD)
gnum_float strtognum (const char *str, char **end);
#endif
#endif /* GNUMERIC_UTILS_H */
......@@ -860,7 +860,7 @@ compute_value (char const *s, const regmatch_t *mp,
char *exppart = NULL;
if (*str == decimal) {
char *end;
errno = 0; /* strtod sets errno, but does not clear it. */
errno = 0; /* strtognum sets errno, but does not clear it. */
if (seconds < 0) {
gnum_float fraction;
......@@ -871,14 +871,14 @@ compute_value (char const *s, const regmatch_t *mp,
*end = 0;
}
fraction = strtod (str, &end);
fraction = strtognum (str, &end);
if (is_neg)
number -= fraction;
else
number += fraction;
is_number = TRUE;
} else
seconds += strtod (str, &end);
seconds += strtognum (str, &end);
}
if (exppart) {
char *end;
......@@ -1094,16 +1094,16 @@ format_match_simple (char const *text)
/* Is it a double? */
{
char *end;
double d;
gnum_float d;
errno = 0; /* strtod sets errno, but does not clear it. */
d = strtod (text, &end);
if (text != end && errno != ERANGE && d == (gnum_float)d) {
errno = 0; /* strtognum sets errno, but does not clear it. */
d = strtognum (text, &end);
if (text != end && errno != ERANGE) {
/* Allow and ignore spaces at the end. */
while (*end == ' ')
end++;
if (*end == '\0')
return value_new_float ((gnum_float)d);
return value_new_float (d);
}
}
......
#ifndef GNUMERIC_NUMBERS_H
#define GNUMERIC_NUMBERS_H
typedef double gnum_float;
typedef int gnum_int;
#ifdef WITH_LONG_DOUBLE
typedef long double gnum_float;
#ifdef HAVE_STRTOLD
#define strtognum strtold
#else
/* Defined in gutils.h */
#endif
#ifdef HAVE_MODFL
#define modfgnum modfl
#else
#define NEED_FAKE_MODFL
#define modfgnum fake_modfl
#endif
#define GNUM_FORMAT_e "Le"
#define GNUM_FORMAT_E "LE"
#define GNUM_FORMAT_f "Lf"
#define GNUM_FORMAT_g "Lg"
#define GNUM_DIG LDBL_DIG
#else /* !WITH_LONG_DOUBLE */
typedef double gnum_float;
#define strtognum strtod
#define modfgnum modf
#define GNUM_FORMAT_e "e"
#define GNUM_FORMAT_E "E"
#define GNUM_FORMAT_f "f"
#define GNUM_FORMAT_g "g"
#define GNUM_DIG DBL_DIG
#endif
#endif /* GNUMERIC_NUMBERS_H */
......@@ -278,7 +278,7 @@ gnumeric_char_start_expr_p (char const * c)
* just checks for C-syntax numbers.
*/
errno = 0;
(void) strtod (c, &end);
(void) strtognum (c, &end);
if (errno || *end != 0 || end == c)
return (c0 == '+') ? c + 1 : c;
/* Otherwise, it's a number. */
......
......@@ -808,14 +808,14 @@ yylex (void)
if (c == state->decimal_point || tolower (c) == 'e') {
/* This is float */
char *end;
double d;
gnum_float d;
errno = 0;
d = strtod (start, &end);
d = strtognum (start, &end);
if (start == end) {
g_warning ("%s is not a double, but was expected to be one", start);
} else if (errno != ERANGE) {
v = value_new_float ((gnum_float)d);
v = value_new_float (d);
state->expr_text = end;
} else if (tolower (c) != 'e') {
gnumeric_parse_error (
......@@ -853,12 +853,12 @@ yylex (void)
v = value_new_int (l);
state->expr_text = end;
} else if (l == LONG_MIN || l == LONG_MAX) {
double d;
gnum_float d;
errno = 0;
d = strtod (start, &end);
d = strtognum (start, &end);
if (errno != ERANGE) {
v = value_new_float ((gnum_float)d);
v = value_new_float (d);
state->expr_text = end;
} else {
gnumeric_parse_error (
......
......@@ -32,17 +32,17 @@
g_free (var); \
} while (0)
#define PRINT_MATRIX(var,dim1,dim2) \
do { \
int _i, _j, _d1, _d2; \
_d1 = (dim1); \
_d2 = (dim2); \
for (_i = 0; _i < _d1; _i++) \
{ \
for (_j = 0; _j < _d2; _j++) \
fprintf (stderr, "%20.10f", var[_i][_j]); \
fprintf (stderr, "\n"); \
} \
#define PRINT_MATRIX(var,dim1,dim2) \
do { \
int _i, _j, _d1, _d2; \
_d1 = (dim1); \
_d2 = (dim2); \
for (_i = 0; _i < _d1; _i++) \
{ \
for (_j = 0; _j < _d2; _j++) \
fprintf (stderr, "%20.10" GNUM_FORMAT_f, var[_i][_j]); \
fprintf (stderr, "\n"); \
} \
} while (0)
/* ------------------------------------------------------------------------- */
......@@ -242,7 +242,10 @@ general_linear_regression (gnum_float **xss, int xdim,
/* FIXME: we ought to have a devsq variant that does not
recompute the mean. */
err = range_devsq (ys, n, &ss_total);
if (xss[0])
err = range_sumsq (ys, n, &ss_total);
else
err = range_devsq (ys, n, &ss_total);
g_assert (err == 0);
extra_stat->xbar = g_new (gnum_float, n);
......
......@@ -43,7 +43,7 @@ value_dump (Value const *value)
break;
case VALUE_FLOAT:
printf ("Float: %f\n", value->v_float.val);
printf ("Float: %" GNUM_FORMAT_f "\n", value->v_float.val);
break;
case VALUE_ARRAY: {
......
......@@ -284,12 +284,12 @@ value_new_from_string (ValueType t, char const *str, StyleFormat *sf)
case VALUE_FLOAT: {
char *end;
double d;
gnum_float d;
errno = 0;
d = strtod (str, &end);
d = strtognum (str, &end);
if (str != end && *end == '\0' && errno != ERANGE)
res = value_new_float ((gnum_float)d);
res = value_new_float (d);
break;
}
......@@ -525,7 +525,7 @@ value_get_as_string (Value const *v)
return g_strdup_printf ("%d", v->v_int.val);
case VALUE_FLOAT:
return g_strdup_printf ("%.*g", DBL_DIG, v->v_float.val);
return g_strdup_printf ("%.*" GNUM_FORMAT_g, GNUM_DIG, v->v_float.val);
case VALUE_ARRAY: {
char const row_sep = format_get_arg_sep ();
......@@ -548,7 +548,7 @@ value_get_as_string (Value const *v)
g_string_sprintfa (str, "\"%s\"",
val->v_str.val->str);
else
g_string_sprintfa (str, "%g",
g_string_sprintfa (str, "%" GNUM_FORMAT_g,
value_get_as_float (val));
}
if (y < v->v_array.y-1)
......
......@@ -705,7 +705,7 @@ cb_change_zoom (GtkWidget *caller, char *new_zoom, WorkbookControlGUI *wbcg)
if (sheet == NULL || wbcg->updating_ui)
return TRUE;
errno = 0; /* strtod sets errno, but does not clear it. */
errno = 0; /* strtol sets errno, but does not clear it. */
factor = strtol (new_zoom, &end, 10);
if (new_zoom != end && errno != ERANGE && factor == (gnum_float)factor)
/* The GSList of sheet passed to cmd_zoom will be freed by cmd_zoom,
......