Coverage Report

Created: 2025-12-08 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/math/rounding.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2004 Decillion Pty(Ltd)
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
/*! \file rounding.hpp
21
    \brief Rounding implementation
22
*/
23
24
#include <ql/math/rounding.hpp>
25
#include <ql/errors.hpp>
26
27
namespace QuantLib {
28
29
0
    static inline Real fast_pow10(Integer precision) {
30
        // Providing support for truncating up to 16 decimal places after dot
31
0
        constexpr static double pow10_lut[0x20] = {
32
0
            1.0E0,  1.0E1,  1.0E2,  1.0E3,  1.0E4,  1.0E5,
33
0
            1.0E6,  1.0E7,  1.0E8,  1.0E9,  1.0E10, 1.0E11,
34
0
            1.0E12, 1.0E13, 1.0E14, 1.0E15, 1.0E16
35
0
            /*the rest of the numbers are zeros*/};
36
        // Skipping precision input value checks without causing a crash
37
0
        return pow10_lut[precision & 0x1F];
38
0
    }
39
40
0
    Decimal Rounding::operator()(Decimal value) const {
41
42
0
        if (type_ == None)
43
0
            return value;
44
45
0
        Real mult = fast_pow10(precision_);
46
0
        bool neg = (value < 0.0);
47
0
        Real lvalue = std::fabs(value)*mult;
48
0
        Real integral = 0.0;
49
0
        Real modVal = std::modf(lvalue,&integral);
50
0
        lvalue -= modVal;
51
0
        switch (type_) {
52
0
          case Down:
53
0
            break;
54
0
          case Up:
55
0
            if (modVal != 0.0)
56
0
                lvalue += 1.0;
57
0
            break;
58
0
          case Closest:
59
0
            if (modVal >= (digit_/10.0))
60
0
                lvalue += 1.0;
61
0
            break;
62
0
          case Floor:
63
0
            if (!neg) {
64
0
                if (modVal >= (digit_/10.0))
65
0
                    lvalue += 1.0;
66
0
            }
67
0
            break;
68
0
          case Ceiling:
69
0
            if (neg) {
70
0
                if (modVal >= (digit_/10.0))
71
0
                    lvalue += 1.0;
72
0
            }
73
0
            break;
74
0
          default:
75
0
            QL_FAIL("unknown rounding method");
76
0
        }
77
0
        return (neg) ? Real(-(lvalue / mult)) : Real(lvalue / mult);
78
0
    }
79
80
}