mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-22 10:00:33 +00:00
Introduce proper integer rounding function
This fixes a failing unit test with 32bit gcc 4.9.3 and -O2 optimization: It computed 9953 instead of 9954 for Length::inPixels() of value 2342. The reason for this is probably different rounding behaviour caused by storing the unrounded value in a processor register (uses 80bit accuracy) vs. writing it back to memory (uses 64bit accuracy). The unrounded value is very close to 9953.5 (which is not representable as an exact IEEE floating point value). Apart from that, having a proper function for rounding makes the code more readable, and has the nice side effect to make Length::inPB() work for negative lengths as well.
This commit is contained in:
parent
fc459bd977
commit
c0ce79452f
@ -23,6 +23,7 @@
|
||||
|
||||
#include "support/docstream.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/lyxlib.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
@ -215,7 +216,7 @@ int Length::inPixels(int text_width, int em_width_base) const
|
||||
|
||||
double const text_width_in = text_width / (zoom * dpi);
|
||||
double const result = zoom * dpi * inInch(text_width_in, em_width_in);
|
||||
return static_cast<int>(result + ((result >= 0) ? 0.5 : -0.5));
|
||||
return support::iround(result);
|
||||
}
|
||||
|
||||
|
||||
@ -311,7 +312,7 @@ int Length::inBP() const
|
||||
double const text_width_in = 210.0 / 2.54; // assume A4
|
||||
double const em_width_in = 10.0 / 72.27;
|
||||
double result = 72.0 * inInch(text_width_in, em_width_in);
|
||||
return static_cast<int>(result + 0.5);
|
||||
return support::iround(result);
|
||||
}
|
||||
|
||||
|
||||
|
@ -438,7 +438,7 @@ docstring InsetGraphics::createDocBookAttributes() const
|
||||
if (!params().scale.empty() && !float_equal(scl, 0.0, 0.05)) {
|
||||
if (!float_equal(scl, 100.0, 0.05))
|
||||
options << " scale=\""
|
||||
<< static_cast<int>( (scl) + 0.5 )
|
||||
<< support::iround(scl)
|
||||
<< "\" ";
|
||||
} else {
|
||||
if (!params().width.zero()) {
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "support/debug.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/lyxlib.h"
|
||||
#include "support/textutils.h"
|
||||
|
||||
|
||||
@ -77,9 +78,9 @@ void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
}
|
||||
int const em = mathed_font_em(mi.base.font);
|
||||
if (isBinaryOp(char_))
|
||||
dim.wid += static_cast<int>(0.5*em+0.5);
|
||||
dim.wid += support::iround(0.5 * em);
|
||||
else if (char_ == '\'')
|
||||
dim.wid += static_cast<int>(0.1667*em+0.5);
|
||||
dim.wid += support::iround(0.1667 * em);
|
||||
#else
|
||||
whichFont(font_, code_, mi);
|
||||
dim = theFontMetrics(font_).dimension(char_);
|
||||
@ -95,9 +96,9 @@ void InsetMathChar::draw(PainterInfo & pi, int x, int y) const
|
||||
//lyxerr << "drawing '" << char_ << "' font: " << pi.base.fontname << std::endl;
|
||||
int const em = mathed_font_em(pi.base.font);
|
||||
if (isBinaryOp(char_))
|
||||
x += static_cast<int>(0.25*em+0.5);
|
||||
x += support::iround(0.25 * em);
|
||||
else if (char_ == '\'')
|
||||
x += static_cast<int>(0.0833*em+0.5);
|
||||
x += support::iround(0.0833 * em);
|
||||
#if 1
|
||||
if (char_ == '=' && has_math_fonts) {
|
||||
FontSetChanger dummy(pi.base, "cmr");
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "support/debug.h"
|
||||
#include "support/docstream.h"
|
||||
#include "support/lyxlib.h"
|
||||
#include "support/textutils.h"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
@ -80,9 +81,9 @@ void InsetMathSymbol::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
}
|
||||
// seperate things a bit
|
||||
if (isRelOp())
|
||||
dim.wid += static_cast<int>(0.5 * em + 0.5);
|
||||
dim.wid += support::iround(0.5 * em);
|
||||
else
|
||||
dim.wid += static_cast<int>(0.1667 * em + 0.5);
|
||||
dim.wid += support::iround(0.1667 * em);
|
||||
|
||||
scriptable_ = false;
|
||||
if (mi.base.style == LM_ST_DISPLAY)
|
||||
@ -106,9 +107,9 @@ void InsetMathSymbol::draw(PainterInfo & pi, int x, int y) const
|
||||
std::string const font = italic_upcase_greek ? "cmm" : sym_->inset;
|
||||
int const em = mathed_font_em(pi.base.font);
|
||||
if (isRelOp())
|
||||
x += static_cast<int>(0.25*em+0.5);
|
||||
x += support::iround(0.25 * em);
|
||||
else
|
||||
x += static_cast<int>(0.0833*em+0.5);
|
||||
x += support::iround(0.0833 * em);
|
||||
|
||||
FontSetChanger dummy(pi.base, from_ascii(font));
|
||||
pi.draw(x, y - h_, sym_->draw);
|
||||
|
@ -16,13 +16,13 @@
|
||||
|
||||
#include "support/convert.h"
|
||||
#include "support/debug.h"
|
||||
#include "support/lyxlib.h"
|
||||
#include "support/qstring_helpers.h"
|
||||
|
||||
#include "support/lassert.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
@ -1400,18 +1400,6 @@ int findToken(char const * const str[], string const & search_token)
|
||||
}
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Replacement for C99 function lround()
|
||||
double round(double x)
|
||||
{
|
||||
if (x < 0)
|
||||
return ceil(x - 0.5);
|
||||
else
|
||||
return floor(x + 0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
std::string formatFPNumber(double x)
|
||||
{
|
||||
// Need manual tweaking, QString::number(x, 'f', 16) does not work either
|
||||
@ -1420,7 +1408,7 @@ std::string formatFPNumber(double x)
|
||||
// Prevent outputs of 23.4200000000000017 but output small numbers
|
||||
// with at least 6 significant digits.
|
||||
double const logarithm = log10(fabs(x));
|
||||
os << std::setprecision(max(6 - static_cast<int>(round(logarithm)), 0)) << x;
|
||||
os << std::setprecision(max(6 - iround(logarithm), 0)) << x;
|
||||
string result = os.str();
|
||||
if (result.find('.') != string::npos) {
|
||||
result = rtrim(result, "0");
|
||||
|
@ -15,6 +15,20 @@
|
||||
#ifndef LYX_LIB_H
|
||||
#define LYX_LIB_H
|
||||
|
||||
// always include <math.h> (also with MSVC), to avoid compiler specific side effects
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/// Replacement for C99 round()
|
||||
inline double round(double x)
|
||||
{
|
||||
if (x < 0)
|
||||
return ceil(x - 0.5);
|
||||
else
|
||||
return floor(x + 0.5);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace lyx {
|
||||
namespace support {
|
||||
|
||||
@ -34,6 +48,12 @@ inline bool float_equal(double var, double number, double error)
|
||||
return (number - error <= var && var <= number + error);
|
||||
}
|
||||
|
||||
/// round \p x to nearest integer
|
||||
inline int iround(double x)
|
||||
{
|
||||
return static_cast<int>(round(x));
|
||||
}
|
||||
|
||||
} // namespace support
|
||||
} // namespace lyx
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user