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

Reply via email to