Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/math/array.hpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5
 Copyright (C) 2003, 2004, 2005, 2006, 2009 StatPro Italia srl
6
 Copyright (C) 2004 Ferdinando Ametrano
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
 <http://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
/*! \file array.hpp
23
    \brief 1-D array used in linear algebra.
24
*/
25
26
#ifndef quantlib_array_hpp
27
#define quantlib_array_hpp
28
29
#include <ql/types.hpp>
30
#include <ql/errors.hpp>
31
#include <ql/utilities/null.hpp>
32
#include <iterator>
33
#include <functional>
34
#include <algorithm>
35
#include <numeric>
36
#include <vector>
37
#include <initializer_list>
38
#include <iomanip>
39
#include <memory>
40
#include <type_traits>
41
42
namespace QuantLib {
43
44
    //! 1-D array used in linear algebra.
45
    /*! This class implements the concept of vector as used in linear
46
        algebra.
47
        As such, it is <b>not</b> meant to be used as a container -
48
        <tt>std::vector</tt> should be used instead.
49
50
        \test construction of arrays is checked in a number of cases
51
    */
52
    class Array {
53
      public:
54
        //! \name Constructors, destructor, and assignment
55
        //@{
56
        //! creates the array with size 0
57
0
        Array() : Array(static_cast<Size>(0)) {}
58
        //! creates the array with the given dimension
59
        explicit Array(Size size);
60
        //! creates the array and fills it with <tt>value</tt>
61
        Array(Size size, Real value);
62
        /*! \brief creates the array and fills it according to
63
            \f$ a_{0} = value, a_{i}=a_{i-1}+increment \f$
64
        */
65
        Array(Size size, Real value, Real increment);
66
        Array(const Array&);
67
        Array(Array&&) noexcept;
68
        Array(std::initializer_list<Real>);
69
        template <typename T, typename = std::enable_if_t<std::is_convertible_v<T, Real>>>
70
        Array(std::initializer_list<T> init);
71
        //! creates the array from an iterable sequence
72
        template <class ForwardIterator>
73
        Array(ForwardIterator begin, ForwardIterator end);
74
0
        ~Array() = default;
75
76
        Array& operator=(const Array&);
77
        Array& operator=(Array&&) noexcept;
78
79
        bool operator==(const Array&) const;
80
        bool operator!=(const Array&) const;
81
        //@}
82
        /*! \name Vector algebra
83
84
            <tt>v += x</tt> and similar operation involving a scalar value
85
            are shortcuts for \f$ \forall i : v_i = v_i + x \f$
86
87
            <tt>v *= w</tt> and similar operation involving two vectors are
88
            shortcuts for \f$ \forall i : v_i = v_i \times w_i \f$
89
90
            \pre all arrays involved in an algebraic expression must have
91
            the same size.
92
        */
93
        //@{
94
        const Array& operator+=(const Array&);
95
        const Array& operator+=(Real);
96
        const Array& operator-=(const Array&);
97
        const Array& operator-=(Real);
98
        const Array& operator*=(const Array&);
99
        const Array& operator*=(Real);
100
        const Array& operator/=(const Array&);
101
        const Array& operator/=(Real);
102
        //@}
103
        //! \name Element access
104
        //@{
105
        //! read-only
106
        Real operator[](Size) const;
107
        Real at(Size) const;
108
        Real front() const;
109
        Real back() const;
110
        //! read-write
111
        Real& operator[](Size);
112
        Real& at(Size);
113
        Real& front();
114
        Real& back();
115
        //@}
116
        //! \name Inspectors
117
        //@{
118
        //! dimension of the array
119
        Size size() const;
120
        //! whether the array is empty
121
        bool empty() const;
122
        //@}
123
        typedef Size size_type;
124
        typedef Real value_type;
125
        typedef Real* iterator;
126
        typedef const Real* const_iterator;
127
        typedef std::reverse_iterator<iterator> reverse_iterator;
128
        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
129
        //! \name Iterator access
130
        //@{
131
        const_iterator begin() const;
132
        iterator begin();
133
        const_iterator end() const;
134
        iterator end();
135
        const_reverse_iterator rbegin() const;
136
        reverse_iterator rbegin();
137
        const_reverse_iterator rend() const;
138
        reverse_iterator rend();
139
        //@}
140
        //! \name Utilities
141
        //@{
142
        void resize(Size n);
143
        void swap(Array&) noexcept;
144
        //@}
145
146
      private:
147
        std::unique_ptr<Real[]> data_;
148
        Size n_;
149
    };
150
151
152
    /*! \relates Array */
153
    Real DotProduct(const Array&, const Array&);
154
155
    /*! \relates Array */
156
    Real Norm2(const Array&);
157
158
    // unary operators
159
    /*! \relates Array */
160
    Array operator+(const Array& v);
161
    /*! \relates Array */
162
    Array operator+(Array&& v);
163
    /*! \relates Array */
164
    Array operator-(const Array& v);
165
    /*! \relates Array */
166
    Array operator-(Array&& v);
167
168
    // binary operators
169
    /*! \relates Array */
170
    Array operator+(const Array&, const Array&);
171
    /*! \relates Array */
172
    Array operator+(const Array&, Array&&);
173
    /*! \relates Array */
174
    Array operator+(Array&&, const Array&);
175
    /*! \relates Array */
176
    Array operator+(Array&&, Array&&);
177
    /*! \relates Array */
178
    Array operator+(const Array&, Real);
179
    /*! \relates Array */
180
    Array operator+(Array&&, Real);
181
    /*! \relates Array */
182
    Array operator+(Real, const Array&);
183
    /*! \relates Array */
184
    Array operator+(Real, Array&&);
185
    /*! \relates Array */
186
    Array operator-(const Array&, const Array&);
187
    /*! \relates Array */
188
    Array operator-(const Array&, Array&&);
189
    /*! \relates Array */
190
    Array operator-(Array&&, const Array&);
191
    /*! \relates Array */
192
    Array operator-(Array&&, Array&&);
193
    /*! \relates Array */
194
    Array operator-(const Array&, Real);
195
    /*! \relates Array */
196
    Array operator-(Real, const Array&);
197
    /*! \relates Array */
198
    Array operator-(Array&&, Real);
199
    /*! \relates Array */
200
    Array operator-(Real, Array&&);
201
    /*! \relates Array */
202
    Array operator*(const Array&, const Array&);
203
    /*! \relates Array */
204
    Array operator*(const Array&, Array&&);
205
    /*! \relates Array */
206
    Array operator*(Array&&, const Array&);
207
    /*! \relates Array */
208
    Array operator*(Array&&, Array&&);
209
    /*! \relates Array */
210
    Array operator*(const Array&, Real);
211
    /*! \relates Array */
212
    Array operator*(Real, const Array&);
213
    /*! \relates Array */
214
    Array operator*(Array&&, Real);
215
    /*! \relates Array */
216
    Array operator*(Real, Array&&);
217
    /*! \relates Array */
218
    Array operator/(const Array&, const Array&);
219
    /*! \relates Array */
220
    Array operator/(const Array&, Array&&);
221
    /*! \relates Array */
222
    Array operator/(Array&&, const Array&);
223
    /*! \relates Array */
224
    Array operator/(Array&&, Array&&);
225
    /*! \relates Array */
226
    Array operator/(const Array&, Real);
227
    /*! \relates Array */
228
    Array operator/(Real, const Array&);
229
    /*! \relates Array */
230
    Array operator/(Array&&, Real);
231
    /*! \relates Array */
232
    Array operator/(Real, Array&&);
233
234
    // math functions
235
    /*! \relates Array */
236
    Array Abs(const Array&);
237
    /*! \relates Array */
238
    Array Abs(Array&&);
239
    /*! \relates Array */
240
    Array Sqrt(const Array&);
241
    /*! \relates Array */
242
    Array Sqrt(Array&&);
243
    /*! \relates Array */
244
    Array Log(const Array&);
245
    /*! \relates Array */
246
    Array Log(Array&&);
247
    /*! \relates Array */
248
    Array Exp(const Array&);
249
    /*! \relates Array */
250
    Array Exp(Array&&);
251
    /*! \relates Array */
252
    Array Pow(const Array&, Real);
253
    /*! \relates Array */
254
    Array Pow(Array&&, Real);
255
256
    // utilities
257
    /*! \relates Array */
258
    void swap(Array&, Array&) noexcept;
259
260
    // format
261
    /*! \relates Array */
262
    std::ostream& operator<<(std::ostream&, const Array&);
263
264
265
    // inline definitions
266
267
    inline Array::Array(Size size)
268
0
    : data_(size != 0U ? new Real[size] : (Real*)nullptr), n_(size) {}
269
270
    inline Array::Array(Size size, Real value)
271
0
    : data_(size != 0U ? new Real[size] : (Real*)nullptr), n_(size) {
272
0
        std::fill(begin(),end(),value);
273
0
    }
274
275
    inline Array::Array(Size size, Real value, Real increment)
276
0
    : data_(size != 0U ? new Real[size] : (Real*)nullptr), n_(size) {
277
0
        for (iterator i=begin(); i!=end(); ++i, value+=increment)
278
0
            *i = value;
279
0
    }
280
281
    inline Array::Array(const Array& from)
282
0
    : data_(from.n_ != 0U ? new Real[from.n_] : (Real*)nullptr), n_(from.n_) {
283
0
        if (data_)
284
0
            std::copy(from.begin(),from.end(),begin());
285
0
    }
286
287
    inline Array::Array(Array&& from) noexcept
288
0
    : data_((Real*)nullptr), n_(0) {
289
0
        swap(from);
290
0
    }
291
292
    namespace detail {
293
294
        template <class I>
295
        inline void _fill_array_(Array& a,
296
                                 std::unique_ptr<Real[]>& data_,
297
                                 Size& n_,
298
                                 I begin, I end,
299
                                 const std::true_type&) {
300
            // we got redirected here from a call like Array(3, 4)
301
            // because it matched the constructor below exactly with
302
            // ForwardIterator = int.  What we wanted was fill an
303
            // Array with a given value, which we do here.
304
            Size n = begin;
305
            Real value = end;
306
            data_.reset(n ? new Real[n] : (Real*)nullptr);
307
            n_ = n;
308
            std::fill(a.begin(),a.end(),value);
309
        }
310
311
        template <class I>
312
        inline void _fill_array_(Array& a,
313
                                 std::unique_ptr<Real[]>& data_,
314
                                 Size& n_,
315
                                 const I& begin, const I& end,
316
0
                                 const std::false_type&) {
317
            // true iterators
318
0
            Size n = std::distance(begin, end);
319
0
            data_.reset(n ? new Real[n] : (Real*)nullptr);
320
0
            n_ = n;
321
            #if defined(QL_PATCH_MSVC) && defined(QL_DEBUG)
322
            if (n_)
323
            #endif
324
0
            std::copy(begin, end, a.begin());
325
0
        }
Unexecuted instantiation: void QuantLib::detail::_fill_array_<double const*>(QuantLib::Array&, std::__1::unique_ptr<double [], std::__1::default_delete<double []> >&, unsigned long&, double const* const&, double const* const&, std::__1::integral_constant<bool, false> const&)
Unexecuted instantiation: void QuantLib::detail::_fill_array_<std::__1::__wrap_iter<double const*> >(QuantLib::Array&, std::__1::unique_ptr<double [], std::__1::default_delete<double []> >&, unsigned long&, std::__1::__wrap_iter<double const*> const&, std::__1::__wrap_iter<double const*> const&, std::__1::integral_constant<bool, false> const&)
Unexecuted instantiation: void QuantLib::detail::_fill_array_<std::__1::__tree_const_iterator<double, std::__1::__tree_node<double, void*>*, long> >(QuantLib::Array&, std::__1::unique_ptr<double [], std::__1::default_delete<double []> >&, unsigned long&, std::__1::__tree_const_iterator<double, std::__1::__tree_node<double, void*>*, long> const&, std::__1::__tree_const_iterator<double, std::__1::__tree_node<double, void*>*, long> const&, std::__1::integral_constant<bool, false> const&)
Unexecuted instantiation: void QuantLib::detail::_fill_array_<QuantLib::step_iterator<double const*> >(QuantLib::Array&, std::__1::unique_ptr<double [], std::__1::default_delete<double []> >&, unsigned long&, QuantLib::step_iterator<double const*> const&, QuantLib::step_iterator<double const*> const&, std::__1::integral_constant<bool, false> const&)
326
327
    }
328
329
0
    inline Array::Array(std::initializer_list<Real> init) {
330
0
        detail::_fill_array_(*this, data_, n_, init.begin(), init.end(),
331
0
                             std::false_type());
332
0
    }
333
334
    template <class ForwardIterator>
335
0
    inline Array::Array(ForwardIterator begin, ForwardIterator end) {   // NOLINT(performance-unnecessary-value-param)
336
        // Unfortunately, calls such as Array(3, 4) match this constructor.
337
        // We have to detect integral types and dispatch.
338
0
        detail::_fill_array_(*this, data_, n_, begin, end,
339
0
                             std::is_integral<ForwardIterator>());
340
0
    }
Unexecuted instantiation: QuantLib::Array::Array<std::__1::__wrap_iter<double const*> >(std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<double const*>)
Unexecuted instantiation: QuantLib::Array::Array<std::__1::__tree_const_iterator<double, std::__1::__tree_node<double, void*>*, long> >(std::__1::__tree_const_iterator<double, std::__1::__tree_node<double, void*>*, long>, std::__1::__tree_const_iterator<double, std::__1::__tree_node<double, void*>*, long>)
Unexecuted instantiation: QuantLib::Array::Array<double const*>(double const*, double const*)
Unexecuted instantiation: QuantLib::Array::Array<QuantLib::step_iterator<double const*> >(QuantLib::step_iterator<double const*>, QuantLib::step_iterator<double const*>)
341
342
    template <typename T, typename>
343
    Array::Array(std::initializer_list<T> init) {
344
        detail::_fill_array_(*this, data_, n_, init.begin(), init.end(), std::false_type());
345
    }
346
347
0
    inline Array& Array::operator=(const Array& from) {
348
0
        // strong guarantee
349
0
        Array temp(from);
350
0
        swap(temp);
351
0
        return *this;
352
0
    }
353
354
0
    inline Array& Array::operator=(Array&& from) noexcept {
355
0
        swap(from);
356
0
        return *this;
357
0
    }
358
359
0
    inline bool Array::operator==(const Array& to) const {
360
0
        return (n_ == to.n_) && std::equal(begin(), end(), to.begin());
361
0
    }
362
363
0
    inline bool Array::operator!=(const Array& to) const {
364
0
        return !(this->operator==(to));
365
0
    }
366
367
0
    inline const Array& Array::operator+=(const Array& v) {
368
0
        QL_REQUIRE(n_ == v.n_,
369
0
                   "arrays with different sizes (" << n_ << ", "
370
0
                   << v.n_ << ") cannot be added");
371
0
        std::transform(begin(),end(),v.begin(),begin(), std::plus<>());
372
0
        return *this;
373
0
    }
Unexecuted instantiation: QuantLib::Array::operator+=(QuantLib::Array const&)
Unexecuted instantiation: QuantLib::Array::operator+=(QuantLib::Array const&)
374
375
376
0
    inline const Array& Array::operator+=(Real x) {
377
0
        std::transform(begin(), end(), begin(), [=](Real y) -> Real { return y + x; });
378
0
        return *this;
379
0
    }
380
381
0
    inline const Array& Array::operator-=(const Array& v) {
382
0
        QL_REQUIRE(n_ == v.n_,
383
0
                   "arrays with different sizes (" << n_ << ", "
384
0
                   << v.n_ << ") cannot be subtracted");
385
0
        std::transform(begin(), end(), v.begin(), begin(), std::minus<>());
386
0
        return *this;
387
0
    }
Unexecuted instantiation: QuantLib::Array::operator-=(QuantLib::Array const&)
Unexecuted instantiation: QuantLib::Array::operator-=(QuantLib::Array const&)
388
389
0
    inline const Array& Array::operator-=(Real x) {
390
0
        std::transform(begin(),end(),begin(), [=](Real y) -> Real { return y - x; });
391
0
        return *this;
392
0
    }
393
394
0
    inline const Array& Array::operator*=(const Array& v) {
395
0
        QL_REQUIRE(n_ == v.n_,
396
0
                   "arrays with different sizes (" << n_ << ", "
397
0
                   << v.n_ << ") cannot be multiplied");
398
0
        std::transform(begin(), end(), v.begin(), begin(), std::multiplies<>());
399
0
        return *this;
400
0
    }
401
402
0
    inline const Array& Array::operator*=(Real x) {
403
0
        std::transform(begin(), end(), begin(), [=](Real y) -> Real { return y * x; });
404
0
        return *this;
405
0
    }
406
407
0
    inline const Array& Array::operator/=(const Array& v) {
408
0
        QL_REQUIRE(n_ == v.n_,
409
0
                   "arrays with different sizes (" << n_ << ", "
410
0
                   << v.n_ << ") cannot be divided");
411
0
        std::transform(begin(), end(), v.begin(), begin(), std::divides<>());
412
0
        return *this;
413
0
    }
414
415
0
    inline const Array& Array::operator/=(Real x) {
416
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
417
0
        QL_REQUIRE(x != 0.0, "division by zero");
418
0
        #endif
419
0
        std::transform(begin(), end(), begin(), [=](Real y) -> Real { return y / x; });
420
0
        return *this;
421
0
    }
422
423
0
    inline Real Array::operator[](Size i) const {
424
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
425
0
        QL_REQUIRE(i<n_,
426
0
                   "index (" << i << ") must be less than " << n_ <<
427
0
                   ": array access out of range");
428
0
        #endif
429
0
        return data_.get()[i];
430
0
    }
431
432
0
    inline Real Array::at(Size i) const {
433
0
        QL_REQUIRE(i<n_,
434
0
                   "index (" << i << ") must be less than " << n_ <<
435
0
                   ": array access out of range");
436
0
        return data_.get()[i];
437
0
    }
438
439
0
    inline Real Array::front() const {
440
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
441
0
        QL_REQUIRE(n_>0, "null Array: array access out of range");
442
0
        #endif
443
0
        return data_.get()[0];
444
0
    }
445
446
0
    inline Real Array::back() const {
447
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
448
0
        QL_REQUIRE(n_>0, "null Array: array access out of range");
449
0
        #endif
450
0
        return data_.get()[n_-1];
451
0
    }
452
453
0
    inline Real& Array::operator[](Size i) {
454
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
455
0
        QL_REQUIRE(i<n_,
456
0
                   "index (" << i << ") must be less than " << n_ <<
457
0
                   ": array access out of range");
458
0
        #endif
459
0
        return data_.get()[i];
460
0
    }
461
462
0
    inline Real& Array::at(Size i) {
463
0
        QL_REQUIRE(i<n_,
464
0
                   "index (" << i << ") must be less than " << n_ <<
465
0
                   ": array access out of range");
466
0
        return data_.get()[i];
467
0
    }
Unexecuted instantiation: QuantLib::Array::at(unsigned long)
Unexecuted instantiation: QuantLib::Array::at(unsigned long)
468
469
0
    inline Real& Array::front() {
470
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
471
0
        QL_REQUIRE(n_>0, "null Array: array access out of range");
472
0
        #endif
473
0
        return data_.get()[0];
474
0
    }
475
476
0
    inline Real& Array::back() {
477
0
        #if defined(QL_EXTRA_SAFETY_CHECKS)
478
0
        QL_REQUIRE(n_>0, "null Array: array access out of range");
479
0
        #endif
480
0
        return data_.get()[n_-1];
481
0
    }
482
483
0
    inline Size Array::size() const {
484
0
        return n_;
485
0
    }
486
487
0
    inline bool Array::empty() const {
488
0
        return n_ == 0;
489
0
    }
490
491
0
    inline Array::const_iterator Array::begin() const {
492
0
        return data_.get();
493
0
    }
494
495
0
    inline Array::iterator Array::begin() {
496
0
        return data_.get();
497
0
    }
498
499
0
    inline Array::const_iterator Array::end() const {
500
0
        return data_.get()+n_;
501
0
    }
502
503
0
    inline Array::iterator Array::end() {
504
0
        return data_.get()+n_;
505
0
    }
506
507
0
    inline Array::const_reverse_iterator Array::rbegin() const {
508
0
        return const_reverse_iterator(end());
509
0
    }
510
511
0
    inline Array::reverse_iterator Array::rbegin() {
512
0
        return reverse_iterator(end());
513
0
    }
514
515
0
    inline Array::const_reverse_iterator Array::rend() const {
516
0
        return const_reverse_iterator(begin());
517
0
    }
518
519
0
    inline Array::reverse_iterator Array::rend() {
520
0
        return reverse_iterator(begin());
521
0
    }
522
523
0
    inline void Array::resize(Size n) {
524
0
        if (n > n_) {
525
0
            Array swp(n);
526
0
            std::copy(begin(), end(), swp.begin());
527
0
            swap(swp);
528
0
        }
529
0
        else if (n < n_) {
530
0
            n_ = n;
531
0
        }
532
0
    }
533
534
0
    inline void Array::swap(Array& from) noexcept {
535
0
        data_.swap(from.data_);
536
0
        std::swap(n_, from.n_);
537
0
    }
538
539
    // dot product and norm
540
541
0
    inline Real DotProduct(const Array& v1, const Array& v2) {
542
0
        QL_REQUIRE(v1.size() == v2.size(),
543
0
                   "arrays with different sizes (" << v1.size() << ", "
544
0
                   << v2.size() << ") cannot be multiplied");
545
0
        return std::inner_product(v1.begin(),v1.end(),v2.begin(),Real(0.0));
546
0
    }
Unexecuted instantiation: QuantLib::DotProduct(QuantLib::Array const&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::DotProduct(QuantLib::Array const&, QuantLib::Array const&)
547
548
0
    inline Real Norm2(const Array& v) {
549
0
        return std::sqrt(DotProduct(v, v));
550
0
    }
551
552
    // overloaded operators
553
554
    // unary
555
556
0
    inline Array operator+(const Array& v) {
557
0
        Array result = v;
558
0
        return result;
559
0
    }
560
561
0
    inline Array operator+(Array&& v) {
562
0
        return std::move(v);
563
0
    }
564
565
0
    inline Array operator-(const Array& v) {
566
0
        Array result(v.size());
567
0
        std::transform(v.begin(), v.end(), result.begin(), std::negate<>());
568
0
        return result;
569
0
    }
570
571
0
    inline Array operator-(Array&& v) {
572
0
        Array result = std::move(v);
573
0
        std::transform(result.begin(), result.end(), result.begin(), std::negate<>());
574
0
        return result;
575
0
    }
576
577
    // binary operators
578
579
0
    inline Array operator+(const Array& v1, const Array& v2) {
580
0
        QL_REQUIRE(v1.size() == v2.size(),
581
0
                   "arrays with different sizes (" << v1.size() << ", "
582
0
                   << v2.size() << ") cannot be added");
583
0
        Array result(v1.size());
584
0
        std::transform(v1.begin(),v1.end(),v2.begin(),result.begin(), std::plus<>());
585
0
        return result;
586
0
    }
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array const&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array const&, QuantLib::Array const&)
587
588
0
    inline Array operator+(const Array& v1, Array&& v2) {
589
0
        QL_REQUIRE(v1.size() == v2.size(),
590
0
                   "arrays with different sizes (" << v1.size() << ", "
591
0
                   << v2.size() << ") cannot be added");
592
0
        Array result = std::move(v2);
593
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::plus<>());
594
0
        return result;
595
0
    }
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array const&, QuantLib::Array&&)
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array const&, QuantLib::Array&&)
596
597
0
    inline Array operator+(Array&& v1, const Array& v2) {
598
0
        QL_REQUIRE(v1.size() == v2.size(),
599
0
                   "arrays with different sizes (" << v1.size() << ", "
600
0
                   << v2.size() << ") cannot be added");
601
0
        Array result = std::move(v1);
602
0
        std::transform(result.begin(), result.end(), v2.begin(), result.begin(), std::plus<>());
603
0
        return result;
604
0
    }
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array&&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array&&, QuantLib::Array const&)
605
606
0
    inline Array operator+(Array&& v1, Array&& v2) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
