static void SamplesAlloc(cThis *t, Samples *samples) { #define FIRST -INT_MAX #define MarkLast(x) (x | Marked(INT_MAX)) #include "KorobovCoeff.c" number nx, nf; if( samples->sampler == SampleKorobov ) { enum { max = Elements(prime) - 2 }; cint n = IMin(2*samples->n - 1, MAXPRIME); int i = Hash(n), p; count shift = 2 + NegQ(n - 1000); while( i = IMin(IDim(i), max), n > (p = prime[i + 1]) || n <= prime[i] ) { cint d = (n - Unmark(p)) >> ++shift; i += Min1(d); } samples->coeff = coeff[i][t->ndim - KOROBOV_MINDIM]; samples->neff = p = Unmark(p); samples->n = p/2 + 1; } nx = t->ndim*(samples->n + 1); /* need 1 for extrapolation */ nf = t->ncomp*(samples->n + 1); Alloc(samples->x, nx + nf + t->ncomp + t->ncomp); samples->f = samples->x + nx; }
static void RefineGrid(cThis *t, Grid grid, Grid margsum) { real avgperbin, thisbin, newcur, delta; Grid imp, newgrid; int bin, newbin; /* smooth the f^2 value stored for each bin */ real prev = margsum[0]; real cur = margsum[1]; real norm = margsum[0] = .5*(prev + cur); for( bin = 1; bin < NBINS - 1; ++bin ) { creal s = prev + cur; prev = cur; cur = margsum[bin + 1]; norm += margsum[bin] = (s + cur)/3.; } norm += margsum[NBINS - 1] = .5*(prev + cur); if( norm == 0 ) return; norm = 1/norm; /* compute the importance function for each bin */ avgperbin = 0; for( bin = 0; bin < NBINS; ++bin ) { real impfun = 0; if( margsum[bin] > 0 ) { creal r = margsum[bin]*norm; avgperbin += impfun = powx((r - 1)/log(r), 1.5); } imp[bin] = impfun; } avgperbin /= NBINS; /* redefine the size of each bin */ cur = newcur = 0; thisbin = 0; bin = -1; for( newbin = 0; newbin < NBINS - 1; ++newbin ) { while( thisbin < avgperbin ) { thisbin += imp[++bin]; prev = cur; cur = grid[bin]; } thisbin -= avgperbin; delta = (cur - prev)*thisbin; newgrid[newbin] = SHARPEDGES ? cur - delta/imp[bin] : (newcur = Max(newcur + 16*DBL_EPSILON, cur - 2*delta/(imp[bin] + imp[IDim(bin - 1)]))); } Copy(grid, newgrid, NBINS - 1); grid[NBINS - 1] = 1; }
static count SamplesLookup(Samples *samples, int key, ccount nwant, ccount nmax, count nmin) { count n; if( key == 13 && ndim_ == 2 ) { if( rule13_.first == NULL ) Rule13Alloc(&rule13_); samples->rule = &rule13_; samples->n = n = nmin = rule13_.n; samples->sampler = SampleRule; } else if( key == 11 && ndim_ == 3 ) { if( rule11_.first == NULL ) Rule11Alloc(&rule11_); samples->rule = &rule11_; samples->n = n = nmin = rule11_.n; samples->sampler = SampleRule; } else if( key == 9 ) { if( rule9_.first == NULL ) Rule9Alloc(&rule9_); samples->rule = &rule9_; samples->n = n = nmin = rule9_.n; samples->sampler = SampleRule; } else if( key == 7 ) { if( rule7_.first == NULL ) Rule7Alloc(&rule7_); samples->rule = &rule7_; samples->n = n = nmin = rule7_.n; samples->sampler = SampleRule; } else { n = Abs1(key); if( n < 40 ) n *= nwant; samples->sampler = (key < 0) ? SampleSobol : (n = n/2 + 1, SampleKorobov); samples->n = IMin(n, nmax); } samples->neff = samples->n; return IDim(n - nmax) | Marked(nmax - nmin); }
static count SamplesLookup(This *t, Samples *samples, cint key, cnumber nwant, cnumber nmax, number nmin) { number n; if( key == 13 && t->ndim == 2 ) { samples->rule = &t->rule13; samples->n = n = nmin = t->rule13.n; samples->sampler = SampleRule; } else if( key == 11 && t->ndim == 3 ) { samples->rule = &t->rule11; samples->n = n = nmin = t->rule11.n; samples->sampler = SampleRule; } else if( key == 9 ) { samples->rule = &t->rule9; samples->n = n = nmin = t->rule9.n; samples->sampler = SampleRule; } else if( key == 7 ) { samples->rule = &t->rule7; samples->n = n = nmin = t->rule7.n; samples->sampler = SampleRule; } else { n = Abs1(key); if( n < 40 ) n *= nwant; samples->sampler = (key < 0) ? SampleSobol : (n = n/2 + 1, SampleKorobov); samples->n = IMin(n, nmax); } samples->neff = samples->n; return IDim(n - nmax) | Marked(nmax - nmin); }
static void SamplesAlloc(Samples *samples) { #define FIRST -INT_MAX #define MarkLast(x) (x | Marked(INT_MAX)) #include "KorobovCoeff.c" count nx, nf; if( samples->sampler == SampleKorobov ) { enum { max = Elements(prime) - 2 }; cint n = IMin(2*samples->n - 1, MAXPRIME); int i = Hash(n), p; count shift = 2 + NegQ(n - 1000); while( i = IMin(IDim(i), max), n > (p = prime[i + 1]) || n <= prime[i] ) { cint d = (n - Unmark(p)) >> ++shift; i += Min1(d); } samples->coeff = coeff[i][ndim_ - KOROBOV_MINDIM]; samples->neff = p = Unmark(p); samples->n = p/2 + 1; } nx = ndim_*(samples->n + 1); /* need 1 for extrapolation */ nf = ncomp_*(samples->n + 1); Allocate(samples->x, nx + nf + ncomp_ + ncomp_); samples->f = samples->x + nx; samples->avg = samples->f + nf; samples->err = samples->avg + ncomp_; ResClear(samples->err); samples->weight = 1./samples->neff; }
Integer cachelookup(const Real *para, double *base, void (*calc)(const Real *, Real *, const long *), const int *pnpara, const int *pnval) { const long one = 1; const Integer C_size = sizeof(Complex); const int npara = *pnpara, nval = *pnval; typedef struct node { struct node *next[2], *succ; int serial; Real para[2]; } Node; #define base_valid (int *)&base[0] #define base_last (Node ***)&base[1] #define base_first (Node **)&base[2] const int valid = *base_valid; Node **last = *base_last; Node **next = base_first; Node *node; if( last == NULL ) last = next; if( ltcache.cmpbits > 0 ) { dblint mask = -(1ULL << IDim(64 - ltcache.cmpbits)); #if KIND == 2 dblint (*cmp)(const Real *, const Real *, int, const dblint) = CmpPara; if( ltcache.cmpbits >= 64 ) { mask = -(1ULL << IDim(128 - ltcache.cmpbits)); cmp = CmpParaLo; } #else #define cmp CmpPara #endif while( (node = *next) && node->serial < valid ) { const dblint i = cmp(para, node->para, npara, mask); if( i == 0 ) { goto found; } next = &node->next[SignBit(i)]; } } node = *last; if( node == NULL ) { /* The "Real para[2]" bit in Node is effectively an extra Complex for alignment so that node can be reached with an integer index into base */ node = malloc(sizeof(Node) + npara*sizeof(Real) + nval*sizeof(Complex)); if( node == NULL ) { fputs("Out of memory for LoopTools cache.\n", stderr); exit(1); } node = (Node *)((char *)node + (PtrDiff(base, &node->para[npara]) & (sizeof(Complex) - 1))); node->succ = NULL; node->serial = valid; *last = node; } *next = node; *base_last = &node->succ; *base_valid = valid + 1; node->next[0] = NULL; node->next[1] = NULL; memcpy(node->para, para, npara*sizeof(Real)); calc(node->para, &node->para[npara], &one); found: return PtrDiff(&node->para[npara], base)/C_size; }
static inline int IMax(cint a, cint b) { /* return (a > b) ? a : b; */ return b + IDim(a - b); }
static inline int IMin(cint a, cint b) { /* return (a < b) ? a : b; */ return a - IDim(a - b); }
static bool Explore(count iregion, cSamples *samples, cint depth, cint flags) { #define SPLICE (flags & 1) #define HAVESAMPLES (flags & 2) TYPEDEFREGION; count n, dim, comp, maxcomp; Extrema extrema[NCOMP]; Result *r; real *x, *f; real halfvol, maxerr; Region *region; Bounds *bounds; Result *result; /* needed as of gcc 3.3 to make gcc correctly address region #@$&! */ sizeof(*region); if( SPLICE ) { if( nregions_ == size_ ) { size_ += CHUNKSIZE; ReAlloc(voidregion_, size_*sizeof(Region)); } VecCopy(region_[nregions_].bounds, region_[iregion].bounds); iregion = nregions_++; } region = ®ion_[iregion]; bounds = region->bounds; result = region->result; for( comp = 0; comp < ncomp_; ++comp ) { Extrema *e = &extrema[comp]; e->fmin = INFTY; e->fmax = -INFTY; e->xmin = e->xmax = NULL; } if( !HAVESAMPLES ) { real vol = 1; for( dim = 0; dim < ndim_; ++dim ) { cBounds *b = &bounds[dim]; vol *= b->upper - b->lower; } region->vol = vol; for( comp = 0; comp < ncomp_; ++comp ) { Result *r = &result[comp]; r->fmin = INFTY; r->fmax = -INFTY; } x = xgiven_; f = fgiven_; n = ngiven_; if( nextra_ ) n += SampleExtra(bounds); for( ; n; --n ) { for( dim = 0; dim < ndim_; ++dim ) { cBounds *b = &bounds[dim]; if( x[dim] < b->lower || x[dim] > b->upper ) goto skip; } for( comp = 0; comp < ncomp_; ++comp ) { Extrema *e = &extrema[comp]; creal y = f[comp]; if( y < e->fmin ) e->fmin = y, e->xmin = x; if( y > e->fmax ) e->fmax = y, e->xmax = x; } skip: x += ldxgiven_; f += ncomp_; } samples->sampler(samples, bounds, vol); } x = samples->x; f = samples->f; for( n = samples->n; n; --n ) { for( comp = 0; comp < ncomp_; ++comp ) { Extrema *e = &extrema[comp]; creal y = *f++; if( y < e->fmin ) e->fmin = y, e->xmin = x; if( y > e->fmax ) e->fmax = y, e->xmax = x; } x += ndim_; } neval_opt_ -= neval_; halfvol = .5*region->vol; maxerr = -INFTY; maxcomp = -1; for( comp = 0; comp < ncomp_; ++comp ) { Extrema *e = &extrema[comp]; Result *r = &result[comp]; real xtmp[NDIM], ftmp, err; if( e->xmin ) { /* not all NaNs */ selectedcomp_ = comp; sign_ = 1; VecCopy(xtmp, e->xmin); ftmp = FindMinimum(bounds, xtmp, e->fmin); if( ftmp < r->fmin ) { r->fmin = ftmp; VecCopy(r->xmin, xtmp); } sign_ = -1; VecCopy(xtmp, e->xmax); ftmp = -FindMinimum(bounds, xtmp, -e->fmax); if( ftmp > r->fmax ) { r->fmax = ftmp; VecCopy(r->xmax, xtmp); } } r->avg = samples->avg[comp]; r->err = samples->err[comp]; r->spread = halfvol*(r->fmax - r->fmin); err = r->spread/Max(fabs(r->avg), NOTZERO); if( err > maxerr ) { maxerr = err; maxcomp = comp; } } neval_opt_ += neval_; if( maxcomp == -1 ) { /* all NaNs */ region->depth = 0; return false; } region->cutcomp = maxcomp; r = ®ion->result[maxcomp]; if( halfvol*(r->fmin + r->fmax) > r->avg ) { region->fminor = r->fmin; region->fmajor = r->fmax; region->xmajor = r->xmax - (real *)region->result; } else { region->fminor = r->fmax; region->fmajor = r->fmin; region->xmajor = r->xmin - (real *)region->result; } region->depth = IDim(depth); if( !HAVESAMPLES ) { if( samples->weight*r->spread < r->err || r->spread < totals_[maxcomp].secondspread ) region->depth = 0; if( region->depth == 0 ) for( comp = 0; comp < ncomp_; ++comp ) totals_[comp].secondspread = Max(totals_[comp].secondspread, result[comp].spread); } if( region->depth ) Split(iregion, region->depth); return true; }