QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
unitofmeasureconversionmanager.cpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 J. Erik Radmall
5 Copyright (C) 2009 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/experimental/commodities/unitofmeasureconversionmanager.hpp>
22#include <ql/experimental/commodities/petroleumunitsofmeasure.hpp>
23#include <ql/errors.hpp>
24#include <algorithm>
25
26using namespace std;
27
28namespace QuantLib {
29
30 namespace {
31
32 bool matches(const UnitOfMeasureConversion& c1,
33 const UnitOfMeasureConversion& c2) {
34 return c1.commodityType() == c2.commodityType() &&
35 ((c1.source() == c2.source() && c1.target() == c2.target())
36 || (c1.source() == c2.target() && c1.target() == c2.source()));
37 }
38
39 bool matches(const UnitOfMeasureConversion& c,
40 const CommodityType& commodityType,
41 const UnitOfMeasure& source,
42 const UnitOfMeasure& target) {
43 return c.commodityType() == commodityType &&
44 ((c.source() == source && c.target() == target)
45 || (c.source() == target && c.target() == source));
46 }
47
48 bool matches(const UnitOfMeasureConversion& c,
49 const CommodityType& commodityType,
50 const UnitOfMeasure& source) {
51 return c.commodityType() == commodityType &&
52 (c.source() == source || c.target() == source);
53 }
54
55 }
56
59 }
60
62 // not fast, but hopefully we won't have a lot of entries.
63 for (auto i = data_.begin(); i != data_.end(); ++i) {
64 if (matches(*i, c)) {
65 data_.erase(i);
66 break;
67 }
68 }
69
70 data_.push_back(c);
71 }
72
74 const CommodityType& commodityType,
75 const UnitOfMeasure& source,
76 const UnitOfMeasure& target,
79 return directLookup(commodityType,source,target);
80 } else if (!source.triangulationUnitOfMeasure().empty()) {
81 const UnitOfMeasure& link = source.triangulationUnitOfMeasure();
82 if (link == target)
83 return directLookup(commodityType,source,link);
84 else
86 directLookup(commodityType,source,link),
87 lookup(commodityType,link,target));
88 } else if (!target.triangulationUnitOfMeasure().empty()) {
89 const UnitOfMeasure& link = target.triangulationUnitOfMeasure();
90 if (source == link)
91 return directLookup(commodityType,link,target);
92 else
94 lookup(commodityType,source,link),
95 directLookup(commodityType,link,target));
96 } else {
97 return smartLookup(commodityType,source,target);
98 }
99 }
100
102 data_.clear();
104 }
105
110 1000));
114 42));
118 1000 * 42));
122 3.78541));
126 158.987));
130 6.28981));
134 6.28981));
135 }
136
138 const CommodityType& commodityType,
139 const UnitOfMeasure& source,
140 const UnitOfMeasure& target) const {
141
142 for (const auto& i : data_) {
143 if (matches(i, commodityType, source, target)) {
144 return i;
145 }
146 }
147
148 // Here, the code used to look for conversions with null
149 // commodity type as a fall-back. However, this would only
150 // affect direct lookups and not other matches being tried in
151 // the smart-lookup loop. To implement the complete fall-back
152 // strategy, we should either duplicate the loop (as we would
153 // duplicate it here---smelly) or change the 'matches'
154 // functions so that a null commodity type matches. However,
155 // in the second case we would also have to take care that
156 // conversions with a null type be at the end of the list so
157 // that they don't supersede specific types. We'll have to
158 // think a bit about this, so no fall-back for the time being.
159
160 QL_FAIL("no direct conversion available from "
161 << commodityType.code() << " " << source.code()
162 << " to " << target.code());
163 }
164
166 const CommodityType& commodityType,
167 const UnitOfMeasure& source,
168 const UnitOfMeasure& target,
169 list<string> forbidden) const {
170
171 try {
172 return directLookup(commodityType,source,target);
173 } catch (Error&) {
174 ; // no direct conversion available; turn to smart lookup.
175 }
176
177 // The source unit is forbidden to subsequent lookups in order
178 // to avoid cycles.
179 forbidden.push_back(source.code());
180
181 for (const auto& i : data_) {
182 // we look for conversion data which involve our source unit...
183 if (matches(i, commodityType, source)) {
184 const UnitOfMeasure& other = source == i.source() ? i.target() : i.source();
185 if (find(forbidden.begin(),forbidden.end(),
186 other.code()) == forbidden.end()) {
187 // if we can get to the target from here...
188 try {
190 smartLookup(commodityType,other,target);
191 // ..we're done.
192 return UnitOfMeasureConversion::chain(i, tail);
193 } catch (Error&) {
194 // otherwise, we just discard this conversion.
195 ;
196 }
197 }
198 }
199 }
200
201 // if the loop completed, we have no way to return the
202 // requested conversion.
203 QL_FAIL("no conversion available for "
204 << commodityType.code() << " from "
205 << source.code() << " to " << target.code());
206 }
207
208}
209
const std::string & code() const
commodity code, e.g, "HO"
Base error class.
Definition: errors.hpp:39
static UnitOfMeasureConversion chain(const UnitOfMeasureConversion &r1, const UnitOfMeasureConversion &r2)
chain two conversion factors
UnitOfMeasureConversion lookup(const CommodityType &commodityType, const UnitOfMeasure &, const UnitOfMeasure &, UnitOfMeasureConversion::Type type=UnitOfMeasureConversion::Derived) const
UnitOfMeasureConversion smartLookup(const CommodityType &commodityType, const UnitOfMeasure &source, const UnitOfMeasure &target, std::list< std::string > forbidden=std::list< std::string >()) const
UnitOfMeasureConversion directLookup(const CommodityType &commodityType, const UnitOfMeasure &source, const UnitOfMeasure &target) const
Unit of measure specification
const UnitOfMeasure & triangulationUnitOfMeasure() const
unit used for triangulation when required
const std::string & code() const
code, e.g, "BBL", "MT"
bool empty() const
is this a usable instance?
Definition: any.hpp:35
STL namespace.