commit 59e4d16ab9611732dbc208f23d3de4b9da321dce
Author: Georg Baum <[email protected]>
Date: Thu May 14 12:10:42 2015 +0200
Fix LaTeX length export of big numbers (bug 9416)
LaTeX lengths must not use scientific notation, since the + sign has a
different meaning (glue lengths). This is the export part of bug 9416, the
GUI
part is still not fixed.
diff --git a/src/Length.cpp b/src/Length.cpp
index 2463be8..89061e1 100644
--- a/src/Length.cpp
+++ b/src/Length.cpp
@@ -22,6 +22,7 @@
#include "frontends/FontMetrics.h"
#include "support/docstream.h"
+#include "support/lstrings.h"
#include <sstream>
#include <iomanip>
@@ -81,29 +82,31 @@ docstring const Length::asDocstring() const
string const Length::asLatexString() const
{
ostringstream os;
+ // Do not allow scientific notation (e.g. 1.2e+03), since this is not
valid
+ // LaTeX (bug 9416)
switch (unit_) {
case PTW:
- os << val_ / 100.0 << "\\textwidth";
+ os << support::formatFPNumber(val_ / 100.0) << "\\textwidth";
break;
case PCW:
- os << val_ / 100.0 << "\\columnwidth";
+ os << support::formatFPNumber(val_ / 100.0) << "\\columnwidth";
break;
case PPW:
- os << val_ / 100.0 << "\\paperwidth";
+ os << support::formatFPNumber(val_ / 100.0) << "\\paperwidth";
break;
case PLW:
- os << val_ / 100.0 << "\\linewidth";
+ os << support::formatFPNumber(val_ / 100.0) << "\\linewidth";
break;
case PTH:
- os << val_ / 100.0 << "\\textheight";
+ os << support::formatFPNumber(val_ / 100.0) << "\\textheight";
break;
case PPH:
- os << val_ / 100.0 << "\\paperheight";
+ os << support::formatFPNumber(val_ / 100.0) << "\\paperheight";
break;
case UNIT_NONE:
break;
default:
- os << val_ << unit_name[unit_];
+ os << support::formatFPNumber(val_) << unit_name[unit_];
break;
}
return os.str();
diff --git a/src/support/lstrings.cpp b/src/support/lstrings.cpp
index ea1ba59..f7e8b5a 100644
--- a/src/support/lstrings.cpp
+++ b/src/support/lstrings.cpp
@@ -22,9 +22,12 @@
#include <QString>
+#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
+#include <iomanip>
+#include <sstream>
#include <typeinfo>
using namespace std;
@@ -1385,6 +1388,25 @@ int findToken(char const * const str[], string const &
search_token)
}
+std::string formatFPNumber(double x)
+{
+ // Need manual tweaking, QString::number(x, 'f', 16) does not work
either
+ ostringstream os;
+ os << std::fixed;
+ // Prevent outputs of 23.4200000000000017 but output small numbers
+ // with at least 6 significant digits.
+ double const logarithm = log10(x);
+ os << std::setprecision(max(6 - static_cast<int>(round(logarithm)), 0))
<< x;
+ string result = os.str();
+ if (result.find('.') != string::npos) {
+ result = rtrim(result, "0");
+ if (result[result.length()-1] == '.')
+ result = rtrim(result, ".");
+ }
+ return result;
+}
+
+
template<>
docstring bformat(docstring const & fmt, int arg1)
{
diff --git a/src/support/lstrings.h b/src/support/lstrings.h
index 0d21e95..395e18e 100644
--- a/src/support/lstrings.h
+++ b/src/support/lstrings.h
@@ -302,6 +302,15 @@ docstring const getStringFromVector(std::vector<docstring>
const & vec,
/// found, else -1. The last item in \p str must be "".
int findToken(char const * const str[], std::string const & search_token);
+
+/// Format a floating point number with at least 6 siginificant digits, but
+/// without scientific notation.
+/// Scientific notation would be invalid in some contexts, such as lengths for
+/// LaTeX. Simply using std::ostream with std::fixed would produce results
+/// like "1000000.000000", and precision control would not be that easy either.
+std::string formatFPNumber(double);
+
+
template <class Arg1>
docstring bformat(docstring const & fmt, Arg1);
diff --git a/src/support/tests/check_lstrings.cpp
b/src/support/tests/check_lstrings.cpp
index 3509e45..b759f6a 100644
--- a/src/support/tests/check_lstrings.cpp
+++ b/src/support/tests/check_lstrings.cpp
@@ -25,8 +25,59 @@ void test_uppercase()
cout << uppercase('a') << endl;
}
+void test_formatFPNumber()
+{
+ cout << formatFPNumber(0) << endl;
+ cout << formatFPNumber(1) << endl;
+ cout << formatFPNumber(23.42) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-20) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-19) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-18) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-17) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-16) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-15) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-14) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-13) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-12) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-11) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-10) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-9) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-8) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-7) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-6) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-5) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-4) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-3) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-2) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e-1) << endl;
+ cout << formatFPNumber(1.3754937356458394574047) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e1) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e2) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e3) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e4) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e5) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e6) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e7) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e8) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e9) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e10) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e11) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e12) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e13) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e14) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e15) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e16) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e17) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e18) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e19) << endl;
+ cout << formatFPNumber(1.3754937356458394574047e20) << endl;
+ cout << formatFPNumber(1e-42) << endl;
+ cout << formatFPNumber(1e42) << endl;
+}
+
int main()
{
test_lowercase();
test_uppercase();
+ test_formatFPNumber();
}
diff --git a/src/support/tests/regfiles/lstrings
b/src/support/tests/regfiles/lstrings
index cc2481b..20363cd 100644
--- a/src/support/tests/regfiles/lstrings
+++ b/src/support/tests/regfiles/lstrings
@@ -5,3 +5,49 @@ alle
A
ALLE
A
+0
+1
+23.42
+0.00000000000000000001375494
+0.0000000000000000001375494
+0.000000000000000001375494
+0.00000000000000001375494
+0.0000000000000001375494
+0.000000000000001375494
+0.00000000000001375494
+0.0000000000001375494
+0.000000000001375494
+0.00000000001375494
+0.0000000001375494
+0.000000001375494
+0.00000001375494
+0.0000001375494
+0.000001375494
+0.00001375494
+0.0001375494
+0.001375494
+0.01375494
+0.1375494
+1.375494
+13.75494
+137.5494
+1375.494
+13754.94
+137549.4
+1375494
+13754937
+137549374
+1375493736
+13754937356
+137549373565
+1375493735646
+13754937356458
+137549373564584
+1375493735645840
+13754937356458394
+137549373564583952
+1375493735645839360
+13754937356458393600
+137549373564583952384
+0.000000000000000000000000000000000000000001
+1000000000000000044885712678075916785549312