]> git.lyx.org Git - lyx.git/commitdiff
Fix LaTeX length export of big numbers (bug 9416)
authorGeorg Baum <baum@lyx.org>
Thu, 14 May 2015 10:10:42 +0000 (12:10 +0200)
committerGeorg Baum <baum@lyx.org>
Thu, 14 May 2015 10:14:47 +0000 (12:14 +0200)
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.

src/Length.cpp
src/support/lstrings.cpp
src/support/lstrings.h
src/support/tests/check_lstrings.cpp
src/support/tests/regfiles/lstrings

index 2463be8f66c889d37810e907fddbc37d67b5f842..89061e104b2470ef85741c125bc6bf8d52f95500 100644 (file)
@@ -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();
index ea1ba59984a62ba7e92910d94530a930e3baf0ef..f7e8b5aa3cedbfa1b7f7fcf48c3dc5afe8455b91 100644 (file)
 
 #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)
 {
index 0d21e954a4308600bce39a3e81dc469256fc32c9..395e18e04d3f633e867a740cfa132faf2c42233c 100644 (file)
@@ -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);
 
index 3509e45e897bc4660330c0c2ce6bd4268f65d4bd..b759f6a2e7584c23ba37f4f4996fe66d24083336 100644 (file)
@@ -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();
 }
index cc2481b5046e904c4a3445d59a222fe565d399fd..20363cd0c870649c762d46bfd8ee294907a82d6e 100644 (file)
@@ -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