OpenCores
URL https://opencores.org/ocsvn/altor32/altor32/trunk

Subversion Repositories altor32

[/] [altor32/] [trunk/] [gcc-x64/] [or1knd-elf/] [or1knd-elf/] [include/] [c++/] [4.8.0/] [tr1/] [hypergeometric.tcc] - Blame information for rev 35

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 35 ultra_embe
// Special functions -*- C++ -*-
2
 
3
// Copyright (C) 2006, 2007, 2008, 2009, 2010
4
// Free Software Foundation, Inc.
5
//
6
// This file is part of the GNU ISO C++ Library.  This library is free
7
// software; you can redistribute it and/or modify it under the
8
// terms of the GNU General Public License as published by the
9
// Free Software Foundation; either version 3, or (at your option)
10
// any later version.
11
//
12
// This library is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
// GNU General Public License for more details.
16
//
17
// Under Section 7 of GPL version 3, you are granted additional
18
// permissions described in the GCC Runtime Library Exception, version
19
// 3.1, as published by the Free Software Foundation.
20
 
21
// You should have received a copy of the GNU General Public License and
22
// a copy of the GCC Runtime Library Exception along with this program;
23
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24
// .
25
 
26
/** @file tr1/hypergeometric.tcc
27
 *  This is an internal header file, included by other library headers.
28
 *  Do not attempt to use it directly. @headername{tr1/cmath}
29
 */
30
 
31
//
32
// ISO C++ 14882 TR1: 5.2  Special functions
33
//
34
 
35
// Written by Edward Smith-Rowland based:
36
//   (1) Handbook of Mathematical Functions,
37
//       ed. Milton Abramowitz and Irene A. Stegun,
38
//       Dover Publications,
39
//       Section 6, pp. 555-566
40
//   (2) The Gnu Scientific Library, http://www.gnu.org/software/gsl
41
 
42
#ifndef _GLIBCXX_TR1_HYPERGEOMETRIC_TCC
43
#define _GLIBCXX_TR1_HYPERGEOMETRIC_TCC 1
44
 
