Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/o3tl/unit_conversion.hxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 */
9
10
#pragma once
11
12
#include <o3tl/safeint.hxx>
13
#include <sal/types.h>
14
15
#include <array>
16
#include <cassert>
17
#include <concepts>
18
#include <numeric>
19
#include <utility>
20
#include <type_traits>
21
22
namespace o3tl
23
{
24
// Length units
25
enum class Length
26
{
27
    mm100 = 0, // 1/100th mm
28
    mm10, // 1/10 mm, corresponds to MapUnit::Map10thMM
29
    mm, // millimeter
30
    cm, // centimeter
31
    m, // meter
32
    km, // kilometer
33
    emu, // English Metric Unit: 1/360000 cm, 1/914400 in
34
    twip, // "Twentieth of a point" aka "dxa": 1/20 pt
35
    pt, // Point: 1/72 in
36
    pc, // Pica: 1/6 in, corresponds to FieldUnit::PICA and MeasureUnit::PICA
37
    in1000, // 1/1000 in, corresponds to MapUnit::Map1000thInch
38
    in100, // 1/100 in, corresponds to MapUnit::Map100thInch
39
    in10, // 1/10 in, corresponds to MapUnit::Map10thInch
40
    in, // inch
41
    ft, // foot
42
    mi, // mile
43
    master, // PPT Master Unit: 1/576 in
44
    px, // "pixel" unit: 15 twip (96 ppi), corresponds to MeasureUnit::PIXEL
45
    ch, // "char" unit: 210 twip (14 px), corresponds to FieldUnit::CHAR
46
    line, // "line" unit: 312 twip, corresponds to FieldUnit::LINE
47
    count, // <== add new units above this last entry
48
    invalid = -1
49
};
50
51
// If other categories of units would be needed (like time), a separate scoped enum
52
// should be created, respective conversion array prepared in detail namespace, and
53
// respective md(NewUnit, NewUnit) overload introduced, which would allow using
54
// o3tl::convert(), o3tl::convertSaturate() and o3tl::getConversionMulDiv() with the
55
// new category in a type-safe way, without mixing unrelated units.
56
57
namespace detail
58
{
59
// Common utilities
60
61
// A special function to avoid compiler warning comparing signed and unsigned values
62
template <typename I> constexpr bool isBetween(I n, sal_Int64 min, sal_Int64 max)
63
1.36M
{
64
1.36M
    assert(max > 0 && min < 0);
65
    if constexpr (std::is_signed_v<I>)
66
1.36M
        return n >= min && n <= max;
67
    else
68
        return n <= sal_uInt64(max);
69
1.36M
}
bool o3tl::detail::isBetween<long>(long, long, long)
Line
Count
Source
63
1.36M
{
64
1.36M
    assert(max > 0 && min < 0);
65
    if constexpr (std::is_signed_v<I>)
66
1.36M
        return n >= min && n <= max;
67
    else
68
        return n <= sal_uInt64(max);
69
1.36M
}
Unexecuted instantiation: bool o3tl::detail::isBetween<int>(int, long, long)
70
71
// Ensure correct rounding for both positive and negative integers
72
template <std::integral I> constexpr sal_Int64 MulDiv(I n, sal_Int64 m, sal_Int64 d)
73
167M
{
74
167M
    assert(m > 0 && d > 0);
75
167M
    assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m));
76
    // coverity[dead_error_line] - suppress warning for template
77
167M
    return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d;
78
167M
}
_ZN4o3tl6detail6MulDivITkNSt3__18integralElEElT_ll
Line
Count
Source
73
4.63M
{
74
4.63M
    assert(m > 0 && d > 0);
75
4.63M
    assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m));
76
    // coverity[dead_error_line] - suppress warning for template
77
4.63M
    return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d;
78
4.63M
}
_ZN4o3tl6detail6MulDivITkNSt3__18integralEiEElT_ll
Line
Count
Source
73
154M
{
74
154M
    assert(m > 0 && d > 0);
75
154M
    assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m));
76
    // coverity[dead_error_line] - suppress warning for template
77
154M
    return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d;
78
154M
}
_ZN4o3tl6detail6MulDivITkNSt3__18integralEtEElT_ll
Line
Count
Source
73
200k
{
74
200k
    assert(m > 0 && d > 0);
75
200k
    assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m));