607
0
        QL_REQUIRE(v1.size() == v2.size(),
608
0
                   "arrays with different sizes (" << v1.size() << ", "
609
0
                   << v2.size() << ") cannot be added");
610
0
        Array result = std::move(v2);
611
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::plus<>());
612
0
        return result;
613
0
    }
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array&&, QuantLib::Array&&)
Unexecuted instantiation: QuantLib::operator+(QuantLib::Array&&, QuantLib::Array&&)
614
615
0
    inline Array operator+(const Array& v1, Real a) {
616
0
        Array result(v1.size());
617
0
        std::transform(v1.begin(), v1.end(), result.begin(), [=](Real y) -> Real { return y + a; });
618
0
        return result;
619
0
    }
620
621
0
    inline Array operator+(Array&& v1, Real a) {
622
0
        Array result = std::move(v1);
623
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return y + a; });
624
0
        return result;
625
0
    }
626
627
0
    inline Array operator+(Real a, const Array& v2) {
628
0
        Array result(v2.size());
629
0
        std::transform(v2.begin(),v2.end(),result.begin(), [=](Real y) -> Real { return a + y; });
630
0
        return result;
631
0
    }
632
633
0
    inline Array operator+(Real a, Array&& v2) {
634
0
        Array result = std::move(v2);
635
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return a + y; });
636
0
        return result;
