AcouSTO  version 2.0

◆ ruleadapt_integrate()

static int ruleadapt_integrate ( rule r,
unsigned  fdim,
integrand_v  f,
void *  fdata,
const hypercube h,
unsigned  maxEval,
double  reqAbsError,
double  reqRelError,
double *  val,
double *  err,
int  parallel 
)
static
886 {
887  unsigned numEval = 0;
888  heap regions;
889  unsigned i, j;
890  region *R = NULL; /* array of regions to evaluate */
891  unsigned nR_alloc = 0;
892  esterr *ee = NULL;
893 
894  regions = heap_alloc(1, fdim);
895  if (!regions.ee || !regions.items) goto bad;
896 
897  ee = (esterr *) malloc(sizeof(esterr) * fdim);
898  if (!ee) goto bad;
899 
900  nR_alloc = 2;
901  R = (region *) malloc(sizeof(region) * nR_alloc);
902  if (!R) goto bad;
903  R[0] = make_region(h, fdim);
904  if (!R[0].ee
905  || eval_regions(1, R, f, fdata, r)
906  || heap_push(&regions, R[0]))
907  goto bad;
908  numEval += r->num_points;
909 
910  while (numEval < maxEval || !maxEval) {
911  for (j = 0; j < fdim && (regions.ee[j].err <= reqAbsError
912  || relError(regions.ee[j]) <= reqRelError);
913  ++j) ;
914  if (j == fdim)
915  break; /* convergence */
916 
917  if (parallel) { /* maximize potential parallelism */
918  /* adapted from I. Gladwell, "Vectorization of one
919  dimensional quadrature codes," pp. 230--238 in
920  _Numerical Integration. Recent Developments,
921  Software and Applications_, G. Fairweather and
922  P. M. Keast, eds., NATO ASI Series C203, Dordrecht
923  (1987), as described in J. M. Bull and
924  T. L. Freeman, "Parallel Globally Adaptive
925  Algorithms for Multi-dimensional Integration,"
926  http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.42.6638
927  (1994).
928 
929  Basically, this evaluates in one shot all regions
930  that *must* be evaluated in order to reduce the
931  error to the requested bound: the minimum set of
932  largest-error regions whose errors push the total
933  error over the bound.
934 
935  [Note: Bull and Freeman claim that the Gladwell
936  approach is intrinsically inefficent because it
937  "requires sorting", and propose an alternative
938  algorithm that "only" requires three passes over the
939  entire set of regions. Apparently, they didn't
940  realize that one could use a heap data structure, in
941  which case the time to pop K biggest-error regions
942  out of N is only O(K log N), much better than the
943  O(N) cost of the Bull and Freeman algorithm if K <<
944  N, and it is also much simpler.] */
945  unsigned nR = 0;
946  for (j = 0; j < fdim; ++j) ee[j] = regions.ee[j];
947  do {
948  if (nR + 2 > nR_alloc) {
949  nR_alloc = (nR + 2) * 2;
950  R = (region *) realloc(R, nR_alloc * sizeof(region));
951  if (!R) goto bad;
952  }
953  R[nR] = heap_pop(&regions);
954  for (j = 0; j < fdim; ++j) ee[j].err -= R[nR].ee[j].err;
955  if (cut_region(R+nR, R+nR+1)) goto bad;
956  numEval += r->num_points * 2;
957  nR += 2;
958  for (j = 0; j < fdim
959  && (ee[j].err <= reqAbsError
960  || relError(ee[j]) <= reqRelError); ++j) ;
961  if (j == fdim) break; /* other regions have small errs */
962  } while (regions.n > 0 && (numEval < maxEval || !maxEval));
963  if (eval_regions(nR, R, f, fdata, r)
964  || heap_push_many(&regions, nR, R))
965  goto bad;
966  }
967  else { /* minimize number of function evaluations */
968  R[0] = heap_pop(&regions); /* get worst region */
969  if (cut_region(R, R+1)
970  || eval_regions(2, R, f, fdata, r)
971  || heap_push_many(&regions, 2, R))
972  goto bad;
973  numEval += r->num_points * 2;
974  }
975  }
976 
977  /* re-sum integral and errors */
978  for (j = 0; j < fdim; ++j) val[j] = err[j] = 0;
979  for (i = 0; i < regions.n; ++i) {
980  for (j = 0; j < fdim; ++j) {
981  val[j] += regions.items[i].ee[j].val;
982  err[j] += regions.items[i].ee[j].err;
983  }
984  destroy_region(&regions.items[i]);
985  }
986 
987  /* printf("regions.nalloc = %d\n", regions.nalloc); */
988  free(ee);
989  heap_free(&regions);
990  free(R);
991  return SUCCESS;
992 
993 bad:
994  free(ee);
995  heap_free(&regions);
996  free(R);
997  return FAILURE;
998 }
static void heap_free(heap *h)
Definition: cubature.c:800
static double relError(esterr ee)
Definition: cubature.c:119
#define SUCCESS
Definition: cubature.c:109
Definition: cubature.c:115
unsigned num_points
Definition: cubature.c:234
static heap heap_alloc(unsigned nalloc, unsigned fdim)
Definition: cubature.c:783
static int cut_region(region *R, region *R2)
Definition: cubature.c:210
esterr * ee
Definition: cubature.c:774
static heap_item heap_pop(heap *h)
Definition: cubature.c:842
static int heap_push(heap *h, heap_item hi)
Definition: cubature.c:808
static int heap_push_many(heap *h, unsigned ni, heap_item *hi)
Definition: cubature.c:834
double err
Definition: cubature.c:116
unsigned n
Definition: cubature.c:771
double val
Definition: cubature.c:116
static region make_region(const hypercube *h, unsigned fdim)
Definition: cubature.c:193
#define malloc(size)
Definition: allocation.h:38
static void destroy_region(region *R)
Definition: cubature.c:203
#define FAILURE
Definition: cubature.c:110
Definition: cubature.c:770
heap_item * items
Definition: cubature.c:772
Definition: cubature.c:185
esterr * ee
Definition: cubature.c:189
static int eval_regions(unsigned nR, region *R, integrand_v f, void *fdata, rule *r)
Definition: cubature.c:289