Coverage Report

Created: 2026-06-23 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/methods/finitedifferences/utilities/fdmdividendhandler.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2008 Andreas Gaida
5
 Copyright (C) 2008, 2009 Ralph Schreyer
6
 Copyright (C) 2008 Klaus Spanderen
7
8
 This file is part of QuantLib, a free-software/open-source library
9
 for financial quantitative analysts and developers - http://quantlib.org/
10
11
 QuantLib is free software: you can redistribute it and/or modify it
12
 under the terms of the QuantLib license.  You should have received a
13
 copy of the license along with this program; if not, please email
14
 <quantlib-dev@lists.sf.net>. The license is also available online at
15
 <https://www.quantlib.org/license.shtml>.
16
17
 This program is distributed in the hope that it will be useful, but WITHOUT
18
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 FOR A PARTICULAR PURPOSE.  See the license for more details.
20
*/
21
22
#include <ql/time/daycounter.hpp>
23
#include <ql/math/interpolations/linearinterpolation.hpp>
24
#include <ql/methods/finitedifferences/operators/fdmlinearoplayout.hpp>
25
#include <ql/methods/finitedifferences/utilities/fdmdividendhandler.hpp>
26
27
namespace QuantLib {
28
29
30
    FdmDividendHandler::FdmDividendHandler(
31
        const DividendSchedule& schedule,
32
        const ext::shared_ptr<FdmMesher>& mesher,
33
        const Date& referenceDate,
34
        const DayCounter& dayCounter,
35
        Size equityDirection)
36
897
    : x_(mesher->layout()->dim()[equityDirection]),
37
897
      mesher_(mesher),
38
897
      equityDirection_(equityDirection) {
39
40
897
        dividends_.reserve(schedule.size());
41
897
        dividendDates_.reserve(schedule.size());
42
897
        dividendTimes_.reserve(schedule.size());
43
897
        for (const auto& iter : schedule) {
44
0
            dividends_.push_back(iter->amount());
45
0
            dividendDates_.push_back(iter->date());
46
0
            dividendTimes_.push_back(dayCounter.yearFraction(referenceDate, iter->date()));
47
0
        }
48
49
897
         Array tmp = mesher_->locations(equityDirection);
50
897
         Size spacing = mesher_->layout()->spacing()[equityDirection];
51
90.5k
         for (Size i = 0; i < x_.size(); ++i) {
52
89.7k
             x_[i] = std::exp(tmp[i*spacing]);
53
89.7k
         }
54
897
    }
55
56
0
    const std::vector<Time>& FdmDividendHandler::dividendTimes() const {
57
0
        return dividendTimes_;
58
0
    }
59
         
60
0
    const std::vector<Date>& FdmDividendHandler::dividendDates() const {
61
0
        return dividendDates_;
62
0
    }
63
64
0
    const std::vector<Real>& FdmDividendHandler::dividends() const {
65
0
        return dividends_;
66
0
    }
67
68
0
    void FdmDividendHandler::applyTo(Array& a, Time t) const {
69
0
        Array aCopy(a);
70
71
0
        auto iter = std::find(dividendTimes_.begin(), dividendTimes_.end(), t);
72
73
0
        if (iter != dividendTimes_.end()) {
74
0
            const Real dividend = dividends_[iter - dividendTimes_.begin()];
75
76
0
            if (mesher_->layout()->dim().size() == 1) {
77
0
                LinearInterpolation interp(x_.begin(), x_.end(), aCopy.begin());
78
0
                for (Size k=0; k<x_.size(); ++k) {
79
0
                    a[k] = interp(std::max(x_[0], x_[k]-dividend), true);
80
0
                }
81
0
            }
82
0
            else {
83
0
                Array tmp(x_.size());
84
0
                Size xSpacing = mesher_->layout()->spacing()[equityDirection_];
85
                
86
0
                for (Size i=0; i<mesher_->layout()->dim().size(); ++i) {
87
0
                    if (i!=equityDirection_) {
88
0
                        Size ySpacing = mesher_->layout()->spacing()[i];
89
0
                        for (Size j=0; j<mesher_->layout()->dim()[i]; ++j) {
90
0
                            for (Size k=0; k<x_.size(); ++k) {
91
0
                                Size index = j*ySpacing + k*xSpacing;
92
0
                                tmp[k] = aCopy[index];
93
0
                            }
94
0
                            LinearInterpolation interp(x_.begin(), x_.end(),
95
0
                                                       tmp.begin());
96
0
                            for (Size k=0; k<x_.size(); ++k) {
97
0
                                Size index = j*ySpacing + k*xSpacing;
98
0
                                a[index] = interp(
99
0
                                        std::max(x_[0], x_[k]-dividend), true);
100
0
                            }
101
0
                        }
102
0
                    }
103
0
                }
104
0
            }
105
0
        }
106
0
    }
107
}