637
0
    }
638
639
0
    inline Array operator-(const Array& v1, const Array& v2) {
640
0
        QL_REQUIRE(v1.size() == v2.size(),
641
0
                   "arrays with different sizes (" << v1.size() << ", "
642
0
                   << v2.size() << ") cannot be subtracted");
643
0
        Array result(v1.size());
644
0
        std::transform(v1.begin(), v1.end(), v2.begin(), result.begin(), std::minus<>());
645
0
        return result;
646
0
    }
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array const&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array const&, QuantLib::Array const&)
647
648
0
    inline Array operator-(const Array& v1, Array&& v2) {
649
0
        QL_REQUIRE(v1.size() == v2.size(),
650
0
                   "arrays with different sizes (" << v1.size() << ", "
651
0
                   << v2.size() << ") cannot be subtracted");
652
0
        Array result = std::move(v2);
653
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::minus<>());
654
0
        return result;
655
0
    }
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array const&, QuantLib::Array&&)
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array const&, QuantLib::Array&&)
656
657
0
    inline Array operator-(Array&& v1, const Array& v2) {
658
0
        QL_REQUIRE(v1.size() == v2.size(),
659
0
                   "arrays with different sizes (" << v1.size() << ", "
660
0
                   << v2.size() << ") cannot be subtracted");
661
0
        Array result = std::move(v1);
662
0
        std::transform(result.begin(), result.end(), v2.begin(), result.begin(), std::minus<>());
663
0
        return result;
664
0
    }
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array&&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array&&, QuantLib::Array const&)
665
666
0
    inline Array operator-(Array&& v1, Array&& v2) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
