aboutsummaryrefslogtreecommitdiff
path: root/src/integral.sc
blob: fa3d7a67275df3f3d35cd57e0ec2f1fa7c1d5361 (plain)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
(sc-include "macros/macros")

(pre-include "gsl/gsl_poly.h")
(pre-include "gsl/gsl_sf.h")
(pre-include "extent-sampling.h")
(pre-include "oracles.h")
(pre-include "integrands.h")
(pre-include "utils.h")

(pre-define TRIALS 1000)
(pre-define MAX-EXTENT 1.0)

(sc-define-syntax* (define-polynomial var)
  (let ((coefficients (list -0.09375 0.6875 -1.5 1))
        (coeff (sc-gensym)))
    `(begin
       (declare ,coeff (array double ,(length coefficients)))
       (array-set* ,coeff ,@coefficients)
       (declare ,var (struct-variable polynomial-integrand-params
                                      (coefficients ,coeff)
                                      (degree ,(1- (length coefficients))))))))

(sc-define-syntax (polynomial-map! polynomial i coeff form)
  (for-i i (+ 1 (struct-get polynomial degree))
    (let* ((coeff double (array-get (struct-get polynomial coefficients)
                                    i)))
      (array-set (convert-type (struct-get polynomial coefficients)
                               double*)
                 i form))))

(define (polyval polynomial value) (double polynomial-integrand-params double)
  (return (gsl-poly-eval (struct-get polynomial coefficients)
                         (+ 1 (struct-get polynomial degree))
                         value)))

(sc-define-syntax* (define-polynomial-integrand integrand)
  (let ((params (sc-gensym)))
    `(begin
       (define-polynomial ,params)
       (declare ,integrand (struct-variable (const integrand-t)
                                            (integrand polynomial-integrand)
                                            (params (address-of ,params)))))))

(sc-define-syntax* (define-uniform-extent-oracle oracle a b)
  (let ((oracle-params (sc-gensym)))
    `(begin
       (declare ,oracle-params (struct-variable uniform-params
                                                (a ,a)
                                                (b ,b)))
       (declare ,oracle (struct-variable extent-oracle-t
                                         (oracle uniform-extent-oracle)
                                         (params (address-of ,oracle-params)))))))

(sc-define-syntax* (experiment integrand true-integral filename)
  (let ((rtols (list 0.2 0.1 0.05)))
    `(begin
       ,@(map (lambda (i rtol)
                `(begin
                   (with-data-file fp ,(format #f "integral-~a-~a.dat" filename rtol) "w"
                     (fprintf fp "dimension\tsamples\n"))))
              (iota (length rtols))
              rtols)
       (for-i-step dimension 10 100 10
         (printf "Dimension %d: " dimension)
         (with-rstats* samples ,(length rtols)
           (for-i trial TRIALS
             (with-rstats stats
               ,@(map (lambda (i rtol)
                        `(begin
                           (integral (address-of ,integrand)
                                     (address-of oracle)
                                     (,true-integral dimension)
                                     rng
                                     dimension
                                     ,rtol
                                     stats)
                           (gsl-rstat-add (gsl-rstat-n stats)
                                          (array-get samples ,i))))
                      (iota (length rtols))
                      rtols))
             (when (= (modulo trial (/ TRIALS 10)) 0)
               (printf "%d " trial))
             (fflush NULL))
           (printf "\n")
           ,@(map (lambda (i rtol)
                    `(with-data-file fp ,(format #f "integral-~a-~a.dat" filename rtol) "a"
                       (fprintf fp "%d\t%g\n" dimension (gsl-rstat-mean (array-get samples ,i)))))
                  (iota (length rtols))
                  rtols))))))

(define (true-polynomial-integral dimension)
  (double (unsigned int))
  (define-polynomial polynomial)
  (polynomial-map! polynomial k coeff
    (/ coeff (+ dimension k) (+ dimension k 1)))
  (return (* (surface-area-of-ball dimension)
             (gsl-pow-uint MAX-EXTENT dimension)
             (polyval polynomial MAX-EXTENT))))

(define (lower-incomplete-gamma s x)
  (double double double)
  (return (* (gsl-sf-gamma s)
             (gsl-sf-gamma-inc-P s x))))

(define (true-gaussian-integral dimension)
  (double (unsigned int))
  (return (/ (* (pow 2.0 (- (* dimension 0.5) 1))
                (surface-area-of-ball dimension)
                (- (* MAX-EXTENT
                      (lower-incomplete-gamma (* 0.5 dimension)
                                              (* 0.5 (gsl-pow-2 MAX-EXTENT))))
                   (* (sqrt 2.0)
                      (lower-incomplete-gamma (* 0.5 (+ dimension 1))
                                              (* 0.5 (gsl-pow-2 MAX-EXTENT))))))
             MAX-EXTENT)))

(define (true-x-coordinate-integral dimension)
  (double (unsigned int))
  (return (/ (* (gsl-pow-uint MAX-EXTENT (1+ dimension))
                (surface-area-of-ball (+ dimension 3)))
             2.0
             (pow M-PI 2)
             (+ dimension 2))))

(define (main) (int)
  (define-polynomial-integrand -polynomial-integrand)
  (declare -gaussian-integrand (struct-variable (const integrand-t)
                                                gaussian-integrand
                                                NULL))
  (declare -x-coordinate-integrand (struct-variable (const integrand-t)
                                                    x-coordinate-integrand
                                                    NULL))
  (define-uniform-extent-oracle oracle 0 MAX-EXTENT)
  (with-rng rng
    (experiment -polynomial-integrand true-polynomial-integral "polynomial")
    (experiment -gaussian-integrand true-gaussian-integral "gaussian")
    (experiment -x-coordinate-integrand true-x-coordinate-integral "x-coordinate"))
  (with-data-file fp "integral-parameters.tex" "w"
    (fprintf fp "\\\\newcommand{\\\\integraltrials}{%d}\n" TRIALS))
  (return 0))