76
    // coverity[dead_error_line] - suppress warning for template
77
200k
    return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d;
78
200k
}
_ZN4o3tl6detail6MulDivITkNSt3__18integralEsEElT_ll
Line
Count
Source
73
196k
{
74
196k
    assert(m > 0 && d > 0);
75
196k
    assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m));
76
    // coverity[dead_error_line] - suppress warning for template
77
196k
    return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d;
78
196k
}
_ZN4o3tl6detail6MulDivITkNSt3__18integralEmEElT_ll
Line
Count
Source
73
477k
{
74
477k
    assert(m > 0 && d > 0);
75
477k
    assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m));
76
    // coverity[dead_error_line] - suppress warning for template
77
477k
    return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d;
78
477k
}
_ZN4o3tl6detail6MulDivITkNSt3__18integralEjEElT_ll
Line
Count
Source
73
7.62M
{
74
7.62M
    assert(m > 0 && d > 0);
75
7.62M
    assert(isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m));
76
    // coverity[dead_error_line] - suppress warning for template
77
7.62M
    return (n >= 0 ? (n * m + d / 2) : (n * m - d / 2)) / d;
78
7.62M
}
Unexecuted instantiation: _ZN4o3tl6detail6MulDivITkNSt3__18integralEaEElT_ll
79
template <std::floating_point F> constexpr double MulDiv(F f, sal_Int64 m, sal_Int64 d)
80
10.2M
{
81
10.2M
    assert(m > 0 && d > 0);
82
10.2M
    return f * (double(m) / d);
83
10.2M
}
_ZN4o3tl6detail6MulDivITkNSt3__114floating_pointEdEEdT_ll
Line
Count
Source
80
10.2M
{
81
    assert(m > 0 && d > 0);
82
10.2M
    return f * (double(m) / d);
83
10.2M
}
Unexecuted instantiation: _ZN4o3tl6detail6MulDivITkNSt3__114floating_pointEfEEdT_ll
84
85
template <std::integral I>
86
constexpr sal_Int64 MulDiv(I n, sal_Int64 m, sal_Int64 d, bool& bOverflow, sal_Int64 nDefault)
87
1.28M
{
88
1.28M
    if (!isBetween(n, (SAL_MIN_INT64 + d / 2) / m, (SAL_MAX_INT64 - d / 2) / m))
89
1
    {
90
1
        bOverflow = true;
91
1
        return nDefault;
92
1
    }
93
1.28M
    bOverflow = false;
94
1.28M
    return MulDiv(n, m, d);
95
1.28M
}
96
97
template <std::integral I> constexpr sal_Int64 MulDivSaturate(I n, sal_Int64 m, sal_Int64 d)
98
71.9k
{
99
71.9k
    if (sal_Int64 d_2 = d / 2; !isBetween(n, (SAL_MIN_INT64 + d_2) / m, (SAL_MAX_INT64 - d_2) / m))
100
12
    {
101
12
        if (n >= 0)
102
12
        {
103
12
            if (m > d && std::make_unsigned_t<I>(n) > sal_uInt64(SAL_MAX_INT64 / m * d - d_2))
104
0
                return SAL_MAX_INT64; // saturate
105
            // coverity[ tainted_data_return : SUPPRESS ] 2024.6.1
106
12
            return saturating_add<sal_uInt64>(n, d_2) / d * m; // divide before multiplication
107
12
        }
108
        else if constexpr (std::is_signed_v<I>) // n < 0; don't compile for unsigned n
109
0
        {
110
0
            if (m > d && n < SAL_MIN_INT64 / m * d + d_2)
111
0
                return SAL_MIN_INT64; // saturate
112
0
            return saturating_sub<sal_Int64>(n, d_2) / d * m; // divide before multiplication
113
0
        }
114
12
    }
115
71.9k
    return MulDiv(n, m, d);
116
71.9k
}
Unexecuted instantiation: _ZN4o3tl6detail14MulDivSaturateITkNSt3__18integralElEElT_ll
Unexecuted instantiation: _ZN4o3tl6detail14MulDivSaturateITkNSt3__18integralEiEElT_ll
_ZN4o3tl6detail14MulDivSaturateITkNSt3__18integralElEElT_ll
Line
Count
Source
98
71.9k
{
99
71.9k
    if (sal_Int64 d_2 = d / 2; !isBetween(n, (SAL_MIN_INT64 + d_2) / m, (SAL_MAX_INT64 - d_2) / m))
100
12
    {
101
12
        if (n >= 0)
102
12
        {
103
12
            if (m > d && std::make_unsigned_t<I>(n) > sal_uInt64(SAL_MAX_INT64 / m * d - d_2))
104
0
                return SAL_MAX_INT64; // saturate
105
            // coverity[ tainted_data_return : SUPPRESS ] 2024.6.1
106
12
            return saturating_add<sal_uInt64>(n, d_2) / d * m; // divide before multiplication
107
12
        }
108
        else if constexpr (std::is_signed_v<I>) // n < 0; don't compile for unsigned n
109
0
        {
110
0
            if (m > d && n < SAL_MIN_INT64 / m * d + d_2)
111
0
                return SAL_MIN_INT64; // saturate
112
0
            return saturating_sub<sal_Int64>(n, d_2) / d * m; // divide before multiplication
113
0
        }
114
12
    }
115
71.9k
    return MulDiv(n, m, d);
116
71.9k
}
117
118
template <class M, class N> constexpr std::common_type_t<M, N> asserting_gcd(M m, N n)
119
0
{
120
0
    auto ret = std::gcd(m, n);
121
0
    assert(ret != 0);
122
0
    return ret;
123
0
}
124
125
// Packs integral multiplier and divisor for conversion from one unit to another
126
struct m_and_d
127
{
128
    sal_Int64 m; // multiplier
129
    sal_Int64 d; // divisor
130
    constexpr m_and_d(sal_Int64 _m, sal_Int64 _d)
131
        : m(_m / asserting_gcd(_m, _d)) // make sure to use smallest quotients here because
132
        , d(_d / asserting_gcd(_m, _d)) // they will be multiplied when building final table
133
0
    {
134
0
        assert(_m > 0 && _d > 0);
135
0
    }
136
};
137
138
// Resulting static array N x N of all quotients to convert between all units. The
139
// quotients are minimal to allow largest range of converted numbers without overflow.
140
// Maybe o3tl::enumarray could be used here, but it's not constexpr yet.
141
template <int N> constexpr auto prepareMDArray(const m_and_d (&mdBase)[N])
142
0
{
143
0
    std::array<std::array<sal_Int64, N>, N> a{};
144
0
    for (int i = 0; i < N; ++i)
145
0
    {
146
0
        a[i][i] = 1;
147
0
        for (int j = 0; j < i; ++j)
148
0
        {
149
0
            assert(mdBase[i].m < SAL_MAX_INT64 / mdBase[j].d);
150
0
            assert(mdBase[i].d < SAL_MAX_INT64 / mdBase[j].m);
151
0
            const sal_Int64 m = mdBase[i].m * mdBase[j].d, d = mdBase[i].d * mdBase[j].m;
152
0
            const sal_Int64 g = asserting_gcd(m, d);
153
0
            a[i][j] = m / g;
154
0
            a[j][i] = d / g;
155
0
        }
156
0
    }
157
0
    return a;
158
0
}
159
160
// A generic template used for fundamental arithmetic types
161
6
template <typename U> constexpr sal_Int64 md(U i, U /*j*/) { return i; }
long o3tl::detail::md<int>(int, int)
Line
Count
Source
161
6
template <typename U> constexpr sal_Int64 md(U i, U /*j*/) { return i; }
Unexecuted instantiation: long o3tl::detail::md<long>(long, long)
162
163
// Length units implementation
164
165
// Array of conversion quotients for mm, used to build final conversion table. Entries
166
// are { multiplier, divider } to convert respective unit *to* mm. Order of elements
167
// corresponds to order in o3tl::Length enum (Length::count and Length::invalid omitted).
168
constexpr m_and_d mdBaseLen[] = {
169
    { 1, 100 }, // mm100 => mm
170
    { 1, 10 }, // mm10 => mm
171
    { 1, 1 }, // mm => mm
172
    { 10, 1 }, // cm => mm
173
    { 1000, 1 }, // m => mm
174
    { 1000000, 1 }, // km => mm
175
    { 1, 36000 }, // emu => mm
176
    { 254, 10 * 1440 }, // twip => mm
177
    { 254, 10 * 72 }, // pt => mm
178
    { 254, 10 * 6 }, // pc => mm
179
    { 254, 10000 }, // in1000 => mm
180
    { 254, 1000 }, // in100 => mm
181
    { 254, 100 }, // in10 => mm
182
    { 254, 10 }, // in => mm
183
    { 254 * 12, 10 }, // ft => mm
184
    { 254 * 12 * 5280, 10 }, // mi => mm
185
    { 254, 10 * 576 }, // master => mm
186
    { 254 * 15, 10 * 1440 }, // px => mm
187
    { 254 * 210, 10 * 1440 }, // ch => mm
188
    { 254 * 312, 10 * 1440 }, // line => mm
189
};
190
static_assert(std::size(mdBaseLen) == static_cast<int>(Length::count),
191
              "mdBaseL must have an entry for each unit in o3tl::Length");