667
0
        QL_REQUIRE(v1.size() == v2.size(),
668
0
                   "arrays with different sizes (" << v1.size() << ", "
669
0
                   << v2.size() << ") cannot be subtracted");
670
0
        Array result = std::move(v2);
671
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::minus<>());
672
0
        return result;
673
0
    }
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array&&, QuantLib::Array&&)
Unexecuted instantiation: QuantLib::operator-(QuantLib::Array&&, QuantLib::Array&&)
674
675
0
    inline Array operator-(const Array& v1, Real a) {
676
0
        Array result(v1.size());
677
0
        std::transform(v1.begin(),v1.end(),result.begin(), [=](Real y) -> Real { return y - a; });
678
0
        return result;
679
0
    }
680
681
0
    inline Array operator-(Array&& v1, Real a) {
682
0
        Array result = std::move(v1);
683
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return y - a; });
684
0
        return result;
685
0
    }
686
687
0
    inline Array operator-(Real a, const Array& v2) {
688
0
        Array result(v2.size());
689
0
        std::transform(v2.begin(),v2.end(),result.begin(), [=](Real y) -> Real { return a - y; });
690
0
        return result;
691
0
    }
692
693
0
    inline Array operator-(Real a, Array&& v2) {
694
0
        Array result = std::move(v2);
695
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return a - y; });
696
0
        return result;
