1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2010 Hachemi Benyahia
5  Copyright (C) 2010 DeriveXperts SAS
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 /*! \file farliegumbelmorgensterncopularng.hpp
22     \brief Farlie-Gumbel-Morgenstern copula random-number generator
23 */
24 
25 #ifndef quantlib_farlie_gumbel_morgenstern_copula_rng_hpp
26 #define quantlib_farlie_gumbel_morgenstern_copula_rng_hpp
27 
28 #include <ql/methods/montecarlo/sample.hpp>
29 #include <ql/errors.hpp>
30 #include <vector>
31 
32 namespace QuantLib {
33 
34     //! Farlie-Gumbel-Morgenstern copula random-number generator
35     template <class RNG>
36     class FarlieGumbelMorgensternCopulaRng {
37       public:
38         typedef Sample<std::vector<Real> > sample_type;
39         typedef RNG urng_type;
40         explicit FarlieGumbelMorgensternCopulaRng(const RNG& uniformGenerator,
41                                                   Real theta);
42         sample_type next() const;
43       private:
44         Real theta_;
45         RNG uniformGenerator_;
46     };
47 
48     template <class RNG>
FarlieGumbelMorgensternCopulaRng(const RNG & ug,Real th)49     FarlieGumbelMorgensternCopulaRng<RNG>::FarlieGumbelMorgensternCopulaRng(
50                                                        const RNG& ug, Real th)
51     : uniformGenerator_(ug), theta_(th) {
52         QL_REQUIRE(th >= -1.0 && th <= 1.00,
53                    "theta (" << th << ") must be in [-1,1]");
54     }
55 
56     template <class RNG>
57     inline typename FarlieGumbelMorgensternCopulaRng<RNG>::sample_type
next() const58     FarlieGumbelMorgensternCopulaRng<RNG>::next() const {
59         typename RNG::sample_type v1 = uniformGenerator_.next();
60         typename RNG::sample_type v2 = uniformGenerator_.next();
61         Real u1 = v1.value;
62         Real a = theta_*(2.0*u1-1.0);
63         Real b = pow(1.0-theta_*(2.0*u1-1.0),2.0)+4.0*theta_*v2.value*(2.0*u1-1.0);
64         Real u2 = (2.0*v2.value)/(sqrt(b)-a);
65         std::vector<Real> u;
66         u.push_back(u1);
67         u.push_back(u2);
68         return sample_type(u,v1.weight*v2.weight);
69     }
70 
71 }
72 
73 
74 #endif
75