[goffice] Math: various.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Math: various.
- Date: Thu, 17 Feb 2022 22:45:40 +0000 (UTC)
commit c92dd350e4e35f9c09fdc0686ff91a92aab44088
Author: Morten Welinder <terra gnome org>
Date: Thu Feb 17 17:44:21 2022 -0500
Math: various.
* Introspection fixes.
* Fix fallback code for !HAVE_NEXTAFTER
* Avoid reserved word "exp" as parameter name.
* Avoid a few cases of potentially returning -0.0
NEWS | 2 +
goffice/math/go-math.c | 115 +++++++++++++++++++++++++++++++++----------------
goffice/math/go-math.h | 5 ++-
3 files changed, 84 insertions(+), 38 deletions(-)
---
diff --git a/NEWS b/NEWS
index 23fe50ac..0ca1e883 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ goffice 0.10.52:
Morten:
* Improve GOComboBox css styling.
* Reimplement GOActionComboStack using GtkComboBox.
+ * Introspection fixes.
+ * Fix go_{add,sub}_epsilon{,l} confusion in fallback code for win32.
--------------------------------------------------------------------------
goffice 0.10.51:
diff --git a/goffice/math/go-math.c b/goffice/math/go-math.c
index 51b0b216..b50961f4 100644
--- a/goffice/math/go-math.c
+++ b/goffice/math/go-math.c
@@ -193,10 +193,12 @@ _go_math_init (void)
return;
}
-/*
- * In preparation for truncation, make the value a tiny bit larger (seen
- * absolutely). This makes ROUND (etc.) behave a little closer to what
- * people want, even if it is a bit bogus.
+/**
+ * go_add_epsilon:
+ * @x: a number
+ *
+ * Returns the next-smaller representable value, except that zero and
+ * infinites are returned unchanged.
*/
double
go_add_epsilon (double x)
@@ -206,15 +208,23 @@ go_add_epsilon (double x)
#else
if (!go_finite (x) || x == 0)
return x;
+ else if (x < 0)
+ return 0 - go_sub_epsilon(-x);
else {
- int exp;
- double mant = frexp (fabs (x), &exp);
- double absres = ldexp (mant + DBL_EPSILON, exp);
- return (x < 0) ? -absres : absres;
+ int e;
+ double mant = frexp (fabs (x), &e);
+ return ldexp (mant + DBL_EPSILON, e);
}
#endif
}
+/**
+ * go_sub_epsilon:
+ * @x: a number
+ *
+ * Returns the next-smaller representable value, except that zero and
+ * infinites are returned unchanged.
+ */
double
go_sub_epsilon (double x)
{
@@ -223,11 +233,12 @@ go_sub_epsilon (double x)
#else
if (!go_finite (x) || x == 0)
return x;
+ else if (x < 0)
+ return 0 - go_add_epsilon(-x);
else {
- int exp;
- double mant = frexp (fabs (x), &exp);
- double absres = ldexp (mant - DBL_EPSILON, exp);
- return (x < 0) ? -absres : absres;
+ int e;
+ double mant = frexp (fabs (x), &e);
+ return ldexp (mant - DBL_EPSILON, e);
}
#endif
}
@@ -413,8 +424,9 @@ strtod_helper (const char *s)
/*
* go_strtod: A sane strtod.
* @s: string to convert
- * @end: optional pointer to end of string.
+ * @end: (out): optional pointer to end of string.
*
+ * Returns: the numeric value of the given string.
* Like strtod, but without hex notation and MS extensions.
* Unlike strtod, there is no need to reset errno before calling this.
*/
@@ -634,11 +646,31 @@ go_powl (long double x, long double y)
return powl (x, y);
}
+long double
+go_log10l (long double x)
+{
+ long double l = log10l (x);
+ int il;
+
+ // Quick rejection of stuff we cannot improve. 10^28 is too big
+ // for long double to be exact.
+ if (!(x == floorl (x)) || x < 1 || x > 1e27L)
+ return l;
+
+ il = (int)(l + 0.5);
+ if (x != go_pow10l (il))
+ return l;
+
+ return il;
+}
+
+
/*
* go_strtold: A sane strtold.
* @s: string to convert
- * @end: optional pointer to end of string.
+ * @end: (out): optional pointer to end of string.
*
+ * Returns: the numeric value of the given string.
* Like strtold, but without hex notation and MS extensions.
* Unlike strtold, there is no need to reset errno before calling this.
*/
@@ -712,10 +744,12 @@ go_ascii_strtold (const char *s, char **end)
return res;
}
-/*
- * In preparation for truncation, make the value a tiny bit larger (seen
- * absolutely). This makes ROUND (etc.) behave a little closer to what
- * people want, even if it is a bit bogus.
+/**
+ * go_add_epsilonl:
+ * @x: a number
+ *
+ * Returns the next-larger representable value, except that zero and
+ * infinites are returned unchanged.
*/
long double
go_add_epsilonl (long double x)
@@ -725,15 +759,23 @@ go_add_epsilonl (long double x)
#else
if (!go_finitel (x) || x == 0)
return x;
+ else if (x < 0)
+ return 0 - go_sub_epsilonl(-x);
else {
- int exp;
- long double mant = frexpl (fabsl (x), &exp);
- long double absres = ldexpl (mant + LDBL_EPSILON, exp);
- return (x < 0) ? -absres : absres;
+ int e;
+ long double mant = frexpl (fabsl (x), &e);
+ return ldexpl (mant + LDBL_EPSILON, e);
}
#endif
}
+/**
+ * go_sub_epsilonl:
+ * @x: a number
+ *
+ * Returns the next-smaller representable value, except that zero and
+ * infinites are returned unchanged.
+ */
long double
go_sub_epsilonl (long double x)
{
@@ -742,11 +784,12 @@ go_sub_epsilonl (long double x)
#else
if (!go_finitel (x) || x == 0)
return x;
+ else if (x < 0)
+ return 0 - go_add_epsilonl(-x);
else {
- int exp;
- long double mant = frexpl (fabsl (x), &exp);
- long double absres = ldexpl (mant - LDBL_EPSILON, exp);
- return (x < 0) ? -absres : absres;
+ int e;
+ long double mant = frexpl (fabsl (x), &e);
+ return ldexpl (mant - LDBL_EPSILON, e);
}
#endif
}
@@ -786,7 +829,7 @@ go_fake_roundl (long double x)
* case is nextafter(0.5,-1) for which we want to produce 1 here.
*/
y = go_fake_floorl (fabsl (x) + 0.5L);
- return (x < 0) ? -y : y;
+ return (x < 0) ? 0 - y : y;
}
long double
@@ -797,17 +840,17 @@ go_fake_truncl (long double x)
return (x >= 0)
? floorl (go_add_epsilonl (x))
- : -floorl (go_add_epsilonl (-x));
+ : 0 - floorl (go_add_epsilonl (-x));
}
#ifdef GOFFICE_SUPPLIED_LDEXPL
long double
-ldexpl (long double x, int exp)
+ldexpl (long double x, int e)
{
if (!go_finitel (x) || x == 0)
return x;
else {
- long double res = x * go_pow2l (exp);
+ long double res = x * go_pow2l (e);
if (go_finitel (res))
return res;
else {
@@ -820,27 +863,27 @@ ldexpl (long double x, int exp)
#ifdef GOFFICE_SUPPLIED_FREXPL
long double
-frexpl (long double x, int *exp)
+frexpl (long double x, int *e)
{
long double l2x;
if (!go_finitel (x) || x == 0) {
- *exp = 0;
+ *e = 0;
return x;
}
l2x = logl (fabsl (x)) / logl (2);
- *exp = (int)floorl (l2x);
+ *e = (int)floorl (l2x);
/*
* Now correct the result and adjust things that might have gotten
* off-by-one due to rounding.
*/
- x /= go_pow2l (*exp);
+ x /= go_pow2l (*e);
if (fabsl (x) >= 1.0)
- x /= 2, (*exp)++;
+ x /= 2, (*e)++;
else if (fabsl (x) < 0.5)
- x *= 2, (*exp)--;
+ x *= 2, (*e)--;
return x;
}
diff --git a/goffice/math/go-math.h b/goffice/math/go-math.h
index ee1c25d2..92158e95 100644
--- a/goffice/math/go-math.h
+++ b/goffice/math/go-math.h
@@ -85,6 +85,7 @@ int go_finitel (long double x);
long double go_pow2l (int n);
long double go_pow10l (int n);
long double go_powl (long double x, long double y);
+long double go_log10l (long double x);
long double go_strtold (const char *s, char **end);
long double go_ascii_strtold (const char *s, char **end);
@@ -100,10 +101,10 @@ long double go_atanpil (long double x);
* We provide working versions of these functions for long doubles.
*/
#ifdef GOFFICE_SUPPLIED_LDEXPL
-long double ldexpl (long double x, int exp);
+long double ldexpl (long double x, int e);
#endif
#ifdef GOFFICE_SUPPLIED_FREXPL
-long double frexpl (long double x, int *exp);
+long double frexpl (long double x, int *e);
#endif
#ifdef GOFFICE_SUPPLIED_STRTOLD
long double strtold (const char *, char **);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]