697
0
    }
698
699
0
    inline Array operator*(const Array& v1, const Array& v2) {
700
0
        QL_REQUIRE(v1.size() == v2.size(),
701
0
                   "arrays with different sizes (" << v1.size() << ", "
702
0
                   << v2.size() << ") cannot be multiplied");
703
0
        Array result(v1.size());
704
0
        std::transform(v1.begin(), v1.end(), v2.begin(), result.begin(), std::multiplies<>());
705
0
        return result;
706
0
    }
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array const&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array const&, QuantLib::Array const&)
707
708
0
    inline Array operator*(const Array& v1, Array&& v2) {
709
0
        QL_REQUIRE(v1.size() == v2.size(),
710
0
                   "arrays with different sizes (" << v1.size() << ", "
711
0
                   << v2.size() << ") cannot be multiplied");
712
0
        Array result = std::move(v2);
713
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::multiplies<>());
714
0
        return result;
715
0
    }
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array const&, QuantLib::Array&&)
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array const&, QuantLib::Array&&)
716
717
0
    inline Array operator*(Array&& v1, const Array& v2) {
718
0
        QL_REQUIRE(v1.size() == v2.size(),
719
0
                   "arrays with different sizes (" << v1.size() << ", "
720
0
                   << v2.size() << ") cannot be multiplied");
721
0
        Array result = std::move(v1);
722
0
        std::transform(result.begin(), result.end(), v2.begin(), result.begin(), std::multiplies<>());
723
0
        return result;
724
0
    }
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array&&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array&&, QuantLib::Array const&)
725
726
0
    inline Array operator*(Array&& v1, Array&& v2) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