192
193
// The resulting multipliers and divisors array
194
constexpr auto aLengthMDArray = prepareMDArray(mdBaseLen);
195
196
// an overload taking Length
197
constexpr sal_Int64 md(Length i, Length j)
198
400M
{
199
400M
    const int nI = static_cast<int>(i), nJ = static_cast<int>(j);
200
400M
    assert(nI >= 0 && o3tl::make_unsigned(nI) < aLengthMDArray.size());
201
400M
    assert(nJ >= 0 && o3tl::make_unsigned(nJ) < aLengthMDArray.size());
202
400M
    return aLengthMDArray[nI][nJ];
203
400M
}
204
205
// here might go overloads of md() taking other units ...
206
}
207
208
// Unchecked conversion. Takes a number value, multiplier and divisor
209
template <typename N> constexpr auto convert(N n, sal_Int64 mul, sal_Int64 div)
210
176M
{
211
176M
    return detail::MulDiv(n, mul, div);
212
176M
}
auto o3tl::convert<long>(long, long, long)
Line
Count
Source
210
3.27M
{
211
3.27M
    return detail::MulDiv(n, mul, div);
212
3.27M
}
auto o3tl::convert<int>(int, long, long)
Line
Count
Source
210
154M
{
211
154M
    return detail::MulDiv(n, mul, div);
212
154M
}
auto o3tl::convert<double>(double, long, long)
Line
Count
Source
210
10.2M
{
211
10.2M
    return detail::MulDiv(n, mul, div);
212
10.2M
}
Unexecuted instantiation: auto o3tl::convert<float>(float, long, long)
auto o3tl::convert<unsigned short>(unsigned short, long, long)
Line
Count
Source
210
200k
{
211
200k
    return detail::MulDiv(n, mul, div);
212
200k
}
auto o3tl::convert<short>(short, long, long)
Line
Count
Source
210
196k
{
211
196k
    return detail::MulDiv(n, mul, div);
212
196k
}
auto o3tl::convert<unsigned long>(unsigned long, long, long)
Line
Count
Source
210
477k
{
211
477k
    return detail::MulDiv(n, mul, div);
212
477k
}
auto o3tl::convert<unsigned int>(unsigned int, long, long)
Line
Count
Source
210
7.62M
{
211
7.62M
    return detail::MulDiv(n, mul, div);
212
7.62M
}
Unexecuted instantiation: auto o3tl::convert<signed char>(signed char, long, long)
213
214
// Unchecked conversion. Takes a number value and units defined in this header
215
template <typename N, typename U> constexpr auto convert(N n, U from, U to)
216
171M
{
217
171M
    return convert(n, detail::md(from, to), detail::md(to, from));
218
171M
}
auto o3tl::convert<long, o3tl::Length>(long, o3tl::Length, o3tl::Length)
Line
Count
Source
216
2.80M
{
217
2.80M
    return convert(n, detail::md(from, to), detail::md(to, from));
218
2.80M
}
auto o3tl::convert<int, o3tl::Length>(int, o3tl::Length, o3tl::Length)
Line
Count
Source
216
154M
{
217
154M
    return convert(n, detail::md(from, to), detail::md(to, from));
218
154M
}
auto o3tl::convert<double, o3tl::Length>(double, o3tl::Length, o3tl::Length)
Line
Count
Source
216
6.18M
{
217
6.18M
    return convert(n, detail::md(from, to), detail::md(to, from));
218
6.18M
}
Unexecuted instantiation: auto o3tl::convert<float, o3tl::Length>(float, o3tl::Length, o3tl::Length)
Unexecuted instantiation: auto o3tl::convert<long, int>(long, int, int)
auto o3tl::convert<unsigned short, o3tl::Length>(unsigned short, o3tl::Length, o3tl::Length)
Line
Count
Source
216
200k
{
217
200k
    return convert(n, detail::md(from, to), detail::md(to, from));
218
200k
}
auto o3tl::convert<short, o3tl::Length>(short, o3tl::Length, o3tl::Length)
Line
Count
Source
216
196k
{
217
196k
    return convert(n, detail::md(from, to), detail::md(to, from));
218
196k
}
auto o3tl::convert<unsigned long, o3tl::Length>(unsigned long, o3tl::Length, o3tl::Length)
Line
Count
Source
216
477k
{
217
477k
    return convert(n, detail::md(from, to), detail::md(to, from));
218
477k
}
auto o3tl::convert<unsigned int, o3tl::Length>(unsigned int, o3tl::Length, o3tl::Length)
Line
Count
Source
216
7.62M
{
217
7.62M
    return convert(n, detail::md(from, to), detail::md(to, from));
218
7.62M
}
Unexecuted instantiation: auto o3tl::convert<signed char, o3tl::Length>(signed char, o3tl::Length, o3tl::Length)
auto o3tl::convert<int, int>(int, int, int)
Line
Count
Source
216
3
{
217
3
    return convert(n, detail::md(from, to), detail::md(to, from));
218
3
}
219
220
// Convert to twips - for convenience as we do this a lot
221
template <typename N> constexpr auto toTwips(N number, Length from)
222
4.93M
{
223
4.93M
    return convert(number, from, Length::twip);
224
4.93M
}
auto o3tl::toTwips<double>(double, o3tl::Length)
Line
Count
Source
222
181k
{
223
181k
    return convert(number, from, Length::twip);
224
181k
}
auto o3tl::toTwips<long>(long, o3tl::Length)
Line
Count
Source
222
139k
{
223
139k
    return convert(number, from, Length::twip);
224
139k
}
auto o3tl::toTwips<unsigned int>(unsigned int, o3tl::Length)
Line
Count
Source
222
3.03M
{
223
3.03M
    return convert(number, from, Length::twip);
224
3.03M
}
auto o3tl::toTwips<int>(int, o3tl::Length)
Line
Count
Source
222
1.45M
{
223
1.45M
    return convert(number, from, Length::twip);
224
1.45M
}
auto o3tl::toTwips<short>(short, o3tl::Length)
Line
Count
Source
222
113k
{
223
113k
    return convert(number, from, Length::twip);
224
113k
}
auto o3tl::toTwips<unsigned short>(unsigned short, o3tl::Length)
Line
Count
Source
222
9.37k
{
223
9.37k
    return convert(number, from, Length::twip);
224
9.37k
}
Unexecuted instantiation: auto o3tl::toTwips<Point>(Point, o3tl::Length)
Unexecuted instantiation: auto o3tl::toTwips<Size>(Size, o3tl::Length)
Unexecuted instantiation: auto o3tl::toTwips<tools::Rectangle>(tools::Rectangle, o3tl::Length)
auto o3tl::toTwips<unsigned long>(unsigned long, o3tl::Length)
Line
Count
Source
222
257
{
223
257
    return convert(number, from, Length::twip);
224
257
}
225
226
// Returns nDefault if intermediate multiplication overflows sal_Int64 (only for integral types).
227
// On return, bOverflow indicates if overflow happened. nDefault is returned when overflow occurs.
228
template <typename N, typename U>
229
constexpr auto convert(N n, U from, U to, bool& bOverflow, sal_Int64 nDefault = 0)
230
1.28M
{
231
1.28M
    return detail::MulDiv(n, detail::md(from, to), detail::md(to, from), bOverflow, nDefault);
232
1.28M
}
233
234
// Conversion with saturation (only for integral types). For too large input returns SAL_MAX_INT64.
235
// When intermediate multiplication would overflow, but the end result is in sal_Int64 range, the
236
// precision is decreased because of inversion of multiplication and division.
237
template <typename N, typename U> constexpr auto convertSaturate(N n, U from, U to)
238
71.9k
{
239
71.9k
    return detail::MulDivSaturate(n, detail::md(from, to), detail::md(to, from));
240
71.9k
}
Unexecuted instantiation: auto o3tl::convertSaturate<int, o3tl::Length>(int, o3tl::Length, o3tl::Length)
auto o3tl::convertSaturate<long, o3tl::Length>(long, o3tl::Length, o3tl::Length)
Line
Count
Source
238
71.9k
{
239
71.9k
    return detail::MulDivSaturate(n, detail::md(from, to), detail::md(to, from));
240
71.9k
}
Unexecuted instantiation: auto o3tl::convertSaturate<int, long>(int, long, long)
241
242
// Conversion with saturation (only for integral types), optimized for return types smaller than
243
// sal_Int64. In this case, it's easier to clamp input values to known bounds, than to do some
244
// preprocessing to handle too large input values, just to clamp the result anyway. Use it like:
245
//
246
//     sal_Int32 n = convertNarrowing<sal_Int32, o3tl::Length::mm100, o3tl::Length::emu>(m);
247
template <std::integral Out, auto from, auto to, std::integral N>
248
requires(sizeof(Out) < sizeof(sal_Int64)) constexpr Out convertNarrowing(N n)
249
685k
{
250
685k
    constexpr sal_Int64 nMin = convertSaturate(std::numeric_limits<Out>::min(), to, from);
251
685k
    constexpr sal_Int64 nMax = convertSaturate(std::numeric_limits<Out>::max(), to, from);
252
685k
    if (static_cast<sal_Int64>(n) > nMax)
253
0
        return std::numeric_limits<Out>::max();
254
685k
    if (static_cast<sal_Int64>(n) < nMin)
255
0
        return std::numeric_limits<Out>::min();
256
685k
    return convert(n, from, to);
257
685k
}
_ZN4o3tl16convertNarrowingITkNSt3__18integralEiTnDaLNS_6LengthE6ETnDaLS2_0ETkNS1_8integralElQltstT_Lm8EEES3_T2_
Line
Count
Source
249
203k
{
250
203k
    constexpr sal_Int64 nMin = convertSaturate(std::numeric_limits<Out>::min(), to, from);
251
203k
    constexpr sal_Int64 nMax = convertSaturate(std::numeric_limits<Out>::max(), to, from);
252
203k
    if (static_cast<sal_Int64>(n) > nMax)
253
0
        return std::numeric_limits<Out>::max();
254
203k
    if (static_cast<sal_Int64>(n) < nMin)
255
0
        return std::numeric_limits<Out>::min();
256
203k
    return convert(n, from, to);
257
203k
}
_ZN4o3tl16convertNarrowingITkNSt3__18integralEiTnDaLl127ETnDaLl360ETkNS1_8integralEiQltstT_Lm8EEES2_T2_
Line
Count
Source
249
482k
{
250
482k
    constexpr sal_Int64 nMin = convertSaturate(std::numeric_limits<Out>::min(), to, from);
251
482k
    constexpr sal_Int64 nMax = convertSaturate(std::numeric_limits<Out>::max(), to, from);
252
482k
    if (static_cast<sal_Int64>(n) > nMax)
253
0
        return std::numeric_limits<Out>::max();
254
482k
    if (static_cast<sal_Int64>(n) < nMin)
255
0
        return std::numeric_limits<Out>::min();
256
482k
    return convert(n, from, to);
257
482k
}
258
259
// Return a pair { multiplier, divisor } for a given conversion
260
template <typename U> constexpr std::pair<sal_Int64, sal_Int64> getConversionMulDiv(U from, U to)
261
27.0M
{
262
27.0M
    return { detail::md(from, to), detail::md(to, from) };
263
27.0M
}
264
}
265
266
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */