[goffice] dtoa: implement some approximation of shortest-string versions.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] dtoa: implement some approximation of shortest-string versions.
- Date: Wed, 23 Apr 2014 01:01:17 +0000 (UTC)
commit 02df4e11989d375bd3f16b50337b97292bd38b1c
Author: Morten Welinder <terra gnome org>
Date: Tue Apr 22 21:00:39 2014 -0400
dtoa: implement some approximation of shortest-string versions.
ChangeLog | 3 ++
goffice/math/go-dtoa.c | 53 ++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 52 insertions(+), 4 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 1e24497..c10d1e5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2014-04-22 Morten Welinder <terra gnome org>
+ * goffice/math/go-dtoa.c (go_dtoa): Mostly implement the
+ shortest-version flag.
+
* goffice/graph/gog-object-xml.c (gog_object_write_property_sax):
Properly handle float/double properties.
diff --git a/goffice/math/go-dtoa.c b/goffice/math/go-dtoa.c
index 72db547..e2e42a7 100644
--- a/goffice/math/go-dtoa.c
+++ b/goffice/math/go-dtoa.c
@@ -452,6 +452,26 @@ parse_fmt (const char *fmt, va_list args, gboolean *is_long,
*d = va_arg (args, double);
}
+static long double
+strto (const char *str, gboolean is_long, gboolean is_ascii)
+{
+ if (is_long) {
+#ifdef GOFFICE_WITH_LONG_DOUBLE
+ /*
+ * FIXME: ignore ascii flag for now. Given the limited
+ * and checked usage of this function this should still
+ * be safe, if suboptimal.
+ */
+ return go_strtold (str, NULL);
+#else
+ return go_nan;
+#endif
+ } else {
+ return is_ascii
+ ? g_ascii_strtod (str, NULL)
+ : go_strtod (str, NULL);
+ }
+}
void
@@ -462,18 +482,43 @@ go_dtoa (GString *dst, const char *fmt, ...)
long double d;
gboolean is_long;
gboolean debug = FALSE;
+ size_t oldlen;
va_start (args, fmt);
parse_fmt (fmt, args, &is_long, &w, &p, &fl, &t, &d);
va_end (args);
- /*
- * FLAG_SHORTEST isn't fully implemented yet. For now we just
- * ensure a roundtrip.
- */
if (fl & FLAG_SHORTEST) p = is_long ? 20 : 17;
+ oldlen = (fl & FLAG_TRUNCATE) ? 0 : dst->len;
if (debug) g_printerr ("%Lg [%s] t=%c p=%d\n", d, fmt, t, p);
fmt_fp (dst, d, w, p, fl, t);
if (debug) g_printerr (" --> %s\n", dst->str);
+
+ if (fl & FLAG_SHORTEST) {
+ const char *dec = (fl & FLAG_ASCII)
+ ? "."
+ : go_locale_get_decimal()->str;
+ const char *dot = strstr (dst->str + oldlen, dec);
+ if (dot) {
+ /*
+ * This is crude. We have a dot, so try to render
+ * the same number with less precision and check
+ * that the result round-trips.
+ */
+ GString *alt = g_string_new (NULL);
+ long double dalt;
+
+ fmt_fp (alt, d, w, p - 1, fl, t);
+
+ dalt = strto (alt->str, is_long, (fl & FLAG_ASCII));
+
+ if (dalt == d) {
+ g_string_truncate (dst, oldlen);
+ go_string_append_gstring (dst, alt);
+ if (debug) g_printerr (" --> %s\n", dst->str);
+ }
+ g_string_free (alt, TRUE);
+ }
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]