1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2005 StatPro Italia srl
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 <http://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#include "array.hpp"
21#include "utilities.hpp"
22#include <ql/math/array.hpp>
23#include <ql/utilities/dataformatters.hpp>
24
25using namespace QuantLib;
26using namespace boost::unit_test_framework;
27
28namespace array_test {
29 class FSquared {
30 public:
31 Real operator()(Real x) const { return x*x; }
32 };
33}
34
35void ArrayTest::testConstruction() {
36
37 BOOST_TEST_MESSAGE("Testing array construction...");
38
39 using namespace array_test;
40
41 // empty array
42 Array a1;
43 if (!a1.empty())
44 BOOST_ERROR("default-initialized array is not empty "
45 "(size = " << a1.size() << ")");
46
47 // sized array
48 Size size = 5;
49 Array a2(size);
50 if (a2.size() != size)
51 BOOST_ERROR("array not of the required size"
52 << "\n required: " << size
53 << "\n resulting: " << a2.size());
54
55 // sized array, constant values
56 Real value = 42.0;
57 Array a3(size, value);
58 if (a3.size() != size)
59 BOOST_ERROR("array not of the required size"
60 << "\n required: " << size
61 << "\n resulting: " << a3.size());
62 Size i;
63 for (i=0; i<size; ++i) {
64 if (a3[i] != value)
65 BOOST_ERROR(io::ordinal(i+1) << " element not with required value"
66 << "\n required: " << value
67 << "\n resulting: " << a3[i]);
68 }
69
70 // sized array, incremental values
71 Real increment = 3.0;
72 Array a4(size, value, increment);
73 if (a4.size() != size)
74 BOOST_ERROR("array not of the required size"
75 << "\n required: " << size
76 << "\n resulting: " << a4.size());
77 for (i=0; i<size; i++) {
78 if (a4[i] != value + i*increment)
79 BOOST_ERROR(io::ordinal(i+1) << " element not with required value"
80 << "\n required: " << value + i*increment
81 << "\n resulting: " << a4[i]);
82 }
83
84 // copy constructor
85 Array a5(a1); // NOLINT(performance-unnecessary-copy-initialization)
86 if (a5.size() != a1.size())
87 BOOST_ERROR("copy not of the same size as original"
88 << "\n original: " << a1.size()
89 << "\n copy: " << a5.size());
90
91 Array a6(a3);
92 if (a6.size() != a3.size())
93 BOOST_ERROR("copy not of the same size as original"
94 << "\n original: " << a3.size()
95 << "\n copy: " << a6.size());
96 for (i=0; i<a3.size(); i++) {
97 if (a6[i] != a3[i])
98 BOOST_ERROR(io::ordinal(i+1) << " element of copy "
99 "not with same value as original"
100 << "\n original: " << a3[i]
101 << "\n copy: " << a6[i]);
102 }
103
104 // transform
105 Array a10(5);
106 for (i=0; i < a10.size(); i++) {
107 a10[i] = static_cast<Real>(i);
108 }
109 FSquared f2;
110 std::transform(first: a10.begin(), last: a10.end(), result: a10.begin(), unary_op: FSquared());
111 for (i=0; i < a10.size(); i++) {
112 Real calculated = f2(static_cast<Real>(i));
113 if (std::fabs(x: a10[i] - calculated) >= 1e-5) {
114 BOOST_ERROR("Array transform test failed " << a10[i] << " "
115 << calculated);
116 }
117 }
118}
119
120void ArrayTest::testArrayFunctions() {
121
122 BOOST_TEST_MESSAGE("Testing array functions...");
123
124 auto get_array = []() {
125 Array a(5);
126 for (Size i=0; i < a.size(); ++i) {
127 a[i] = std::sin(x: Real(i))+1.1;
128 }
129 return a;
130 };
131
132 const Array a = get_array();
133
134 constexpr double exponential = -2.3;
135 const Array p_lvalue = Pow(v: a, alpha: exponential);
136 const Array e_lvalue = Exp(v: a);
137 const Array l_lvalue = Log(v: a);
138 const Array s_lvalue = Sqrt(v: a);
139 const Array a_lvalue = Abs(v: a);
140 const Array p_rvalue = Pow(v: get_array(), alpha: exponential);
141 const Array e_rvalue = Exp(v: get_array());
142 const Array l_rvalue = Log(v: get_array());
143 const Array s_rvalue = Sqrt(v: get_array());
144 const Array a_rvalue = Abs(v: get_array());
145
146 constexpr double tol = 10*QL_EPSILON;
147 for (Size i=0; i < a.size(); ++i) {
148 if (std::fabs(x: p_lvalue[i]-std::pow(x: a[i], y: exponential)) > tol) {
149 BOOST_FAIL("Array function test Pow failed (lvalue)");
150 }
151 if (std::fabs(x: p_rvalue[i]-std::pow(x: a[i], y: exponential)) > tol) {
152 BOOST_FAIL("Array function test Pow failed (lvalue)");
153 }
154 if (std::fabs(x: e_lvalue[i]-std::exp(x: a[i])) > tol) {
155 BOOST_FAIL("Array function test Exp failed (lvalue)");
156 }
157 if (std::fabs(x: e_rvalue[i]-std::exp(x: a[i])) > tol) {
158 BOOST_FAIL("Array function test Exp failed (rvalue)");
159 }
160 if (std::fabs(x: l_lvalue[i]-std::log(x: a[i])) > tol) {
161 BOOST_FAIL("Array function test Log failed (lvalue)");
162 }
163 if (std::fabs(x: l_rvalue[i]-std::log(x: a[i])) > tol) {
164 BOOST_FAIL("Array function test Log failed (rvalue)");
165 }
166 if (std::fabs(x: s_lvalue[i]-std::sqrt(x: a[i])) > tol) {
167 BOOST_FAIL("Array function test Sqrt failed (lvalue)");
168 }
169 if (std::fabs(x: s_rvalue[i]-std::sqrt(x: a[i])) > tol) {
170 BOOST_FAIL("Array function test Sqrt failed (rvalue)");
171 }
172 if (std::fabs(x: a_lvalue[i]-std::abs(x: a[i])) > tol) {
173 BOOST_FAIL("Array function test Abs failed (lvalue)");
174 }
175 if (std::fabs(x: a_rvalue[i]-std::abs(x: a[i])) > tol) {
176 BOOST_FAIL("Array function test Abs failed (rvalue)");
177 }
178 }
179}
180
181void ArrayTest::testArrayResize() {
182 BOOST_TEST_MESSAGE("Testing array resize...");
183
184 Array a(10,1.0,1.0);
185
186 for (Size i=0; i < 10; ++i)
187 QL_CHECK_CLOSE(a[i], Real(1+i), 10*QL_EPSILON);
188
189 a.resize(n: 5);
190 BOOST_CHECK(a.size() == 5);
191
192 for (Size i=0; i < 5; ++i)
193 QL_CHECK_CLOSE(a[i], Real(1+i), 10*QL_EPSILON);
194
195 a.resize(n: 15);
196 BOOST_CHECK(a.size() == 15);
197
198 for (Size i=0; i < 5; ++i)
199 QL_CHECK_CLOSE(a[i], Real(1+i), 10*QL_EPSILON);
200
201 const Array::const_iterator iter = a.begin();
202 a.resize(n: a.size());
203 BOOST_CHECK(iter == a.begin());
204
205 a.resize(n: 10);
206 BOOST_CHECK(a.size() == 10);
207 BOOST_CHECK(iter == a.begin());
208}
209
210#define QL_CHECK_CLOSE_ARRAY(actual, expected) \
211 BOOST_REQUIRE(actual.size() == expected.size()); \
212 for (auto i = 0u; i < actual.size(); i++) { \
213 QL_CHECK_CLOSE(actual[i], expected[i], 100 * QL_EPSILON); \
214 } \
215
216void ArrayTest::testArrayOperators() {
217 BOOST_TEST_MESSAGE("Testing array operators...");
218
219 auto get_array = []() {
220 return Array{1.1, 2.2, 3.3};
221 };
222
223 const auto a = get_array();
224
225 const auto positive = Array{1.1, 2.2, 3.3};
226 const auto lvalue_positive = +a;
227 const auto rvalue_positive = +get_array();
228
229 QL_CHECK_CLOSE_ARRAY(lvalue_positive, positive);
230 QL_CHECK_CLOSE_ARRAY(rvalue_positive, positive);
231
232 const auto negative = Array{-1.1, -2.2, -3.3};
233 const auto lvalue_negative = -a;
234 const auto rvalue_negative = -get_array();
235
236 QL_CHECK_CLOSE_ARRAY(lvalue_negative, negative);
237 QL_CHECK_CLOSE_ARRAY(rvalue_negative, negative);
238
239 const auto array_sum = Array{2.2, 4.4, 6.6};
240 const auto lvalue_lvalue_sum = a + a;
241 const auto lvalue_rvalue_sum = a + get_array();
242 const auto rvalue_lvalue_sum = get_array() + a;
243 const auto rvalue_rvalue_sum = get_array() + get_array();
244
245 QL_CHECK_CLOSE_ARRAY(lvalue_lvalue_sum, array_sum);
246 QL_CHECK_CLOSE_ARRAY(lvalue_rvalue_sum, array_sum);
247 QL_CHECK_CLOSE_ARRAY(rvalue_lvalue_sum, array_sum);
248 QL_CHECK_CLOSE_ARRAY(rvalue_rvalue_sum, array_sum);
249
250 const auto scalar_sum = Array{2.2, 3.3, 4.4};
251 const auto lvalue_real_sum = a + 1.1;
252 const auto rvalue_real_sum = get_array() + 1.1;
253 const auto real_lvalue_sum = 1.1 + a;
254 const auto real_rvalue_sum = 1.1 + get_array();
255
256 QL_CHECK_CLOSE_ARRAY(lvalue_real_sum, scalar_sum);
257 QL_CHECK_CLOSE_ARRAY(rvalue_real_sum, scalar_sum);
258 QL_CHECK_CLOSE_ARRAY(real_lvalue_sum, scalar_sum);
259 QL_CHECK_CLOSE_ARRAY(real_rvalue_sum, scalar_sum);
260
261 const auto array_difference = Array{0.0, 0.0, 0.0};
262 const auto lvalue_lvalue_difference = a - a; // NOLINT(misc-redundant-expression)
263 const auto lvalue_rvalue_difference = a - get_array();
264 const auto rvalue_lvalue_difference = get_array() - a;
265 const auto rvalue_rvalue_difference = get_array() - get_array();
266
267 QL_CHECK_CLOSE_ARRAY(lvalue_lvalue_difference, array_difference);
268 QL_CHECK_CLOSE_ARRAY(lvalue_rvalue_difference, array_difference);
269 QL_CHECK_CLOSE_ARRAY(rvalue_lvalue_difference, array_difference);
270 QL_CHECK_CLOSE_ARRAY(rvalue_rvalue_difference, array_difference);
271
272 const auto scalar_difference_1 = Array{0.0, +1.1, +2.2};
273 const auto scalar_difference_2 = Array{0.0, -1.1, -2.2};
274 const auto lvalue_real_difference = a - 1.1;
275 const auto rvalue_real_difference = get_array() - 1.1;
276 const auto real_lvalue_difference = 1.1 - a;
277 const auto real_rvalue_difference = 1.1 - get_array();
278
279 QL_CHECK_CLOSE_ARRAY(lvalue_real_difference, scalar_difference_1);
280 QL_CHECK_CLOSE_ARRAY(rvalue_real_difference, scalar_difference_1);
281 QL_CHECK_CLOSE_ARRAY(real_lvalue_difference, scalar_difference_2);
282 QL_CHECK_CLOSE_ARRAY(real_rvalue_difference, scalar_difference_2);
283
284 const auto array_product = Array{1.1 * 1.1, 2.2 * 2.2, 3.3 * 3.3};
285 const auto lvalue_lvalue_product = a * a;
286 const auto lvalue_rvalue_product = a * get_array();
287 const auto rvalue_lvalue_product = get_array() * a;
288 const auto rvalue_rvalue_product = get_array() * get_array();
289
290 QL_CHECK_CLOSE_ARRAY(lvalue_lvalue_product, array_product);
291 QL_CHECK_CLOSE_ARRAY(lvalue_rvalue_product, array_product);
292 QL_CHECK_CLOSE_ARRAY(rvalue_lvalue_product, array_product);
293 QL_CHECK_CLOSE_ARRAY(rvalue_rvalue_product, array_product);
294
295 const auto scalar_product = Array{1.1 * 1.1, 2.2 * 1.1, 3.3 * 1.1};
296 const auto lvalue_real_product = a * 1.1;
297 const auto rvalue_real_product = get_array() * 1.1;
298 const auto real_lvalue_product = 1.1 * a;
299 const auto real_rvalue_product = 1.1 * get_array();
300
301 QL_CHECK_CLOSE_ARRAY(lvalue_real_product, scalar_product);
302 QL_CHECK_CLOSE_ARRAY(rvalue_real_product, scalar_product);
303 QL_CHECK_CLOSE_ARRAY(real_lvalue_product, scalar_product);
304 QL_CHECK_CLOSE_ARRAY(real_rvalue_product, scalar_product);
305
306 const auto array_quotient = Array{1.0, 1.0, 1.0};
307 const auto lvalue_lvalue_quotient = a / a; // NOLINT(misc-redundant-expression)
308 const auto lvalue_rvalue_quotient = a / get_array();
309 const auto rvalue_lvalue_quotient = get_array() / a;
310 const auto rvalue_rvalue_quotient = get_array() / get_array();
311
312 QL_CHECK_CLOSE_ARRAY(lvalue_lvalue_quotient, array_quotient);
313 QL_CHECK_CLOSE_ARRAY(lvalue_rvalue_quotient, array_quotient);
314 QL_CHECK_CLOSE_ARRAY(rvalue_lvalue_quotient, array_quotient);
315 QL_CHECK_CLOSE_ARRAY(rvalue_rvalue_quotient, array_quotient);
316
317 const auto scalar_quotient_1 = Array{1.1 / 1.1, 2.2 / 1.1, 3.3 / 1.1};
318 const auto scalar_quotient_2 = Array{1.1 / 1.1, 1.1 / 2.2, 1.1 / 3.3};
319 const auto lvalue_real_quotient = a / 1.1;
320 const auto rvalue_real_quotient = get_array() / 1.1;
321 const auto real_lvalue_quotient = 1.1 / a;
322 const auto real_rvalue_quotient = 1.1 / get_array();
323
324 QL_CHECK_CLOSE_ARRAY(lvalue_real_quotient, scalar_quotient_1);
325 QL_CHECK_CLOSE_ARRAY(rvalue_real_quotient, scalar_quotient_1);
326 QL_CHECK_CLOSE_ARRAY(real_lvalue_quotient, scalar_quotient_2);
327 QL_CHECK_CLOSE_ARRAY(real_rvalue_quotient, scalar_quotient_2);
328}
329
330test_suite* ArrayTest::suite() {
331 auto* suite = BOOST_TEST_SUITE("array tests");
332 suite->add(QUANTLIB_TEST_CASE(&ArrayTest::testConstruction));
333 suite->add(QUANTLIB_TEST_CASE(&ArrayTest::testArrayFunctions));
334 suite->add(QUANTLIB_TEST_CASE(&ArrayTest::testArrayResize));
335 suite->add(QUANTLIB_TEST_CASE(&ArrayTest::testArrayOperators));
336 return suite;
337}
338
339

source code of quantlib/test-suite/array.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.