19#include <boost/timer/timer.hpp>
21#include <qle/math/compiledformula.hpp>
22#include <oret/toplevelfixture.hpp>
26BOOST_FIXTURE_TEST_SUITE(OREDataTestSuite, ore::test::TopLevelFixture)
28BOOST_AUTO_TEST_SUITE(FormulaParserTest)
31 BOOST_TEST_MESSAGE(
"Testing Formula Parser with double...");
36 double x = 42.0, y = -2.3;
37 auto variables = [&x, &y](
const std::string& s) {
43 QL_FAIL(
"variable " << s <<
" not known.");
47 BOOST_CHECK_CLOSE(parseFormula<double>(
"3"), 3.0, tol);
49 BOOST_CHECK_THROW(parseFormula<double>(
"x"), QuantLib::Error);
50 BOOST_CHECK_THROW(parseFormula<double>(
"{x}"), QuantLib::Error);
51 BOOST_CHECK_THROW(parseFormula<double>(
"{z}", variables), QuantLib::Error);
53 BOOST_CHECK_CLOSE(parseFormula<double>(
"{x}", variables), 42.0, tol);
55 BOOST_CHECK_CLOSE(parseFormula<double>(
"3+4"), 7.0, tol);
56 BOOST_CHECK_CLOSE(parseFormula<double>(
"3*4"), 12.0, tol);
57 BOOST_CHECK_CLOSE(parseFormula<double>(
"3/4"), 0.75, tol);
58 BOOST_CHECK_CLOSE(parseFormula<double>(
"3-4"), -1.0, tol);
59 BOOST_CHECK_CLOSE(parseFormula<double>(
"-4"), -4.0, tol);
60 BOOST_CHECK_CLOSE(parseFormula<double>(
"3+(-4)"), -1.0, tol);
61 BOOST_CHECK_CLOSE(parseFormula<double>(
"-{x}", variables), -x, tol);
63 BOOST_CHECK_CLOSE(parseFormula<double>(
"abs({x})", variables), std::abs(x), tol);
64 BOOST_CHECK_CLOSE(parseFormula<double>(
"abs({y})", variables), std::abs(y), tol);
66 BOOST_CHECK_SMALL(parseFormula<double>(
"gtZero({y})", variables), tol);
67 BOOST_CHECK_SMALL(parseFormula<double>(
"geqZero({y})", variables), tol);
68 BOOST_CHECK_CLOSE(parseFormula<double>(
"gtZero({x})", variables), 1.0, tol);
69 BOOST_CHECK_CLOSE(parseFormula<double>(
"geqZero({x})", variables), 1.0, tol);
70 BOOST_CHECK_SMALL(parseFormula<double>(
"gtZero(0.0)", variables), tol);
71 BOOST_CHECK_CLOSE(parseFormula<double>(
"geqZero(0.0)", variables), 1.0, tol);
73 BOOST_CHECK_CLOSE(parseFormula<double>(
"exp({y})", variables), std::exp(y), tol);
74 BOOST_CHECK_CLOSE(parseFormula<double>(
"log({x})", variables), std::log(x), tol);
76 BOOST_CHECK_CLOSE(parseFormula<double>(
"max({x},{y})", variables), std::max(x, y), tol);
77 BOOST_CHECK_CLOSE(parseFormula<double>(
"min({x},{y})", variables), std::min(x, y), tol);
78 BOOST_CHECK_CLOSE(parseFormula<double>(
"pow({x},{y})", variables), std::pow(x, y), tol);
80 BOOST_CHECK_CLOSE(parseFormula<double>(
"max((2.3*({x}-{y}))-4.3,0.0)", variables),
81 std::max(2.3 * (x - y) - 4.3, 0.0), tol);
84 BOOST_CHECK_CLOSE(parseFormula<double>(
"1+2-3-4+5"), 1.0, tol);
85 BOOST_CHECK_CLOSE(parseFormula<double>(
"1+2-3*2*(-4)-4*2*3"), 3.0, tol);
86 BOOST_CHECK_CLOSE(parseFormula<double>(
"1+(2-3)*5+2*3"), 2.0, tol);
87 BOOST_CHECK_CLOSE(parseFormula<double>(
"(1+(2-3)*(5+2))*3"), -18.0, tol);
91 boost::timer::cpu_timer timer;
92 for (Size i = 0; i < 100000; ++i) {
93 parseFormula<double>(
"max((2.3*({x}-{y}))-4.3,0.0)", variables);
96 BOOST_TEST_MESSAGE(
"timing full parsing (100k evaluations) = " << timer.format(boost::timer::default_places,
"%w")
101 BOOST_TEST_MESSAGE(
"Testing Formula Parser with CompiledFormula...");
105 double x = 42.0, y = -2.3;
106 std::vector<std::string> variables;
108 QuantExt::CompiledFormula f =
parseFormula(
"((2*{x})+3)/{y}", variables);
109 BOOST_REQUIRE(variables.size() == 2);
110 BOOST_CHECK_EQUAL(variables[0],
"x");
111 BOOST_CHECK_EQUAL(variables[1],
"y");
112 BOOST_CHECK_CLOSE(f({x, y}), (2.0 * x + 3.0) / y, tol);
115 BOOST_REQUIRE(variables.size() == 2);
116 BOOST_CHECK_EQUAL(variables[0],
"x");
117 BOOST_CHECK_EQUAL(variables[1],
"y");
118 BOOST_CHECK_CLOSE(f({x, y}), x - y, tol);
121 BOOST_REQUIRE(variables.size() == 1);
122 BOOST_CHECK_EQUAL(variables[0],
"y");
123 BOOST_CHECK_CLOSE(f({y}), -y, tol);
126 BOOST_REQUIRE(variables.size() == 2);
127 BOOST_CHECK_EQUAL(variables[0],
"x");
128 BOOST_CHECK_EQUAL(variables[1],
"y");
129 BOOST_CHECK_CLOSE(f({x, y}), x / y, tol);
132 BOOST_REQUIRE(variables.size() == 2);
133 BOOST_CHECK_EQUAL(variables[0],
"x");
134 BOOST_CHECK_EQUAL(variables[1],
"y");
135 BOOST_CHECK_CLOSE(f({x, y}), std::max(x, y), tol);
138 BOOST_REQUIRE(variables.size() == 2);
139 BOOST_CHECK_EQUAL(variables[0],
"x");
140 BOOST_CHECK_EQUAL(variables[1],
"y");
141 BOOST_CHECK_CLOSE(f({x, y}), std::min(x, y), tol);
144 BOOST_REQUIRE(variables.size() == 2);
145 BOOST_CHECK_EQUAL(variables[0],
"x");
146 BOOST_CHECK_EQUAL(variables[1],
"y");
147 BOOST_CHECK_CLOSE(f({x, y}), std::pow(x, y), tol);
150 BOOST_REQUIRE(variables.size() == 1);
151 BOOST_CHECK_EQUAL(variables[0],
"y");
152 BOOST_CHECK_CLOSE(f({y}), std::abs(y), tol);
155 BOOST_REQUIRE(variables.size() == 1);
156 BOOST_CHECK_EQUAL(variables[0],
"x");
157 BOOST_CHECK_CLOSE(f({x}), 1.0, tol);
158 BOOST_CHECK_SMALL(f({y}), tol);
159 BOOST_CHECK_SMALL(f({0.0}), tol);
162 BOOST_REQUIRE(variables.size() == 1);
163 BOOST_CHECK_EQUAL(variables[0],
"x");
164 BOOST_CHECK_CLOSE(f({x}), 1.0, tol);
165 BOOST_CHECK_SMALL(f({y}), tol);
166 BOOST_CHECK_CLOSE(f({0.0}), 1.0, tol);
169 BOOST_REQUIRE(variables.size() == 1);
170 BOOST_CHECK_EQUAL(variables[0],
"y");
171 BOOST_CHECK_CLOSE(f({y}), std::exp(y), tol);
174 BOOST_REQUIRE(variables.size() == 1);
175 BOOST_CHECK_EQUAL(variables[0],
"x");
176 BOOST_CHECK_CLOSE(f({x}), std::log(x), tol);
180 f =
parseFormula(
"max((2.3*({x}-{y}))-4.3,0.0)", variables);
181 boost::timer::cpu_timer timer;
183 std::vector<Real> v(2);
184 for (Size i = 0; i < 100000; ++i) {
185 v[0] =
static_cast<double>(i) /
static_cast<double>(10000);
186 v[1] =
static_cast<double>(100000 - i) /
static_cast<double>(10000);
189 BOOST_TEST_MESSAGE(
"dummy = " << dummy);
191 BOOST_TEST_MESSAGE(
"timing precompiled formula (100k evalulations) = "
192 << timer.format(boost::timer::default_places,
"%w") <<
" secs.");
196 for (Size i = 0; i < 100000; ++i) {
197 Real x =
static_cast<double>(i) /
static_cast<double>(10000);
198 Real y =
static_cast<double>(100000 - i) /
static_cast<double>(10000);
199 dummy += std::max((2.3 * (x - y)) - 4.3, 0.0);
201 BOOST_TEST_MESSAGE(
"dummy = " << dummy);
203 BOOST_TEST_MESSAGE(
"timing native (100k evaluations) = " << timer.format(boost::timer::default_places,
"%w")
230BOOST_AUTO_TEST_SUITE_END()
232BOOST_AUTO_TEST_SUITE_END()
QuantExt::CompiledFormula parseFormula(const std::string &text, std::vector< std::string > &variables)