727
0
        QL_REQUIRE(v1.size() == v2.size(),
728
0
                   "arrays with different sizes (" << v1.size() << ", "
729
0
                   << v2.size() << ") cannot be multiplied");
730
0
        Array result = std::move(v2);
731
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::multiplies<>());
732
0
        return result;
733
0
    }
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array&&, QuantLib::Array&&)
Unexecuted instantiation: QuantLib::operator*(QuantLib::Array&&, QuantLib::Array&&)
734
735
0
    inline Array operator*(const Array& v1, Real a) {
736
0
        Array result(v1.size());
737
0
        std::transform(v1.begin(),v1.end(),result.begin(), [=](Real y) -> Real { return y * a; });
738
0
        return result;
739
0
    }
740
741
0
    inline Array operator*(Array&& v1, Real a) {
742
0
        Array result = std::move(v1);
743
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return y * a; });
744
0
        return result;
745
0
    }
746
747
0
    inline Array operator*(Real a, const Array& v2) {
748
0
        Array result(v2.size());
749
0
        std::transform(v2.begin(),v2.end(),result.begin(), [=](Real y) -> Real { return a * y; });
750
0
        return result;
751
0
    }
752
753
0
    inline Array operator*(Real a, Array&& v2) {
754
0
        Array result = std::move(v2);
755
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return a * y; });
756
0
        return result;
