⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pfqfn.cpp

📁 Quantitative Finance C++ source code, asian option pricer
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// testf2c2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "f2c.h"


/* testpfq.f -- translated by f2c (version 20060506).
   You must link the resulting object file with libf2c:
	on Microsoft Windows system, link with libf2c.lib;
	on Linux or Unix systems, link with .../path/to/libf2c.a -lm
	or, if you install libf2c.a in a standard place, with -lf2c -lm
	-- in that order, at the end of the command line, as in
		cc *.o -lf2c -lm
	Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,

		http://www.netlib.org/f2c/libf2c.zip
*/

//#include "f2c.h"


extern "C" integer i_dnnt(doublereal *);
extern "C" double d_imag(doublecomplex *);
extern "C" void z_div(doublecomplex *, doublecomplex *, doublecomplex *), pow_zz(
	    doublecomplex *, doublecomplex *, doublecomplex *);
extern "C" integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), 
	    e_wsle(void);
extern "C" int s_stop(char *, ftnlen);
extern "C" double z_abs(doublecomplex *);
extern "C" integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void);

extern "C" void z_log(doublecomplex *, doublecomplex *);
extern "C" double exp(doublereal);
extern "C" void z_div(doublecomplex *, doublecomplex *, doublecomplex *);
extern "C" double d_sign(doublereal *, doublereal *), pow_dd(doublereal *, 
	    doublereal *), z_abs(doublecomplex *);
extern "C"     double d_lg10(doublereal *), pow_di(doublereal *, integer *), d_int(
	    doublereal *), d_nint(doublereal *), d_imag(doublecomplex *);
extern "C"     integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void),
	     s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), 
	    e_wsle(void), i_dnnt(doublereal *);
extern "C" double d_lg10(doublereal *), d_sign(doublereal *, doublereal *), pow_dd(
	    doublereal *, doublereal *), atan2(doublereal, doublereal), log(
	    doublereal);

extern "C"     double d_imag(doublecomplex *), z_abs(doublecomplex *), atan(doublereal), 
	    log(doublereal);
extern "C"     void z_log(doublecomplex *, doublecomplex *), z_div(doublecomplex *, 
	    doublecomplex *, doublecomplex *);
extern "C" double d_imag(doublecomplex *), atan(doublereal), pow_di(doublereal *, 
	    integer *), log(doublereal);
extern "C" integer i_dnnt(doublereal *), s_wsfe(cilist *), e_wsfe(void), do_fio(
	    integer *, char *, ftnlen);
    /* Subroutine */ int s_stop(char *, ftnlen);
extern "C" double sin(doublereal), sqrt(doublereal), atan2(doublereal, doublereal), 
	    exp(doublereal), cos(doublereal);


/* Common Block Declarations */

struct consts_1_ {
    doublereal zero, half, one, two, ten, eps;
};

#define consts_1 (*(struct consts_1_ *) &consts_)

struct {
    integer nout;
} io_;

#define io_1 io_

/* Initialized data */

struct {
    doublereal e_1[6];
    } consts_ = { 0., .5, 1., 2., 10., 1e-10 };


/* Table of constant values */

static integer c__9 = 9;
static integer c__1 = 1;
static integer c__25000 = 25000;
static doublereal c_b64 = 10.;

