-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgamma.C
90 lines (67 loc) · 1.94 KB
/
gamma.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
* gamma.C
*
* High-precison Gamma function, using the
* Gnu Multiple-precision library.
*
* Linas Vepstas December 2006
*/
#include <gmp.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "brat.h"
#include "coord-xforms.h"
#include "../experiments/bignum/zmp.h"
/* ======================================================================= */
static cpx_t gam, z;
static int prec;
static void psi_init (void)
{
/* the decimal precison (number of decimal places) */
prec = 40;
/* compute number of binary bits this corresponds to. */
double v = ((double) prec) *log(10.0) / log(2.0);
/* the variable-precision calculations are touchy about this */
/* XXX this should be stirling's approx for binomial */
int bits = (int) (v + 30);
/* Set the precision (number of binary bits) */
mpf_set_default_prec (bits);
cpx_init (gam);
cpx_init (z);
}
static double cgamma (double re_q, double im_q, int itermax, double param)
{
static int init = 0;
if (!init) {psi_init(); init=1; }
#if 0
// double mag = 1.0 - sqrt (re_q*re_q + im_q*im_q);
double mag = 1.0 - (re_q*re_q + im_q*im_q);
if (mag <= 0.03) return 0.0;
double re_z = re_q / mag;
double im_z = im_q / mag;
#endif
double re_z = re_q;
double im_z = im_q;
#define USE_POINCARE_DISK
#ifdef USE_POINCARE_DISK
double mag = (re_q*re_q + im_q*im_q);
if ((mag >= 0.995) && (mag <=1.005)) return 0.0;
poincare_disk_to_plane_coords (re_q, im_q, &re_z, &im_z);
#endif
/* avoid hang evaluating near infty */
mag = (re_z*re_z + im_z*im_z);
if (mag >= 10100.97) return 0.0;
cpx_set_d (z, re_z, im_z);
// printf ("duude compute %g %g \n", re_z, im_z);
cpx_gamma (gam, z, prec);
// cpx_exp (gam, z, prec);
double frea = mpf_get_d (gam[0].re);
double fima = mpf_get_d (gam[0].im);
double phase = atan2 (fima, frea);
phase += M_PI;
phase /= 2.0*M_PI;
return phase;
}
DECL_MAKE_HEIGHT(cgamma);
/* --------------------------- END OF LIFE ------------------------- */