45
namespace std _GLIBCXX_VISIBILITY(default)
46
{
47
namespace tr1
48
{
49
  // [5.2] Special functions
50
 
51
  // Implementation-space details.
52
  namespace __detail
53
  {
54
  _GLIBCXX_BEGIN_NAMESPACE_VERSION
55
 
56
    /**
57
     *   @brief This routine returns the confluent hypergeometric function
58
     *          by series expansion.
59
     *
60
     *   @f[
61
     *     _1F_1(a;c;x) = \frac{\Gamma(c)}{\Gamma(a)}
62
     *                      \sum_{n=0}^{\infty}
63
     *                      \frac{\Gamma(a+n)}{\Gamma(c+n)}
64
     *                      \frac{x^n}{n!}
65
     *   @f]
66
     *
67
     *   If a and b are integers and a < 0 and either b > 0 or b < a
68
     *   then the series is a polynomial with a finite number of
69
     *   terms.  If b is an integer and b <= 0 the confluent
70
     *   hypergeometric function is undefined.
71
     *
72
     *   @param  __a  The "numerator" parameter.
73
     *   @param  __c  The "denominator" parameter.
74
     *   @param  __x  The argument of the confluent hypergeometric function.
75
     *   @return  The confluent hypergeometric function.
76
     */
77
    template
78
    _Tp
79
    __conf_hyperg_series(const _Tp __a, const _Tp __c, const _Tp __x)
80
    {
81
      const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
82
 
83
      _Tp __term = _Tp(1);
84
      _Tp __Fac = _Tp(1);
85
      const unsigned int __max_iter = 100000;
86
      unsigned int __i;
87
      for (__i = 0; __i < __max_iter; ++__i)
88
        {
89
          __term *= (__a + _Tp(__i)) * __x
90
                  / ((__c + _Tp(__i)) * _Tp(1 + __i));
91
          if (std::abs(__term) < __eps)
92
            {
93
              break;
94
            }
95
          __Fac += __term;
96
        }
97
      if (__i == __max_iter)
98
        std::__throw_runtime_error(__N("Series failed to converge "
99
                                       "in __conf_hyperg_series."));
100
 
101
      return __Fac;
102
    }
103
 
104
 
105
    /**
106
     *  @brief  Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$
107
     *          by an iterative procedure described in
108
     *          Luke, Algorithms for the Computation of Mathematical Functions.
109
     *
110
     *  Like the case of the 2F1 rational approximations, these are
111
     *  probably guaranteed to converge for x < 0, barring gross
112
     *  numerical instability in the pre-asymptotic regime.
113
     */
114
    template
115
    _Tp
116
    __conf_hyperg_luke(const _Tp __a, const _Tp __c, const _Tp __xin)
117
    {
118
      const _Tp __big = std::pow(std::numeric_limits<_Tp>::max(), _Tp(0.16L));
119
      const int __nmax = 20000;
120
      const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
121
      const _Tp __x  = -__xin;
122
      const _Tp __x3 = __x * __x * __x;
123
      const _Tp __t0 = __a / __c;
124
      const _Tp __t1 = (__a + _Tp(1)) / (_Tp(2) * __c);
125
      const _Tp __t2 = (__a + _Tp(2)) / (_Tp(2) * (__c + _Tp(1)));
126
      _Tp __F = _Tp(1);
127
      _Tp __prec;
128
 
129
      _Tp __Bnm3 = _Tp(1);
130
      _Tp __Bnm2 = _Tp(1) + __t1 * __x;
131
      _Tp __Bnm1 = _Tp(1) + __t2 * __x * (_Tp(1) + __t1 / _Tp(3) * __x);
132
 
133
      _Tp __Anm3 = _Tp(1);
134
      _Tp __Anm2 = __Bnm2 - __t0 * __x;
135
      _Tp __Anm1 = __Bnm1 - __t0 * (_Tp(1) + __t2 * __x) * __x
136
                 + __t0 * __t1 * (__c / (__c + _Tp(1))) * __x * __x;
137
 
138
      int __n = 3;
139
      while(1)
140
        {
141
          _Tp __npam1 = _Tp(__n - 1) + __a;
142
          _Tp __npcm1 = _Tp(__n - 1) + __c;
143
          _Tp __npam2 = _Tp(__n - 2) + __a;
144
          _Tp __npcm2 = _Tp(__n - 2) + __c;
145
          _Tp __tnm1  = _Tp(2 * __n - 1);
146
          _Tp __tnm3  = _Tp(2 * __n - 3);
147
          _Tp __tnm5  = _Tp(2 * __n - 5);
148
          _Tp __F1 =  (_Tp(__n - 2) - __a) / (_Tp(2) * __tnm3 * __npcm1);
149
          _Tp __F2 =  (_Tp(__n) + __a) * __npam1
150
                   / (_Tp(4) * __tnm1 * __tnm3 * __npcm2 * __npcm1);
151
          _Tp __F3 = -__npam2 * __npam1 * (_Tp(__n - 2) - __a)
152
                   / (_Tp(8) * __tnm3 * __tnm3 * __tnm5
153
                   * (_Tp(__n - 3) + __c) * __npcm2 * __npcm1);
154
          _Tp __E  = -__npam1 * (_Tp(__n - 1) - __c)
155
                   / (_Tp(2) * __tnm3 * __npcm2 * __npcm1);
156
 
157
          _Tp __An = (_Tp(1) + __F1 * __x) * __Anm1
158
                   + (__E + __F2 * __x) * __x * __Anm2 + __F3 * __x3 * __Anm3;
159
          _Tp __Bn = (_Tp(1) + __F1 * __x) * __Bnm1
160
                   + (__E + __F2 * __x) * __x * __Bnm2 + __F3 * __x3 * __Bnm3;
161
          _Tp __r = __An / __Bn;
162
 
163
          __prec = std::abs((__F - __r) / __F);
164
          __F = __r;
165
 
166
          if (__prec < __eps || __n > __nmax)
167
            break;
168
 
169
          if (std::abs(__An) > __big || std::abs(__Bn) > __big)
170
            {
171
              __An   /= __big;
172
              __Bn   /= __big;
173
              __Anm1 /= __big;
174
              __Bnm1 /= __big;
175
              __Anm2 /= __big;
176
              __Bnm2 /= __big;
177
              __Anm3 /= __big;
178
              __Bnm3 /= __big;
179
            }
180
          else if (std::abs(__An) < _Tp(1) / __big
181
                || std::abs(__Bn) < _Tp(1) / __big)
182
            {
183
              __An   *= __big;
184
              __Bn   *= __big;
185
              __Anm1 *= __big;
186
              __Bnm1 *= __big;
187
              __Anm2 *= __big;
188
              __Bnm2 *= __big;
189
              __Anm3 *= __big;
190
              __Bnm3 *= __big;
191
            }
192
 
193
          ++__n;
194
          __Bnm3 = __Bnm2;
195
          __Bnm2 = __Bnm1;
196
          __Bnm1 = __Bn;
197
          __Anm3 = __Anm2;
198
          __Anm2 = __Anm1;
199
          __Anm1 = __An;
200
        }
201
 
202
      if (__n >= __nmax)
203
        std::__throw_runtime_error(__N("Iteration failed to converge "
204
                                       "in __conf_hyperg_luke."));
205
 
206
      return __F;
207
    }
208
 
209
 
210
    /**
211
     *   @brief  Return the confluent hypogeometric function
212
     *           @f$ _1F_1(a;c;x) @f$.
213
     *
214
     *   @todo  Handle b == nonpositive integer blowup - return NaN.
215
     *
216
     *   @param  __a  The @a numerator parameter.
217
     *   @param  __c  The @a denominator parameter.
218
     *   @param  __x  The argument of the confluent hypergeometric function.
219
     *   @return  The confluent hypergeometric function.
220
     */
221
    template
222
    inline _Tp
223
    __conf_hyperg(const _Tp __a, const _Tp __c, const _Tp __x)
224
    {
225
#if _GLIBCXX_USE_C99_MATH_TR1
226
      const _Tp __c_nint = std::tr1::nearbyint(__c);
227
#else
228
      const _Tp __c_nint = static_cast(__c + _Tp(0.5L));
229
#endif
230
      if (__isnan(__a) || __isnan(__c) || __isnan(__x))
231
        return std::numeric_limits<_Tp>::quiet_NaN();
232
      else if (__c_nint == __c && __c_nint <= 0)
233
        return std::numeric_limits<_Tp>::infinity();
234
      else if (__a == _Tp(0))
235
        return _Tp(1);
236
      else if (__c == __a)
237
        return std::exp(__x);
238
      else if (__x < _Tp(0))
239
        return __conf_hyperg_luke(__a, __c, __x);
240
      else
241
        return __conf_hyperg_series(__a, __c, __x);
242
    }
243
 
244
 
245
    /**
246
     *   @brief Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$
247
     *   by series expansion.
248
     *
249
     *   The hypogeometric function is defined by
250
     *   @f[
251
     *     _2F_1(a,b;c;x) = \frac{\Gamma(c)}{\Gamma(a)\Gamma(b)}
252
     *                      \sum_{n=0}^{\infty}
253
     *                      \frac{\Gamma(a+n)\Gamma(b+n)}{\Gamma(c+n)}
254
     *                      \frac{x^n}{n!}
255
     *   @f]
256
     *
257
     *   This works and it's pretty fast.
258
     *
259
     *   @param  __a  The first @a numerator parameter.
260
     *   @param  __a  The second @a numerator parameter.
261
     *   @param  __c  The @a denominator parameter.
262
     *   @param  __x  The argument of the confluent hypergeometric function.
263
     *   @return  The confluent hypergeometric function.
264
     */
265
    template
266
    _Tp
267
    __hyperg_series(const _Tp __a, const _Tp __b,
268
                    const _Tp __c, const _Tp __x)
269
    {
270
      const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
271
 
272
      _Tp __term = _Tp(1);
273
      _Tp __Fabc = _Tp(1);
274
      const unsigned int __max_iter = 100000;
275
      unsigned int __i;
276
      for (__i = 0; __i < __max_iter; ++__i)
277
        {
278
          __term *= (__a + _Tp(__i)) * (__b + _Tp(__i)) * __x
279
                  / ((__c + _Tp(__i)) * _Tp(1 + __i));
280
          if (std::abs(__term) < __eps)
281
            {
282
              break;
283
            }
284
          __Fabc += __term;
285
        }
286
      if (__i == __max_iter)
287
        std::__throw_runtime_error(__N("Series failed to converge "
288
                                       "in __hyperg_series."));
289
 
290
      return __Fabc;
291
    }
292
 
293
 
294
    /**
295
     *   @brief  Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$
296
     *           by an iterative procedure described in
297
     *           Luke, Algorithms for the Computation of Mathematical Functions.
298
     */
299
    template
300
    _Tp
301
    __hyperg_luke(const _Tp __a, const _Tp __b, const _Tp __c,
302
                  const _Tp __xin)
303
    {
304
      const _Tp __big = std::pow(std::numeric_limits<_Tp>::max(), _Tp(0.16L));
305
      const int __nmax = 20000;
306
      const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
307
      const _Tp __x  = -__xin;
308
      const _Tp __x3 = __x * __x * __x;
309
      const _Tp __t0 = __a * __b / __c;
310
      const _Tp __t1 = (__a + _Tp(1)) * (__b + _Tp(1)) / (_Tp(2) * __c);
311
      const _Tp __t2 = (__a + _Tp(2)) * (__b + _Tp(2))
312
                     / (_Tp(2) * (__c + _Tp(1)));
313
 
314
      _Tp __F = _Tp(1);
315
 
316
      _Tp __Bnm3 = _Tp(1);
317
      _Tp __Bnm2 = _Tp(1) + __t1 * __x;
318
      _Tp __Bnm1 = _Tp(1) + __t2 * __x * (_Tp(1) + __t1 / _Tp(3) * __x);
319
 
320
      _Tp __Anm3 = _Tp(1);
321
      _Tp __Anm2 = __Bnm2 - __t0 * __x;
322
      _Tp __Anm1 = __Bnm1 - __t0 * (_Tp(1) + __t2 * __x) * __x
323
                 + __t0 * __t1 * (__c / (__c + _Tp(1))) * __x * __x;
324
 
325
      int __n = 3;
326
      while (1)
327
        {
328
          const _Tp __npam1 = _Tp(__n - 1) + __a;
329
          const _Tp __npbm1 = _Tp(__n - 1) + __b;
330
          const _Tp __npcm1 = _Tp(__n - 1) + __c;
331
          const _Tp __npam2 = _Tp(__n - 2) + __a;
332
          const _Tp __npbm2 = _Tp(__n - 2) + __b;
333
          const _Tp __npcm2 = _Tp(__n - 2) + __c;
334
          const _Tp __tnm1  = _Tp(2 * __n - 1);
335
          const _Tp __tnm3  = _Tp(2 * __n - 3);
336
          const _Tp __tnm5  = _Tp(2 * __n - 5);
337
          const _Tp __n2 = __n * __n;
338
          const _Tp __F1 = (_Tp(3) * __n2 + (__a + __b - _Tp(6)) * __n
339
                         + _Tp(2) - __a * __b - _Tp(2) * (__a + __b))
340
                         / (_Tp(2) * __tnm3 * __npcm1);
341
          const _Tp __F2 = -(_Tp(3) * __n2 - (__a + __b + _Tp(6)) * __n
342
                         + _Tp(2) - __a * __b) * __npam1 * __npbm1
343
                         / (_Tp(4) * __tnm1 * __tnm3 * __npcm2 * __npcm1);
344
          const _Tp __F3 = (__npam2 * __npam1 * __npbm2 * __npbm1
345
                         * (_Tp(__n - 2) - __a) * (_Tp(__n - 2) - __b))
346
                         / (_Tp(8) * __tnm3 * __tnm3 * __tnm5
347
                         * (_Tp(__n - 3) + __c) * __npcm2 * __npcm1);
348
          const _Tp __E  = -__npam1 * __npbm1 * (_Tp(__n - 1) - __c)
349
                         / (_Tp(2) * __tnm3 * __npcm2 * __npcm1);
350
 
351
          _Tp __An = (_Tp(1) + __F1 * __x) * __Anm1
352
                   + (__E + __F2 * __x) * __x * __Anm2 + __F3 * __x3 * __Anm3;
353
          _Tp __Bn = (_Tp(1) + __F1 * __x) * __Bnm1
354
                   + (__E + __F2 * __x) * __x * __Bnm2 + __F3 * __x3 * __Bnm3;
355
          const _Tp __r = __An / __Bn;
356
 
357
          const _Tp __prec = std::abs((__F - __r) / __F);
358
          __F = __r;
359
 
360
          if (__prec < __eps || __n > __nmax)
361
            break;
362
 
363
          if (std::abs(__An) > __big || std::abs(__Bn) > __big)
364
            {
365
              __An   /= __big;
366
              __Bn   /= __big;
367
              __Anm1 /= __big;
368
              __Bnm1 /= __big;
369
              __Anm2 /= __big;
370
              __Bnm2 /= __big;
371
              __Anm3 /= __big;
372
              __Bnm3 /= __big;
373
            }
374
          else if (std::abs(__An) < _Tp(1) / __big
375
                || std::abs(__Bn) < _Tp(1) / __big)
376
            {
377
              __An   *= __big;
378
              __Bn   *= __big;
379
              __Anm1 *= __big;
380
              __Bnm1 *= __big;
381
              __Anm2 *= __big;
382
              __Bnm2 *= __big;
383
              __Anm3 *= __big;
384
              __Bnm3 *= __big;
385
            }
386
 
387
          ++__n;
388
          __Bnm3 = __Bnm2;
389
          __Bnm2 = __Bnm1;
390
          __Bnm1 = __Bn;
391
          __Anm3 = __Anm2;
392
          __Anm2 = __Anm1;
393
          __Anm1 = __An;
394
        }
395
 
396
      if (__n >= __nmax)
397
        std::__throw_runtime_error(__N("Iteration failed to converge "
398
                                       "in __hyperg_luke."));
399
 
400
      return __F;
401
    }
402
 
403
 
404
    /**
405
     *  @brief  Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$
406
     *  by the reflection formulae in Abramowitz & Stegun formula
407
     *  15.3.6 for d = c - a - b not integral and formula 15.3.11 for
408
     *  d = c - a - b integral.  This assumes a, b, c != negative
409
     *  integer.
410
     *
411
     *   The hypogeometric function is defined by
412
     *   @f[
413
     *     _2F_1(a,b;c;x) = \frac{\Gamma(c)}{\Gamma(a)\Gamma(b)}
414
     *                      \sum_{n=0}^{\infty}
415
     *                      \frac{\Gamma(a+n)\Gamma(b+n)}{\Gamma(c+n)}
416
     *                      \frac{x^n}{n!}
417
     *   @f]
418
     *
419
     *   The reflection formula for nonintegral @f$ d = c - a - b @f$ is:
420
     *   @f[
421
     *     _2F_1(a,b;c;x) = \frac{\Gamma(c)\Gamma(d)}{\Gamma(c-a)\Gamma(c-b)}
422
     *                            _2F_1(a,b;1-d;1-x)
423
     *                    + \frac{\Gamma(c)\Gamma(-d)}{\Gamma(a)\Gamma(b)}
424
     *                            _2F_1(c-a,c-b;1+d;1-x)
425
     *   @f]
426
     *
427
     *   The reflection formula for integral @f$ m = c - a - b @f$ is:
428
     *   @f[
429
     *     _2F_1(a,b;a+b+m;x) = \frac{\Gamma(m)\Gamma(a+b+m)}{\Gamma(a+m)\Gamma(b+m)}
430
     *                        \sum_{k=0}^{m-1} \frac{(m+a)_k(m+b)_k}{k!(1-m)_k}
431
     *                      -
432
     *   @f]
433
     */
434
    template
435
    _Tp
436
    __hyperg_reflect(const _Tp __a, const _Tp __b, const _Tp __c,
437
                     const _Tp __x)
438
    {
439
      const _Tp __d = __c - __a - __b;
440
      const int __intd  = std::floor(__d + _Tp(0.5L));
441
      const _Tp __eps = std::numeric_limits<_Tp>::epsilon();
442
      const _Tp __toler = _Tp(1000) * __eps;
443
      const _Tp __log_max = std::log(std::numeric_limits<_Tp>::max());
444
      const bool __d_integer = (std::abs(__d - __intd) < __toler);
445
 
446
      if (__d_integer)
447
        {
448
          const _Tp __ln_omx = std::log(_Tp(1) - __x);
449
          const _Tp __ad = std::abs(__d);
450
          _Tp __F1, __F2;
451
 
452
          _Tp __d1, __d2;
453
          if (__d >= _Tp(0))
454
            {
455
              __d1 = __d;
456
              __d2 = _Tp(0);
457
            }
458
          else
459
            {
460
              __d1 = _Tp(0);
461
              __d2 = __d;
462
            }
463
 
464
          const _Tp __lng_c = __log_gamma(__c);
465
 
466
          //  Evaluate F1.
467
          if (__ad < __eps)
468
            {
469
              //  d = c - a - b = 0.
470
              __F1 = _Tp(0);
471
            }
472
          else
473
            {
474
 
475
              bool __ok_d1 = true;
476
              _Tp __lng_ad, __lng_ad1, __lng_bd1;
477
              __try
478
                {
479
                  __lng_ad = __log_gamma(__ad);
480
                  __lng_ad1 = __log_gamma(__a + __d1);
481
                  __lng_bd1 = __log_gamma(__b + __d1);
482
                }
483
              __catch(...)
484
                {
485
                  __ok_d1 = false;
486
                }
487
 
488
              if (__ok_d1)
489
                {
490
                  /* Gamma functions in the denominator are ok.
491
                   * Proceed with evaluation.
492
                   */
493
                  _Tp __sum1 = _Tp(1);
494
                  _Tp __term = _Tp(1);
495
                  _Tp __ln_pre1 = __lng_ad + __lng_c + __d2 * __ln_omx
496
                                - __lng_ad1 - __lng_bd1;
497
 
498
                  /* Do F1 sum.
499
                   */
500
                  for (int __i = 1; __i < __ad; ++__i)
501
                    {
502
                      const int __j = __i - 1;
503
                      __term *= (__a + __d2 + __j) * (__b + __d2 + __j)
504
                              / (_Tp(1) + __d2 + __j) / __i * (_Tp(1) - __x);
505
                      __sum1 += __term;
506
                    }
507
 
508
                  if (__ln_pre1 > __log_max)
509
                    std::__throw_runtime_error(__N("Overflow of gamma functions"
510
                                                   " in __hyperg_luke."));
511
                  else
512
                    __F1 = std::exp(__ln_pre1) * __sum1;
513
                }
514
              else
515
                {
516
                  //  Gamma functions in the denominator were not ok.
517
                  //  So the F1 term is zero.
518
                  __F1 = _Tp(0);
519
                }
520
            } // end F1 evaluation
521
 
522
          // Evaluate F2.
523
          bool __ok_d2 = true;
524
          _Tp __lng_ad2, __lng_bd2;
525
          __try
526
            {
527
              __lng_ad2 = __log_gamma(__a + __d2);
528
              __lng_bd2 = __log_gamma(__b + __d2);
529
            }
530
          __catch(...)
531
            {
532
              __ok_d2 = false;
533
            }
534
 
535
          if (__ok_d2)
536
            {
537
              //  Gamma functions in the denominator are ok.
538
              //  Proceed with evaluation.
539
              const int __maxiter = 2000;
540
              const _Tp __psi_1 = -__numeric_constants<_Tp>::__gamma_e();
541
              const _Tp __psi_1pd = __psi(_Tp(1) + __ad);
542
              const _Tp __psi_apd1 = __psi(__a + __d1);
543
              const _Tp __psi_bpd1 = __psi(__b + __d1);
544
 
545
              _Tp __psi_term = __psi_1 + __psi_1pd - __psi_apd1
546
                             - __psi_bpd1 - __ln_omx;
547
              _Tp __fact = _Tp(1);
548
              _Tp __sum2 = __psi_term;
549
              _Tp __ln_pre2 = __lng_c + __d1 * __ln_omx
550
                            - __lng_ad2 - __lng_bd2;
551
 
552
              // Do F2 sum.
553
              int __j;
554
              for (__j = 1; __j < __maxiter; ++__j)
555
                {
556
                  //  Values for psi functions use recurrence;
557
                  //  Abramowitz & Stegun 6.3.5
558
                  const _Tp __term1 = _Tp(1) / _Tp(__j)
559
                                    + _Tp(1) / (__ad + __j);
560
                  const _Tp __term2 = _Tp(1) / (__a + __d1 + _Tp(__j - 1))
561
                                    + _Tp(1) / (__b + __d1 + _Tp(__j - 1));
562
                  __psi_term += __term1 - __term2;
563
                  __fact *= (__a + __d1 + _Tp(__j - 1))
564
                          * (__b + __d1 + _Tp(__j - 1))
565
                          / ((__ad + __j) * __j) * (_Tp(1) - __x);
566
                  const _Tp __delta = __fact * __psi_term;
567
                  __sum2 += __delta;
568
                  if (std::abs(__delta) < __eps * std::abs(__sum2))
569
                    break;
570
                }
571
              if (__j == __maxiter)
572
                std::__throw_runtime_error(__N("Sum F2 failed to converge "
573
                                               "in __hyperg_reflect"));
574
 
575
              if (__sum2 == _Tp(0))
576
                __F2 = _Tp(0);
577
              else
578
                __F2 = std::exp(__ln_pre2) * __sum2;
579
            }
580
          else
581
            {
582
              // Gamma functions in the denominator not ok.
583
              // So the F2 term is zero.
584
              __F2 = _Tp(0);
585
            } // end F2 evaluation
586
 
587
          const _Tp __sgn_2 = (__intd % 2 == 1 ? -_Tp(1) : _Tp(1));
588
          const _Tp __F = __F1 + __sgn_2 * __F2;
589
 
590
          return __F;
591
        }
592
      else
593
        {
594
          //  d = c - a - b not an integer.
595
 
596
          //  These gamma functions appear in the denominator, so we
597
          //  catch their harmless domain errors and set the terms to zero.
598
          bool __ok1 = true;
599
          _Tp __sgn_g1ca = _Tp(0), __ln_g1ca = _Tp(0);
600
          _Tp __sgn_g1cb = _Tp(0), __ln_g1cb = _Tp(0);
601
          __try
602
            {
603
              __sgn_g1ca = __log_gamma_sign(__c - __a);
604
              __ln_g1ca = __log_gamma(__c - __a);
605
              __sgn_g1cb = __log_gamma_sign(__c - __b);
606
              __ln_g1cb = __log_gamma(__c - __b);
607
            }
608
          __catch(...)
609
            {
610
              __ok1 = false;
611
            }
612
 
613
          bool __ok2 = true;
614
          _Tp __sgn_g2a = _Tp(0), __ln_g2a = _Tp(0);
615
          _Tp __sgn_g2b = _Tp(0), __ln_g2b = _Tp(0);
616
          __try
617
            {
618
              __sgn_g2a = __log_gamma_sign(__a);
619
              __ln_g2a = __log_gamma(__a);
620
              __sgn_g2b = __log_gamma_sign(__b);
621
              __ln_g2b = __log_gamma(__b);
622
            }
623
          __catch(...)
624
            {
625
              __ok2 = false;
626
            }
627
 
628
          const _Tp __sgn_gc = __log_gamma_sign(__c);
629
          const _Tp __ln_gc = __log_gamma(__c);
630
          const _Tp __sgn_gd = __log_gamma_sign(__d);
631
          const _Tp __ln_gd = __log_gamma(__d);
632
          const _Tp __sgn_gmd = __log_gamma_sign(-__d);
633
          const _Tp __ln_gmd = __log_gamma(-__d);
634
 
635
          const _Tp __sgn1 = __sgn_gc * __sgn_gd  * __sgn_g1ca * __sgn_g1cb;
636
          const _Tp __sgn2 = __sgn_gc * __sgn_gmd * __sgn_g2a  * __sgn_g2b;
637
 
638
          _Tp __pre1, __pre2;
639
          if (__ok1 && __ok2)
640
            {
641
              _Tp __ln_pre1 = __ln_gc + __ln_gd  - __ln_g1ca - __ln_g1cb;
642
              _Tp __ln_pre2 = __ln_gc + __ln_gmd - __ln_g2a  - __ln_g2b
643
                            + __d * std::log(_Tp(1) - __x);
644
              if (__ln_pre1 < __log_max && __ln_pre2 < __log_max)
645
                {
646
                  __pre1 = std::exp(__ln_pre1);
647
                  __pre2 = std::exp(__ln_pre2);
648
                  __pre1 *= __sgn1;
649
                  __pre2 *= __sgn2;
650
                }
651
              else
652
                {
653
                  std::__throw_runtime_error(__N("Overflow of gamma functions "
654
                                                 "in __hyperg_reflect"));
655
                }
656
            }
657
          else if (__ok1 && !__ok2)
658
            {
659
              _Tp __ln_pre1 = __ln_gc + __ln_gd - __ln_g1ca - __ln_g1cb;
660
              if (__ln_pre1 < __log_max)
661
                {
662
                  __pre1 = std::exp(__ln_pre1);
663
                  __pre1 *= __sgn1;
664
                  __pre2 = _Tp(0);
665
                }
666
              else
667
                {
668
                  std::__throw_runtime_error(__N("Overflow of gamma functions "
669
                                                 "in __hyperg_reflect"));
670
                }
671
            }
672
          else if (!__ok1 && __ok2)
673
            {
674
              _Tp __ln_pre2 = __ln_gc + __ln_gmd - __ln_g2a - __ln_g2b
675
                            + __d * std::log(_Tp(1) - __x);
676
              if (__ln_pre2 < __log_max)
677
                {
678
                  __pre1 = _Tp(0);
679
                  __pre2 = std::exp(__ln_pre2);
680
                  __pre2 *= __sgn2;
681
                }
682
              else
683
                {
684
                  std::__throw_runtime_error(__N("Overflow of gamma functions "
685
                                                 "in __hyperg_reflect"));
686
                }
687
            }
688
          else
689
            {
690
              __pre1 = _Tp(0);
691
              __pre2 = _Tp(0);
692
              std::__throw_runtime_error(__N("Underflow of gamma functions "
693
                                             "in __hyperg_reflect"));
694
            }
695
 
696
          const _Tp __F1 = __hyperg_series(__a, __b, _Tp(1) - __d,
697
                                           _Tp(1) - __x);
698
          const _Tp __F2 = __hyperg_series(__c - __a, __c - __b, _Tp(1) + __d,
699
                                           _Tp(1) - __x);
700
 
701
          const _Tp __F = __pre1 * __F1 + __pre2 * __F2;
702
 
703
          return __F;
704
        }
705
    }
706
 
707
 
708
    /**
709
     *   @brief Return the hypogeometric function @f$ _2F_1(a,b;c;x) @f$.
710
     *
711
     *   The hypogeometric function is defined by
712
     *   @f[
713
     *     _2F_1(a,b;c;x) = \frac{\Gamma(c)}{\Gamma(a)\Gamma(b)}
714
     *                      \sum_{n=0}^{\infty}
715
     *                      \frac{\Gamma(a+n)\Gamma(b+n)}{\Gamma(c+n)}
716
     *                      \frac{x^n}{n!}
717
     *   @f]
718
     *
719
     *   @param  __a  The first @a numerator parameter.
720
     *   @param  __a  The second @a numerator parameter.
721
     *   @param  __c  The @a denominator parameter.
722
     *   @param  __x  The argument of the confluent hypergeometric function.
723
     *   @return  The confluent hypergeometric function.
724
     */
725
    template
726
    inline _Tp
727
    __hyperg(const _Tp __a, const _Tp __b, const _Tp __c, const _Tp __x)
728
    {
729
#if _GLIBCXX_USE_C99_MATH_TR1
730
      const _Tp __a_nint = std::tr1::nearbyint(__a);
731
      const _Tp __b_nint = std::tr1::nearbyint(__b);
732
      const _Tp __c_nint = std::tr1::nearbyint(__c);
733
#else
734
      const _Tp __a_nint = static_cast(__a + _Tp(0.5L));
735
      const _Tp __b_nint = static_cast(__b + _Tp(0.5L));
736
      const _Tp __c_nint = static_cast(__c + _Tp(0.5L));
737
#endif
738
      const _Tp __toler = _Tp(1000) * std::numeric_limits<_Tp>::epsilon();
739
      if (std::abs(__x) >= _Tp(1))
740
        std::__throw_domain_error(__N("Argument outside unit circle "
741
                                      "in __hyperg."));
742
      else if (__isnan(__a) || __isnan(__b)
743
            || __isnan(__c) || __isnan(__x))
744
        return std::numeric_limits<_Tp>::quiet_NaN();
745
      else if (__c_nint == __c && __c_nint <= _Tp(0))
746
        return std::numeric_limits<_Tp>::infinity();
747
      else if (std::abs(__c - __b) < __toler || std::abs(__c - __a) < __toler)
748
        return std::pow(_Tp(1) - __x, __c - __a - __b);
749
      else if (__a >= _Tp(0) && __b >= _Tp(0) && __c >= _Tp(0)
750
            && __x >= _Tp(0) && __x < _Tp(0.995L))
751
        return __hyperg_series(__a, __b, __c, __x);
752
      else if (std::abs(__a) < _Tp(10) && std::abs(__b) < _Tp(10))
753
        {
754
          //  For integer a and b the hypergeometric function is a
755
          //  finite polynomial.
756
          if (__a < _Tp(0)  &&  std::abs(__a - __a_nint) < __toler)
757
            return __hyperg_series(__a_nint, __b, __c, __x);
758
          else if (__b < _Tp(0)  &&  std::abs(__b - __b_nint) < __toler)
759
            return __hyperg_series(__a, __b_nint, __c, __x);
760
          else if (__x < -_Tp(0.25L))
761
            return __hyperg_luke(__a, __b, __c, __x);
762
          else if (__x < _Tp(0.5L))
763
            return __hyperg_series(__a, __b, __c, __x);
764
          else
765
            if (std::abs(__c) > _Tp(10))
766
              return __hyperg_series(__a, __b, __c, __x);
767
            else
768
              return __hyperg_reflect(__a, __b, __c, __x);
769
        }
770
      else
771
        return __hyperg_luke(__a, __b, __c, __x);
772
    }
773
 
774
  _GLIBCXX_END_NAMESPACE_VERSION
775
  } // namespace std::tr1::__detail
776
}
777
}
778
 
779
#endif // _GLIBCXX_TR1_HYPERGEOMETRIC_TCC

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.