/*     **************************************************************** */
/*     *                                                              * */
/*     *    SOLUTION TO THE GENERALIZED HYPERGEOMETRIC FUNCTION       * */
/*     *                                                              * */
/*     *                           by                                 * */
/*     *                                                              * */
/*     *                      W. F. PERGER,                           * */
/*     *                                                              * */
/*     *              MARK NARDIN  and ATUL BHALLA                    * */
/*     *                                                              * */
/*     *                                                              * */
/*     *            Electrical Engineering Department                 * */
/*     *            Michigan Technological University                 * */
/*     *                  1400 Townsend Drive                         * */
/*     *                Houghton, MI  49931-1295   USA                * */
/*     *                     Copyright 1993                           * */
/*     *                                                              * */
/*     *               e-mail address: wfp@mtu.edu                    * */
/*     *                                                              * */
/*     *  Description : A numerical evaluator for the generalized     * */
/*     *    hypergeometric function for complex arguments with large  * */
/*     *    magnitudes using a direct summation of the Gauss series.  * */
/*     *    The method used allows an accuracy of up to thirteen      * */
/*     *    decimal places through the use of large integer arrays    * */
/*     *    and a single final division.                              * */
/*     *    (original subroutines for the confluent hypergeometric    * */
/*     *    written by Mark Nardin, 1989; modifications made to cal-  * */
/*     *    culate the generalized hypergeometric function were       * */
/*     *    written by W.F. Perger and A. Bhalla, June, 1990)         * */
/*     *                                                              * */
/*     *  The evaluation of the pFq series is accomplished by a func- * */
/*     *  ion call to PFQ, which is a double precision complex func-  * */
/*     *  tion.  The required input is:                               * */
/*     *  1. Double precision complex arrays A and B.  These are the  * */
/*     *     arrays containing the parameters in the numerator and de-* */
/*     *     nominator, respectively.                                 * */
/*     *  2. Integers IP and IQ.  These integers indicate the number  * */
/*     *     of numerator and denominator terms, respectively (these  * */
/*     *     are p and q in the pFq function).                        * */
/*     *  3. Double precision complex argument Z.                     * */
/*     *  4. Integer LNPFQ.  This integer should be set to '1' if the * */
/*     *     result from PFQ is to be returned as the natural logaritm* */
/*     *     of the series, or '0' if not.  The user can generally set* */
/*     *     LNPFQ = '0' and change it if required.                   * */
/*     *  5. Integer IX.  This integer should be set to '0' if the    * */
/*     *     user desires the program PFQ to estimate the number of   * */
/*     *     array terms (in A and B) to be used, or an integer       * */
/*     *     greater than zero specifying the number of integer pos-  * */
/*     *     itions to be used.  This input parameter is escpecially  * */
/*     *     useful as a means to check the results of a given run.   * */
/*     *     Specificially, if the user obtains a result for a given  * */
/*     *     set of parameters, then changes IX and re-runs the eval- * */
/*     *     uator, and if the number of array positions was insuffi- * */
/*     *     cient, then the two results will likely differ.  The rec-* */
/*     *     commended would be to generally set IX = '0' and then set* */
/*     *     it to 100 or so for a second run.  Note that the LENGTH  * */
/*     *     parameter currently sets the upper limit on IX to 777,   * */
/*     *     but that can easily be changed (it is a single PARAMETER * */
/*     *     statement) and the program recompiled.                   * */
/*     *  6. Integer NSIGFIG.  This integer specifies the requested   * */
/*     *     number of significant figures in the final result.  If   * */
/*     *     the user attempts to request more than the number of bits* */
/*     *     in the mantissa allows, the program will abort with an   * */
/*     *     appropriate error message.  The recommended value is 10. * */
/*     *                                                              * */
/*     *     Note: The variable NOUT is the file to which error mess- * */
/*     *           ages are written (default is 6).  This can be      * */
/*     *           changed in the FUNCTION PFQ to accomodate re-      * */
/*     *           of output to another file                          * */
/*     *                                                              * */
/*     *  Subprograms called: HYPER.                                  * */
/*     *                                                              * */
/*     **************************************************************** */

