aboutsummaryrefslogtreecommitdiff
(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))