757
0
    }
758
759
0
    inline Array operator/(const Array& v1, const Array& v2) {
760
0
        QL_REQUIRE(v1.size() == v2.size(),
761
0
                   "arrays with different sizes (" << v1.size() << ", "
762
0
                   << v2.size() << ") cannot be divided");
763
0
        Array result(v1.size());
764
0
        std::transform(v1.begin(), v1.end(), v2.begin(), result.begin(), std::divides<>());
765
0
        return result;
766
0
    }
767
768
0
    inline Array operator/(const Array& v1, Array&& v2) {
769
0
        QL_REQUIRE(v1.size() == v2.size(),
770
0
                   "arrays with different sizes (" << v1.size() << ", "
771
0
                   << v2.size() << ") cannot be divided");
772
0
        Array result = std::move(v2);
773
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::divides<>());
774
0
        return result;
775
0
    }
776
777
0
    inline Array operator/(Array&& v1, const Array& v2) {
778
0
        QL_REQUIRE(v1.size() == v2.size(),
779
0
                   "arrays with different sizes (" << v1.size() << ", "
780
0
                   << v2.size() << ") cannot be divided");
781
0
        Array result = std::move(v1);
782
0
        std::transform(result.begin(), result.end(), v2.begin(), result.begin(), std::divides<>());
783
0
        return result;
784
0
    }
Unexecuted instantiation: QuantLib::operator/(QuantLib::Array&&, QuantLib::Array const&)
Unexecuted instantiation: QuantLib::operator/(QuantLib::Array&&, QuantLib::Array const&)
785
786
0
    inline Array operator/(Array&& v1, Array&& v2) { // NOLINT(cppcoreguidelines-rvalue-reference-param-not-moved)
787
0
        QL_REQUIRE(v1.size() == v2.size(),
788
0
                   "arrays with different sizes (" << v1.size() << ", "
789
0
                   << v2.size() << ") cannot be divided");
790
0
        Array result = std::move(v2);
791
0
        std::transform(v1.begin(), v1.end(), result.begin(), result.begin(), std::divides<>());
792
0
        return result;
793
0
    }