/* Double Complex */ VOID pfq_(doublecomplex * ret_val, doublecomplex *a, 
	doublecomplex *b, integer *ip, integer *iq, doublecomplex *z__, 
	integer *lnpfq, integer *ix, integer *nsigfig)
{
    /* Format strings */
    static char fmt_300[] = "(/,1x,\002IP=\002,1i2,3x,\002IQ=\002,1i2,3x,"
	    "\002AND ABS(Z)=\002,1e12.5,2x,/,\002 WHICH IS GREATER THAN ONE--"
	    "SERIES DOES\002,\002 NOT CONVERGE\002)";

    /* System generated locals */
    doublereal d__1;
    doublecomplex z__1, z__2, z__3, z__4, z__5, z__6, z__7, z__8, z__9, z__10,
	     z__11, z__12, z__13, z__14, z__15, z__16, z__17;

    /* Builtin functions */
    //integer s_wsle(cilist *), do_lio(integer *, integer *, char *, ftnlen), 
	    //e_wsle(void);
    /* Subroutine */ int s_stop(char *, ftnlen);
   // double z_abs(doublecomplex *);
    //integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void);
    //void z_div(doublecomplex *, doublecomplex *, doublecomplex *), pow_zz(
	  //  doublecomplex *, doublecomplex *, doublecomplex *);
    //double d_imag(doublecomplex *);
    //integer i_dnnt(doublereal *);

    /* Local variables */
    static integer i__;
    static doublecomplex a1[2], b1[1], z1, gam1, gam2, gam3, gam4, gam5, gam6,
	     gam7;
    static doublereal diff, argi, argr, dnum;
    extern /* Double Complex */ VOID hyper_(doublecomplex *, doublecomplex *, 
	    doublecomplex *, integer *, integer *, doublecomplex *, integer *,
	     integer *, integer *);
    static doublecomplex hyper1, hyper2;
    extern /* Double Complex */ VOID cgamma_(doublecomplex *, doublecomplex *,
	     integer *);
    static doublereal precis;

    /* Fortran I/O blocks */
    static cilist io___1 = { 0, 0, 0, 0, 0 };
    static cilist io___2 = { 0, 0, 0, fmt_300, 0 };


    /* Parameter adjustments */
    --a;
    --b;

    /* Function Body */
    io_1.nout = 6;
    z__1.r = consts_1.zero, z__1.i = consts_1.zero;
    if (z__->r == z__1.r && z__->i == z__1.i) {
	z__1.r = consts_1.one, z__1.i = consts_1.zero;
	 ret_val->r = z__1.r,  ret_val->i = z__1.i;
	return ;
    }
    if (*lnpfq != 0 && *lnpfq != 1) {
	io___1.ciunit = io_1.nout;
	s_wsle(&io___1);
	do_lio(&c__9, &c__1, " ERROR IN INPUT ARGUMENTS: LNPFQ /= 0 OR 1", (
		ftnlen)42);
	e_wsle();
	s_stop("", (ftnlen)0);
    }
    if (*ip > *iq && z_abs(z__) > consts_1.one && *ip > 2) {
	io___2.ciunit = io_1.nout;
	s_wsfe(&io___2);
	do_fio(&c__1, (char *)&(*ip), (ftnlen)sizeof(integer));
	do_fio(&c__1, (char *)&(*iq), (ftnlen)sizeof(integer));
	d__1 = z_abs(z__);
	do_fio(&c__1, (char *)&d__1, (ftnlen)sizeof(doublereal));
	e_wsfe();
	s_stop("", (ftnlen)0);
    }

/* For the 2F1 function with |z| > 1, use Abramowitz and Stegun, 15.3.7. */

    if (*ip == 2 && *iq == 1 && z_abs(z__) > consts_1.one) {
	z__2.r = consts_1.one, z__2.i = 0.;
	z_div(&z__1, &z__2, z__);
	z1.r = z__1.r, z1.i = z__1.i;
	a1[0].r = a[1].r, a1[0].i = a[1].i;
	z__2.r = consts_1.one - b[1].r, z__2.i = -b[1].i;
	z__1.r = z__2.r + a[1].r, z__1.i = z__2.i + a[1].i;
	a1[1].r = z__1.r, a1[1].i = z__1.i;
	z__2.r = consts_1.one - a[2].r, z__2.i = -a[2].i;
	z__1.r = z__2.r + a[1].r, z__1.i = z__2.i + a[1].i;
	b1[0].r = z__1.r, b1[0].i = z__1.i;
	cgamma_(&z__1, &b[1], lnpfq);
	gam1.r = z__1.r, gam1.i = z__1.i;
	z__2.r = a[2].r - a[1].r, z__2.i = a[2].i - a[1].i;
	cgamma_(&z__1, &z__2, lnpfq);
	gam2.r = z__1.r, gam2.i = z__1.i;
	cgamma_(&z__1, &a[2], lnpfq);
	gam3.r = z__1.r, gam3.i = z__1.i;
	z__2.r = b[1].r - a[1].r, z__2.i = b[1].i - a[1].i;
	cgamma_(&z__1, &z__2, lnpfq);
	gam4.r = z__1.r, gam4.i = z__1.i;
	z__2.r = a[1].r - a[2].r, z__2.i = a[1].i - a[2].i;
	cgamma_(&z__1, &z__2, lnpfq);
	gam5.r = z__1.r, gam5.i = z__1.i;
	cgamma_(&z__1, &a[1], lnpfq);
	gam6.r = z__1.r, gam6.i = z__1.i;
	z__2.r = b[1].r - a[2].r, z__2.i = b[1].i - a[2].i;
	cgamma_(&z__1, &z__2, lnpfq);
	gam7.r = z__1.r, gam7.i = z__1.i;
	hyper_(&z__1, a1, b1, ip, iq, &z1, lnpfq, ix, nsigfig);
	hyper1.r = z__1.r, hyper1.i = z__1.i;
	a1[0].r = a[2].r, a1[0].i = a[2].i;
	z__2.r = consts_1.one - b[1].r, z__2.i = -b[1].i;
	z__1.r = z__2.r + a[2].r, z__1.i = z__2.i + a[2].i;
	a1[1].r = z__1.r, a1[1].i = z__1.i;
	z__2.r = consts_1.one - a[1].r, z__2.i = -a[1].i;
	z__1.r = z__2.r + a[2].r, z__1.i = z__2.i + a[2].i;
	b1[0].r = z__1.r, b1[0].i = z__1.i;
	hyper_(&z__1, a1, b1, ip, iq, &z1, lnpfq, ix, nsigfig);
	hyper2.r = z__1.r, hyper2.i = z__1.i;
	z__5.r = gam1.r * gam2.r - gam1.i * gam2.i, z__5.i = gam1.r * gam2.i 
		+ gam1.i * gam2.r;
	z__7.r = -z__->r, z__7.i = -z__->i;
	z__8.r = -a[1].r, z__8.i = -a[1].i;
	pow_zz(&z__6, &z__7, &z__8);
	z__4.r = z__5.r * z__6.r - z__5.i * z__6.i, z__4.i = z__5.r * z__6.i 
		+ z__5.i * z__6.r;
	z__3.r = z__4.r * hyper1.r - z__4.i * hyper1.i, z__3.i = z__4.r * 
		hyper1.i + z__4.i * hyper1.r;
	z__9.r = gam3.r * gam4.r - gam3.i * gam4.i, z__9.i = gam3.r * gam4.i 
		+ gam3.i * gam4.r;
	z_div(&z__2, &z__3, &z__9);
	z__13.r = gam1.r * gam5.r - gam1.i * gam5.i, z__13.i = gam1.r * 
		gam5.i + gam1.i * gam5.r;
	z__15.r = -z__->r, z__15.i = -z__->i;
	z__16.r = -a[2].r, z__16.i = -a[2].i;
	pow_zz(&z__14, &z__15, &z__16);
	z__12.r = z__13.r * z__14.r - z__13.i * z__14.i, z__12.i = z__13.r * 
		z__14.i + z__13.i * z__14.r;
	z__11.r = z__12.r * hyper2.r - z__12.i * hyper2.i, z__11.i = z__12.r *
		 hyper2.i + z__12.i * hyper2.r;
	z__17.r = gam6.r * gam7.r - gam6.i * gam7.i, z__17.i = gam6.r * 
		gam7.i + gam6.i * gam7.r;
	z_div(&z__10, &z__11, &z__17);
	z__1.r = z__2.r + z__10.r, z__1.i = z__2.i + z__10.i;
	 ret_val->r = z__1.r,  ret_val->i = z__1.i;
	return ;
    }
    if (*ip == 2 && *iq == 1 && z_abs(z__) > .9f) {
	if (*lnpfq == 1) {
	    goto L30;
	}

/*     Check to see if the Gamma function arguments are o.k.; if not, */
/*     then the series will have to be used. */

/*     PRECIS - MACHINE PRECISION */

	precis = consts_1.one;
L10:
	precis /= consts_1.two;
	dnum = precis + consts_1.one;
	if (dnum > consts_1.one) {
	    goto L10;
	}
	precis = consts_1.two * precis;
	for (i__ = 1; i__ <= 6; ++i__) {
	    if (i__ == 1) {
		argi = d_imag(&b[1]);
		argr = b[1].r;
	    } else if (i__ == 2) {
		z__2.r = b[1].r - a[1].r, z__2.i = b[1].i - a[1].i;
		z__1.r = z__2.r - a[2].r, z__1.i = z__2.i - a[2].i;
		argi = d_imag(&z__1);
		z__2.r = b[1].r - a[1].r, z__2.i = b[1].i - a[1].i;
		z__1.r = z__2.r - a[2].r, z__1.i = z__2.i - a[2].i;
		argr = z__1.r;
	    } else if (i__ == 3) {
		z__1.r = b[1].r - a[1].r, z__1.i = b[1].i - a[1].i;
		argi = d_imag(&z__1);
		z__1.r = b[1].r - a[1].r, z__1.i = b[1].i - a[1].i;
		argr = z__1.r;
	    } else if (i__ == 4) {
		z__2.r = a[1].r + a[2].r, z__2.i = a[1].i + a[2].i;
		z__1.r = z__2.r - b[1].r, z__1.i = z__2.i - b[1].i;
		argi = d_imag(&z__1);
		z__2.r = a[1].r + a[2].r, z__2.i = a[1].i + a[2].i;
		z__1.r = z__2.r - b[1].r, z__1.i = z__2.i - b[1].i;
		argr = z__1.r;
	    } else if (i__ == 5) {
		argi = d_imag(&a[1]);
		argr = a[1].r;
	    } else if (i__ == 6) {
		argi = d_imag(&a[2]);
		argr = a[2].r;
	    }

/*     CASES WHERE THE ARGUMENT IS REAL */

	    if (argi == consts_1.zero) {

/*     CASES WHERE THE ARGUMENT IS REAL AND NEGATIVE */

		if (argr <= consts_1.zero) {

/*     USE THE SERIES EXPANSION IF THE ARGUMENT IS TOO NEAR A POLE */

		    diff = (d__1 = (doublereal) i_dnnt(&argr) - argr, abs(
			    d__1));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -