[goffice] GOFormat: minor speed improvement.
- From: Morten Welinder <mortenw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] GOFormat: minor speed improvement.
- Date: Wed, 9 Apr 2014 15:11:00 +0000 (UTC)
commit 55427945f5e0b82606924cc049f9892bdd59d7fd
Author: Morten Welinder <terra gnome org>
Date: Wed Apr 9 11:10:13 2014 -0400
GOFormat: minor speed improvement.
ChangeLog | 3 +
goffice/utils/go-format.c | 113 ++++++++++++++++++++++++++++++++++++++------
2 files changed, 100 insertions(+), 16 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2e5025b..3f3cff1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2014-04-09 Morten Welinder <terra gnome org>
+ * goffice/utils/go-format.c (go_render_general): Drop a decimal by
+ double-rounding the decimal string unless the string ends in '5'.
+
* goffice/math/go-dtoa.c (go_dtoa): Improve long-double handling.
2014-04-07 Morten Welinder <terra gnome org>
diff --git a/goffice/utils/go-format.c b/goffice/utils/go-format.c
index 9ac3a68..2b3ac71 100644
--- a/goffice/utils/go-format.c
+++ b/goffice/utils/go-format.c
@@ -52,6 +52,8 @@
#include <errno.h>
#include <stdlib.h>
+#undef DEBUG_GENERAL
+
/**
* GOFormatFamily:
* @GO_FORMAT_UNKNOWN: unknown ,should not occur.
@@ -491,6 +493,14 @@ typedef struct {
#define UTF8_FULLWIDTH_MINUS "\357\274\215"
#define UTF8_FULLWIDTH_PLUS "\357\274\213"
+/* Number of digits required for roundtrip of DOUBLE. */
+#ifdef DEFINE_COMMON
+static int go_format_roundtrip_digits;
+#ifdef GOFFICE_WITH_LONG_DOUBLE
+static int go_format_roundtrip_digitsl;
+#endif
+#endif
+
gboolean
go_format_allow_ee_markup (void)
{
@@ -4756,7 +4766,7 @@ go_format_measure_pango (G_GNUC_UNUSED const GString *str,
int w;
pango_layout_get_size (layout, &w, NULL);
#ifdef DEBUG_GENERAL
- g_print ("[%s] --> %d\n", str->str, w);
+ g_printerr ("[%s] --> %d\n", str->str, w);
#endif
return w;
}
@@ -4810,6 +4820,46 @@ drop_zeroes (GString *str, int *prec)
g_string_truncate (str, dot - str->str);
}
}
+
+static gboolean
+cheap_drop_decimal (GString *str, size_t pos)
+{
+ char l = str->str[pos];
+ int carry;
+
+ if (!g_ascii_isdigit (l) || l == '5')
+ return FALSE;
+
+ g_string_erase (str, pos, 1);
+ pos--;
+
+ carry = (l > '5');
+ if (!carry && !g_ascii_isdigit (str->str[pos])) {
+ const char *dot = g_utf8_prev_char (str->str + pos + 1);
+ g_string_erase (str, dot - str->str, str->str + pos + 1 - dot);
+#ifdef DEBUG_GENERAL
+ g_printerr ("Removing decimal cheaply\n");
+#endif
+ }
+
+ while (carry) {
+ l = str->str[pos];
+ if (!g_ascii_isdigit (l))
+ return FALSE;
+
+ if (l < '9') {
+ str->str[pos] = l + 1;
+ carry = 0;
+ } else
+ str->str[pos] = '0';
+ pos--;
+ }
+
+#ifdef DEBUG_GENERAL
+ g_printerr ("Cheaply dropped decimal\n");
+#endif
+ return TRUE;
+}
#endif
static int
@@ -4870,7 +4920,8 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
guint shape_flags)
{
DOUBLE aval;
- int prec, safety, digs, digs_as_int, maxdigits = PREFIX(DIG);
+ int prec, safety, digs, digs_as_int;
+ int maxdigits = SUFFIX(go_format_roundtrip_digits) - 1;
size_t epos;
gboolean rounds_to_0;
int sign_width;
@@ -4901,7 +4952,7 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
}
#ifdef DEBUG_GENERAL
- g_print ("Rendering %" FORMAT_G " to width %d (<=%d digits)\n",
+ g_printerr ("Rendering %" FORMAT_G " to width %d (<=%d digits)\n",
val, col_width, maxdigits);
#endif
if (val == 0)
@@ -4919,15 +4970,18 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
if (digs_as_int * min_digit_width > col_width) {
#ifdef DEBUG_GENERAL
- g_print ("No room for whole part.\n");
+ g_printerr ("No room for whole part.\n");
#endif
goto e_notation;
} else if (digs_as_int * metrics->max_digit_width + safety <
col_width - (val > 0 ? 0 : sign_width)) {
#ifdef DEBUG_GENERAL
- g_print ("Room for whole part.\n");
+ g_printerr ("Room for whole part.\n");
#endif
if (val == SUFFIX(floor) (val) || digs_as_int == maxdigits) {
+#ifdef DEBUG_GENERAL
+ g_printerr ("Integer or room for nothing else.\n");
+#endif
go_dtoa (str, "=^.0" FORMAT_f, val);
HANDLE_NUMERAL_SHAPE;
HANDLE_SIGN (0);
@@ -4937,7 +4991,7 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
} else {
int w;
#ifdef DEBUG_GENERAL
- g_print ("Maybe room for whole part.\n");
+ g_printerr ("Maybe room for whole part.\n");
#endif
go_dtoa (str, "=^.0" FORMAT_f, val);
@@ -4948,14 +5002,21 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
if (w > col_width)
goto e_notation;
- if (val == SUFFIX(floor) (val) || digs_as_int == maxdigits)
+ if (val == SUFFIX(floor) (val) || digs_as_int == maxdigits) {
+#ifdef DEBUG_GENERAL
+ g_printerr ("Integer or room for nothing else.\n");
+#endif
return;
+ }
}
/* Number of digits in [aval]. */
digs = (aval >= 10 ? 1 + SUFFIX(ilog10) (aval) : 1);
prec = maxdigits - digs;
+#ifdef DEBUG_GENERAL
+ g_printerr ("Starting with with %d decimals\n", prec);
+#endif
go_dtoa (str, "=^.*" FORMAT_f, prec, val);
if (check_val) {
/*
@@ -4974,22 +5035,35 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
while (prec > 0) {
int w;
+#ifdef DEBUG_GENERAL
+ g_printerr ("Trying with %d decimals\n", prec);
+#endif
SETUP_LAYOUT;
w = measure (str, layout);
- if (w <= col_width)
+ if (w <= col_width) {
+#ifdef DEBUG_GENERAL
+ g_printerr ("Success\n");
+#endif
return;
+ }
prec--;
- go_dtoa (str, "=^.*" FORMAT_f, prec, val);
- drop_zeroes (str, &prec);
- HANDLE_NUMERAL_SHAPE;
- HANDLE_SIGN (0);
+ if (num_shape > 1 || !cheap_drop_decimal (str, str->len - 1)) {
+ go_dtoa (str, "=^.*" FORMAT_f, prec, val);
+ drop_zeroes (str, &prec);
+ HANDLE_NUMERAL_SHAPE;
+ HANDLE_SIGN (0);
+ } else
+ drop_zeroes (str, &prec);
}
SETUP_LAYOUT;
return;
e_notation:
+#ifdef DEBUG_GENERAL
+ g_printerr ("Trying E-notation\n");
+#endif
rounds_to_0 = (aval < 0.5);
prec = (col_width -
(val >= 0 ? 0 : sign_width) -
@@ -4998,9 +5072,9 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
if (prec <= 0) {
#ifdef DEBUG_GENERAL
if (prec == 0)
- g_print ("Maybe room for E notation with no decimals.\n");
+ g_printerr ("Maybe room for E notation with no decimals.\n");
else
- g_print ("No room for E notation.\n");
+ g_printerr ("No room for E notation.\n");
#endif
/* Certainly too narrow for precision. */
if (prec == 0 || !rounds_to_0) {
@@ -5068,7 +5142,7 @@ SUFFIX(go_render_general) (PangoLayout *layout, GString *str,
zero:
#ifdef DEBUG_GENERAL
- g_print ("Zero.\n");
+ g_printerr ("Zero.\n");
#endif
g_string_assign (str, "0");
SETUP_LAYOUT;
@@ -5287,6 +5361,14 @@ SUFFIX(go_format_value) (GOFormat const *fmt, DOUBLE val)
void
_go_number_format_init (void)
{
+ double l10 = log10 (FLT_RADIX);
+ go_format_roundtrip_digits =
+ (int)ceil (DBL_MANT_DIG * l10) + (l10 != (int)l10);
+#ifdef GOFFICE_WITH_LONG_DOUBLE
+ go_format_roundtrip_digitsl =
+ (int)ceil (LDBL_MANT_DIG * l10) + (l10 != (int)l10);
+#endif
+
style_format_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) go_format_unref);
}
@@ -8967,7 +9049,6 @@ go_format_output_conditional_to_odf (GsfXMLOut *xout, gboolean with_extension,
g_free (partname);
g_string_free (condition, TRUE);
}
- /* Do we need to add a catch-all General? */
gsf_xml_out_end_element (xout); /* </number:text-style> or </number:number-style> */
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]