794
795
0
    inline Array operator/(const Array& v1, Real a) {
796
0
        Array result(v1.size());
797
0
        std::transform(v1.begin(),v1.end(),result.begin(), [=](Real y) -> Real { return y / a; });
798
0
        return result;
799
0
    }
800
801
0
    inline Array operator/(Array&& v1, Real a) {
802
0
        Array result = std::move(v1);
803
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return y / a; });
804
0
        return result;
805
0
    }
806
807
0
    inline Array operator/(Real a, const Array& v2) {
808
0
        Array result(v2.size());
809
0
        std::transform(v2.begin(),v2.end(),result.begin(), [=](Real y) -> Real { return a / y; });
810
0
        return result;
811
0
    }
812
813
0
    inline Array operator/(Real a, Array&& v2) {
814
0
        Array result = std::move(v2);
815
0
        std::transform(result.begin(), result.end(), result.begin(), [=](Real y) -> Real { return a / y; });
816
0
        return result;
817
0
    }
818
819
    // functions
820
821
0
    inline Array Abs(const Array& v) {
822
0
        Array result(v.size());
823
0
        std::transform(v.begin(), v.end(), result.begin(),
824
0
                       [](Real x) -> Real { return std::fabs(x); });
825
0
        return result;
826
0
    }
827
828
0
    inline Array Abs(Array&& v) {
829
0
        Array result = std::move(v);
830
0
        std::transform(result.begin(), result.end(), result.begin(),
831
0
                       [](Real x) -> Real { return std::fabs(x); });
832
0
        return result;
833
0
    }
834
835
0
    inline Array Sqrt(const Array& v) {
836
0
        Array result(v.size());
837
0
        std::transform(v.begin(),v.end(),result.begin(),
838
0
                       [](Real x) -> Real { return std::sqrt(x); });
839
0
        return result;
840
0
    }
841
842
0
    inline Array Sqrt(Array&& v) {
843
0
        Array result = std::move(v);
844
0
        std::transform(result.begin(), result.end(), result.begin(),
845
0
                       [](Real x) -> Real { return std::sqrt(x); });
846
0
        return result;
847
0
    }
848
849
0
    inline Array Log(const Array& v) {
850
0
        Array result(v.size());
851
0
        std::transform(v.begin(),v.end(),result.begin(),
852
0
                       [](Real x) -> Real { return std::log(x); });
853
0
        return result;
854
0
    }
855
856
0
    inline Array Log(Array&& v) {
857
0
        Array result = std::move(v);
858
0
        std::transform(result.begin(), result.end(), result.begin(),
859
0
                       [](Real x) -> Real { return std::log(x); });
860
0
        return result;
861
0
    }
862
863
0
    inline Array Exp(const Array& v) {
864
0
        Array result(v.size());
865
0
        std::transform(v.begin(), v.end(), result.begin(),
866
0
                       [](Real x) -> Real { return std::exp(x); });
867
0
        return result;
868
0
    }
869
870
0
    inline Array Exp(Array&& v) {
871
0
        Array result = std::move(v);
872
0
        std::transform(result.begin(), result.end(), result.begin(),
873
0
                       [](Real x) -> Real { return std::exp(x); });
874
0
        return result;
875
0
    }
876
877
0
    inline Array Pow(const Array& v, Real alpha) {
878
0
        Array result(v.size());
879
0
        std::transform(v.begin(), v.end(), result.begin(),
880
0
                       [=](Real x) -> Real { return std::pow(x, alpha); });
881
0
        return result;
882
0
    }
883
884
0
    inline Array Pow(Array&& v, Real alpha) {
885
0
        Array result = std::move(v);
886
0
        std::transform(result.begin(), result.end(), result.begin(),
887
0
                       [=](Real x) -> Real { return std::pow(x, alpha); });
888
0
        return result;
889
0
    }
890
891
0
    inline void swap(Array& v, Array& w) noexcept {
892
0
        v.swap(w);
893
0
    }
894
895
0
    inline std::ostream& operator<<(std::ostream& out, const Array& a) {
896
0
        std::streamsize width = out.width();
897
0
        out << "[ ";
898
0
        if (!a.empty()) {
899
0
            for (Size n=0; n<a.size()-1; ++n)
900
0
                out << std::setw(int(width)) << a[n] << "; ";
901
0
            out << std::setw(int(width)) << a.back();
902
0
        }
903
0
        out << " ]";
904
0
        return out;
905
0
    }
906
907
}
908
909
910
#endif