1 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | |
3 | /* |
4 | Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb |
5 | Copyright (C) 2005, 2006 StatPro Italia srl |
6 | |
7 | This file is part of QuantLib, a free-software/open-source library |
8 | for financial quantitative analysts and developers - http://quantlib.org/ |
9 | |
10 | QuantLib is free software: you can redistribute it and/or modify it |
11 | under the terms of the QuantLib license. You should have received a |
12 | copy of the license along with this program; if not, please email |
13 | <quantlib-dev@lists.sf.net>. The license is also available online at |
14 | <http://quantlib.org/license.shtml>. |
15 | |
16 | This program is distributed in the hope that it will be useful, but WITHOUT |
17 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
18 | FOR A PARTICULAR PURPOSE. See the license for more details. |
19 | */ |
20 | |
21 | #include <ql/timegrid.hpp> |
22 | #include <iomanip> |
23 | |
24 | namespace QuantLib { |
25 | |
26 | TimeGrid::TimeGrid(Time end, Size steps) { |
27 | // We seem to assume that the grid begins at 0. |
28 | // Let's enforce the assumption for the time being |
29 | // (even though I'm not sure that I agree.) |
30 | QL_REQUIRE(end > 0.0, |
31 | "negative times not allowed" ); |
32 | Time dt = end/steps; |
33 | times_.reserve(n: steps+1); |
34 | for (Size i=0; i<=steps; i++) |
35 | times_.push_back(x: dt*i); |
36 | |
37 | mandatoryTimes_ = std::vector<Time>(1); |
38 | mandatoryTimes_[0] = end; |
39 | |
40 | dt_ = std::vector<Time>(steps,dt); |
41 | } |
42 | |
43 | Size TimeGrid::index(Time t) const { |
44 | Size i = closestIndex(t); |
45 | if (close_enough(x: t,y: times_[i])) { |
46 | return i; |
47 | } else { |
48 | if (t < times_.front()) { |
49 | QL_FAIL("using inadequate time grid: all nodes " |
50 | "are later than the required time t = " |
51 | << std::setprecision(12) << t |
52 | << " (earliest node is t1 = " |
53 | << std::setprecision(12) << times_.front() << ")" ); |
54 | } else if (t > times_.back()) { |
55 | QL_FAIL("using inadequate time grid: all nodes " |
56 | "are earlier than the required time t = " |
57 | << std::setprecision(12) << t |
58 | << " (latest node is t1 = " |
59 | << std::setprecision(12) << times_.back() << ")" ); |
60 | } else { |
61 | Size j, k; |
62 | if (t > times_[i]) { |
63 | j = i; |
64 | k = i+1; |
65 | } else { |
66 | j = i-1; |
67 | k = i; |
68 | } |
69 | QL_FAIL("using inadequate time grid: the nodes closest " |
70 | "to the required time t = " |
71 | << std::setprecision(12) << t |
72 | << " are t1 = " |
73 | << std::setprecision(12) << times_[j] |
74 | << " and t2 = " |
75 | << std::setprecision(12) << times_[k]); |
76 | } |
77 | } |
78 | } |
79 | |
80 | Size TimeGrid::closestIndex(Time t) const { |
81 | auto begin = times_.begin(), end = times_.end(); |
82 | auto result = std::lower_bound(first: begin, last: end, val: t); |
83 | if (result == begin) { |
84 | return 0; |
85 | } else if (result == end) { |
86 | return size()-1; |
87 | } else { |
88 | Time dt1 = *result - t; |
89 | Time dt2 = t - *(result-1); |
90 | if (dt1 < dt2) |
91 | return result-begin; |
92 | else |
93 | return (result-begin)-1; |
94 | } |
95 | } |
96 | |
97 | } |
98 | |
99 | |