LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
Classes | Functions
lsst::afw::math::details Namespace Reference

Classes

struct  AuxFunc1
 Auxiliary struct 1. More...
 
struct  AuxFunc2
 
class  binder2_1
 
class  Int2DAuxType
 
class  binder3_1
 
class  Int3DAuxType
 

Functions

template<class T >
norm (const T &x)
 
template<class T >
real (const T &x)
 
template<class T >
Epsilon ()
 
template<class T >
MinRep ()
 
template<class T >
rescale_error (T err, T const &resabs, T const &resasc)
 
template<typename UnaryFunctionT , typename Arg >
bool intGKPNA (UnaryFunctionT func, IntRegion< Arg > &reg, Arg const epsabs, Arg const epsrel, std::map< Arg, Arg > *fxmap=nullptr)
 Non-adaptive integration of the function f over the region 'reg'. More...
 
template<typename UnaryFunctionT , typename Arg >
void intGKP (UnaryFunctionT func, IntRegion< Arg > &reg, Arg const epsabs, Arg const epsrel, std::map< Arg, Arg > *fxmap=nullptr)
 An adaptive integration algorithm which computes the integral of f over the region reg. More...
 
template<class UF >
AuxFunc1< UF > Aux1 (UF uf)
 Auxiliary function 1. More...
 
template<class UF >
AuxFunc2< UF > Aux2 (UF uf)
 Auxiliary function 2. More...
 
template<class BF , class Tp >
binder2_1< BF > bind21 (const BF &oper, const Tp &x)
 
template<class TF , class Tp >
binder3_1< TF > bind31 (const TF &oper, const Tp &x)
 
int gkp_n (int level)
 
template<class T >
const std::vector< T > & gkp_x (int level)
 
template<class T >
const std::vector< T > & gkp_wa (int level)
 
template<class T >
const std::vector< T > & gkp_wb (int level)
 

Function Documentation

◆ Aux1()

template<class UF >
AuxFunc1<UF> lsst::afw::math::details::Aux1 ( UF  uf)
inline

Auxiliary function 1.

Definition at line 587 of file Integrate.h.

587  {
588  return AuxFunc1<UF>(uf);
589 }

◆ Aux2()

template<class UF >
AuxFunc2<UF> lsst::afw::math::details::Aux2 ( UF  uf)
inline

Auxiliary function 2.

Definition at line 608 of file Integrate.h.

608  {
609  return AuxFunc2<UF>(uf);
610 }

◆ bind21()

template<class BF , class Tp >
binder2_1<BF> lsst::afw::math::details::bind21 ( const BF &  oper,
const Tp &  x 
)
inline

Definition at line 628 of file Integrate.h.

628  {
629  using Arg = typename BF::first_argument_type;
630  return binder2_1<BF>(oper, static_cast<Arg>(x));
631 }
double x

◆ bind31()

template<class TF , class Tp >
binder3_1<TF> lsst::afw::math::details::bind31 ( const TF &  oper,
const Tp &  x 
)
inline

Definition at line 671 of file Integrate.h.

671  {
672  using Arg = typename TF::firstof3_argument_type;
673  return binder3_1<TF>(oper, static_cast<Arg>(x));
674 }

◆ Epsilon()

template<class T >
T lsst::afw::math::details::Epsilon ( )
inline

Definition at line 244 of file Integrate.h.

244  {
246 }
T epsilon(T... args)

◆ gkp_n()

int lsst::afw::math::details::gkp_n ( int  level)
inline

Definition at line 47 of file IntGKPData10.h.

47  {
48  assert(level >= 0 && level < NGKPLEVELS);
49  static const int ngkp[NGKPLEVELS] = {5, 5, 11, 22, 44};
50  return ngkp[level];
51 }

◆ gkp_wa()

template<class T >
const std::vector<T>& lsst::afw::math::details::gkp_wa ( int  level)
inline

Definition at line 116 of file IntGKPData10.h.

116  {
117  // w21a, weights of the 21-point formula for abscissae x10
118  static const T aw21a[5] = {0.032558162307964727478818972459390, 0.075039674810919952767043140916190,
119  0.109387158802297641899210590325805, 0.134709217311473325928054001771707,
120  0.147739104901338491374841515972068};
121  static const std::vector<T> vw21a(aw21a, aw21a + 5);
122 
123  // w43a, weights of the 43-point formula for abscissae x10,x21
124  static const T aw43a[10] = {0.016296734289666564924281974617663, 0.037522876120869501461613795898115,
125  0.054694902058255442147212685465005, 0.067355414609478086075553166302174,
126  0.073870199632393953432140695251367, 0.005768556059769796184184327908655,
127  0.027371890593248842081276069289151, 0.046560826910428830743339154433824,
128  0.061744995201442564496240336030883, 0.071387267268693397768559114425516};
129  static const std::vector<T> vw43a(aw43a, aw43a + 10);
130 
131  // w87a, weights of the 87-point formula for abscissae x10..x43
132  static const T aw87a[21] = {0.008148377384149172900002878448190, 0.018761438201562822243935059003794,
133  0.027347451050052286161582829741283, 0.033677707311637930046581056957588,
134  0.036935099820427907614589586742499, 0.002884872430211530501334156248695,
135  0.013685946022712701888950035273128, 0.023280413502888311123409291030404,
136  0.030872497611713358675466394126442, 0.035693633639418770719351355457044,
137  0.000915283345202241360843392549948, 0.005399280219300471367738743391053,
138  0.010947679601118931134327826856808, 0.016298731696787335262665703223280,
139  0.021081568889203835112433060188190, 0.025370969769253827243467999831710,
140  0.029189697756475752501446154084920, 0.032373202467202789685788194889595,
141  0.034783098950365142750781997949596, 0.036412220731351787562801163687577,
142  0.037253875503047708539592001191226};
143  static const std::vector<T> vw87a(aw87a, aw87a + 21);
144 
145  // w175a, weights of the 175-point formula for abscissae x10..x87
146  static const T aw175a[43] = {
147  0.004074188692082600103872341, 0.009380719100781411819741177, 0.01367372552502614309257226,
148  0.01683885365581896502443513, 0.01846754991021395380770806, 0.001442436294030254510518689,
149  0.006842973011356375224430623, 0.01164020675144415562952859, 0.01543624880585667934076834,
150  0.01784681681970938536027839, 0.0004576754584154192941064591, 0.002699640110136963534043642,
151  0.005473839800559775445647306, 0.008149365848393670964180954, 0.01054078444460191775302900,
152  0.01268548488462691364854167, 0.01459484887823787625642303, 0.01618660123360139484467359,
153  0.01739154947518257137619173, 0.01820611036567589378188459, 0.01862693775152385427017140,
154  0.0001363171844264931156688042, 0.0009035606060432074452289352, 0.002048434635928091782250346,
155  0.003379145025868061092978424, 0.004774978836099393880602724, 0.006164723826122346701274159,
156  0.007505223673194467726814647, 0.008774483993121594091281642, 0.009969018893220443741650500,
157  0.01109746798050614328494604, 0.01216957356300040269315573, 0.01318725270741960360319771,
158  0.01414345539438560032188640, 0.01502629056404634765715107, 0.01582337568571996469999659,
159  0.01652520670998925164398162, 0.01712754985211303089259342, 0.01763120633007834051620255,
160  0.01803849481144435059221422, 0.01834930224922804724856518, 0.01856027463491628805666919,
161  0.01866711437596752016025132};
162  static const std::vector<T> vw175a(aw175a, aw175a + 43);
163 
164  static const std::vector<T>* wa[NGKPLEVELS] = {nullptr, &vw21a, &vw43a, &vw87a, &vw175a};
165 
166  assert(level >= 1 && level < NGKPLEVELS);
167  return *wa[level];
168 }

◆ gkp_wb()

template<class T >
const std::vector<T>& lsst::afw::math::details::gkp_wb ( int  level)
inline

Definition at line 171 of file IntGKPData10.h.

171  {
172  // w10, weights of the 10-point formula
173  static const T aw10b[6] = {0.066671344308688137593568809893332, 0.149451349150580593145776339657697,
174  0.219086362515982043995534934228163, 0.269266719309996355091226921569469,
175  0.295524224714752870173892994651338, 0.0};
176  static const std::vector<T> vw10b(aw10b, aw10b + 6);
177 
178  // w21b, weights of the 21-point formula for abscissae x21
179  static const T aw21b[6] = {0.011694638867371874278064396062192, 0.054755896574351996031381300244580,
180  0.093125454583697605535065465083366, 0.123491976262065851077958109831074,
181  0.142775938577060080797094273138717, 0.149445554002916905664936468389821};
182  static const std::vector<T> vw21b(aw21b, aw21b + 6);
183 
184  // w43b, weights of the 43-point formula for abscissae x43
185  static const T aw43b[12] = {0.001844477640212414100389106552965, 0.010798689585891651740465406741293,
186  0.021895363867795428102523123075149, 0.032597463975345689443882222526137,
187  0.042163137935191811847627924327955, 0.050741939600184577780189020092084,
188  0.058379395542619248375475369330206, 0.064746404951445885544689259517511,
189  0.069566197912356484528633315038405, 0.072824441471833208150939535192842,
190  0.074507751014175118273571813842889, 0.074722147517403005594425168280423};
191  static const std::vector<T> vw43b(aw43b, aw43b + 12);
192 
193  // w87b, weights of the 87-point formula for abscissae x87
194  static const T aw87b[23] = {0.000274145563762072350016527092881, 0.001807124155057942948341311753254,
195  0.004096869282759164864458070683480, 0.006758290051847378699816577897424,
196  0.009549957672201646536053581325377, 0.012329447652244853694626639963780,
197  0.015010447346388952376697286041943, 0.017548967986243191099665352925900,
198  0.019938037786440888202278192730714, 0.022194935961012286796332102959499,
199  0.024339147126000805470360647041454, 0.026374505414839207241503786552615,
200  0.028286910788771200659968002987960, 0.030052581128092695322521110347341,
201  0.031646751371439929404586051078883, 0.033050413419978503290785944862689,
202  0.034255099704226061787082821046821, 0.035262412660156681033782717998428,
203  0.036076989622888701185500318003895, 0.036698604498456094498018047441094,
204  0.037120549269832576114119958413599, 0.037334228751935040321235449094698,
205  0.037361073762679023410321241766599};
206  static const std::vector<T> vw87b(aw87b, aw87b + 23);
207 
208  // w175b, weights of the 175-point formula for abscissae x175
209  static const T aw175b[45] = {
210  0.00003901440664395060055484226, 0.0002787312407993348139961464, 0.0006672934146291138823512275,
211  0.001163051749910003055308177, 0.001738533916888715565420637, 0.002369555040550195269486165,
212  0.003036735036032612976379865, 0.003725394125884235586678819, 0.004424387541776355951933433,
213  0.005125062882078508655875582, 0.005820601038952832388647054, 0.006505667785357412495794539,
214  0.007176258976795165213169074, 0.007829642423806550517967042, 0.008464316525043036555640657,
215  0.009079917879101951192512711, 0.009677029304308397008134699, 0.01025687419430508685393322,
216  0.01082092935368957685380896, 0.01137052956179654620079332, 0.01190655150082017425918844,
217  0.01242924137407215963971061, 0.01293819980598456566872951, 0.01343248644726851711632966,
218  0.01391078107864287587682982, 0.01437154592198526807352501, 0.01481316256915705351874381,
219  0.01523404482122031244940129, 0.01563274056894636856297717, 0.01600802989372176552081826,
220  0.01635901148521841710605397, 0.01668515675646806540972517, 0.01698630892029276765404134,
221  0.01726261506199017604299177, 0.01751439915887340284018269, 0.01774200489411242260549908,
222  0.01794564958245060930824294, 0.01812532816637054898168673, 0.01828078919412312732671357,
223  0.01841158014800801587767163, 0.01851713825962505903167768, 0.01859689376712028821908313,
224  0.01865035760791320287947920, 0.01867717982648033250824110, 0.01868053688133951170552407};
225  static const std::vector<T> vw175b(aw175b, aw175b + 45);
226 
227  static const std::vector<T>* wb[NGKPLEVELS] = {&vw10b, &vw21b, &vw43b, &vw87b, &vw175b};
228 
229  assert(level >= 0 && level < NGKPLEVELS);
230  return *wb[level];
231 }

◆ gkp_x()

template<class T >
const std::vector<T>& lsst::afw::math::details::gkp_x ( int  level)
inline

Definition at line 54 of file IntGKPData10.h.

54  {
55  // x10, abscissae common to the 10-, 21-, 43- and 87-point rule
56  static const T ax10[5] = {0.973906528517171720077964012084452, 0.865063366688984510732096688423493,
57  0.679409568299024406234327365114874, 0.433395394129247190799265943165784,
58  0.148874338981631210884826001129720};
59  static const std::vector<T> vx10(ax10, ax10 + 5);
60 
61  // x21, abscissae common to the 21-, 43- and 87-point rule
62  static const T ax21[5] = {0.995657163025808080735527280689003, 0.930157491355708226001207180059508,
63  0.780817726586416897063717578345042, 0.562757134668604683339000099272694,
64  0.294392862701460198131126603103866};
65  static const std::vector<T> vx21(ax21, ax21 + 5);
66 
67  // x43, abscissae common to the 43- and 87-point rule
68  static const T ax43[11] = {0.999333360901932081394099323919911, 0.987433402908088869795961478381209,
69  0.954807934814266299257919200290473, 0.900148695748328293625099494069092,
70  0.825198314983114150847066732588520, 0.732148388989304982612354848755461,
71  0.622847970537725238641159120344323, 0.499479574071056499952214885499755,
72  0.364901661346580768043989548502644, 0.222254919776601296498260928066212,
73  0.074650617461383322043914435796506};
74  static const std::vector<T> vx43(ax43, ax43 + 11);
75 
76  // x87, abscissae of the 87-point rule
77  static const T ax87[22] = {0.999902977262729234490529830591582, 0.997989895986678745427496322365960,
78  0.992175497860687222808523352251425, 0.981358163572712773571916941623894,
79  0.965057623858384619128284110607926, 0.943167613133670596816416634507426,
80  0.915806414685507209591826430720050, 0.883221657771316501372117548744163,
81  0.845710748462415666605902011504855, 0.803557658035230982788739474980964,
82  0.757005730685495558328942793432020, 0.706273209787321819824094274740840,
83  0.651589466501177922534422205016736, 0.593223374057961088875273770349144,
84  0.531493605970831932285268948562671, 0.466763623042022844871966781659270,
85  0.399424847859218804732101665817923, 0.329874877106188288265053371824597,
86  0.258503559202161551802280975429025, 0.185695396568346652015917141167606,
87  0.111842213179907468172398359241362, 0.037352123394619870814998165437704};
88  static const std::vector<T> vx87(ax87, ax87 + 22);
89 
90  // x175, new abscissae of the 175-point rule
91  static const T ax175[44] = {
92  0.9999863601049729677997719, 0.9996988005421428623760900, 0.9987732473138838303043008,
93  0.9969583851613681945576954, 0.9940679446543307664316419, 0.9899673391741082769960501,
94  0.9845657252243253759726856, 0.9778061574856414566055911, 0.9696573134362640567828241,
95  0.9601075259508299668299148, 0.9491605191933640559839528, 0.9368321320434676982049391,
96  0.9231475266471484946315312, 0.9081385954543932335481458, 0.8918414554201179766275301,
97  0.8742940658668577971868106, 0.8555341249920432726468181, 0.8355974653331171075829366,
98  0.8145171513255796294567278, 0.7923233739697216224661771, 0.7690440708082055924983192,
99  0.7447060413364141221086362, 0.7193362474393392286563226, 0.6929630148748741413274435,
100  0.6656169582351898081906710, 0.6373315753624730450361940, 0.6081435407529742253347887,
101  0.5780927509986774074337714, 0.5472221576559162873479056, 0.5155774001694817879753989,
102  0.4832062516695473663839323, 0.4501579202236101928554315, 0.4164822936334372150371142,
103  0.3822292525735955063074986, 0.3474481818229070516859048, 0.3121877718977455143765043,
104  0.2764961311348905899785770, 0.2404211453027010909070665, 0.2040109589145005126324680,
105  0.1673144327616352753945014, 0.1303814601095591675431696, 0.09326308333660176874846400,
106  0.05601141598806823374241435, 0.01867941779948308845140053};
107  static const std::vector<T> vx175(ax175, ax175 + 44);
108 
109  static const std::vector<T>* x[NGKPLEVELS] = {&vx10, &vx21, &vx43, &vx87, &vx175};
110 
111  assert(level >= 0 && level < NGKPLEVELS);
112  return *x[level];
113 }

◆ intGKP()

template<typename UnaryFunctionT , typename Arg >
void lsst::afw::math::details::intGKP ( UnaryFunctionT  func,
IntRegion< Arg > &  reg,
Arg const  epsabs,
Arg const  epsrel,
std::map< Arg, Arg > *  fxmap = nullptr 
)
inline

An adaptive integration algorithm which computes the integral of f over the region reg.

Note
First the non-adaptive GKP algorithm is tried. If that is not accurate enough (according to the absolute and relative accuracies, epsabs and epsrel), the region is split in half, and each new region is integrated. The routine continues by successively splitting the subregion which gave the largest absolute error until the integral converges.

The area and estimated error are returned as reg.Area() and reg.Err() If desired, *retx and *retf return std::vectors of x,f(x) respectively They only include the evaluations in the non-adaptive pass, so they do not give an accurate estimate of the number of function evaluations.

Definition at line 426 of file Integrate.h.

428  {
429  integ_dbg2 << "Start intGKP\n";
430 
431  assert(epsabs >= 0.0);
432  assert(epsrel > 0.0);
433 
434  // perform the first integration
435  bool done = intGKPNA(func, reg, epsabs, epsrel, fxmap);
436  if (done) return;
437 
438  integ_dbg2 << "In adaptive GKP, failed first pass... subdividing\n";
439  integ_dbg2 << "Intial range = " << reg.Left() << ".." << reg.Right() << std::endl;
440 
441  int roundoffType1 = 0, errorType = 0;
442  Arg roundoffType2 = 0;
443  size_t iteration = 1;
444 
446  allregions.push(reg);
447  Arg finalarea = reg.Area();
448  Arg finalerr = reg.Err();
449  Arg tolerance = std::max(epsabs, epsrel * fabs(finalarea));
450  assert(finalerr > tolerance);
451 
452  while (!errorType && finalerr > tolerance) {
453  // Bisect the subinterval with the largest error estimate
454  integ_dbg2 << "Current answer = " << finalarea << " +- " << finalerr;
455  integ_dbg2 << " (tol = " << tolerance << ")\n";
456  IntRegion<Arg> parent = allregions.top();
457  allregions.pop();
458  integ_dbg2 << "Subdividing largest error region ";
459  integ_dbg2 << parent.Left() << ".." << parent.Right() << std::endl;
460  integ_dbg2 << "parent area = " << parent.Area();
461  integ_dbg2 << " +- " << parent.Err() << std::endl;
462  std::vector<IntRegion<Arg> > children;
463  parent.SubDivide(&children);
464  // For "GKP", there are only two, but for GKPOSC, there is one
465  // for each oscillation in region
466 
467  // Try to do at least 3x better with the children
468  Arg factor = 3 * children.size() * finalerr / tolerance;
469  Arg newepsabs = fabs(parent.Err() / factor);
470  Arg newepsrel = newepsabs / fabs(parent.Area());
471  integ_dbg2 << "New epsabs, rel = " << newepsabs << ", " << newepsrel;
472  integ_dbg2 << " (" << children.size() << " children)\n";
473 
474  Arg newarea = Arg(0.0);
475  Arg newerror = 0.0;
476  for (size_t i = 0; i < children.size(); i++) {
477  IntRegion<Arg> &child = children[i];
478  integ_dbg2 << "Integrating child " << child.Left();
479  integ_dbg2 << ".." << child.Right() << std::endl;
480  bool hasConverged;
481  hasConverged = intGKPNA(func, child, newepsabs, newepsrel);
482  integ_dbg2 << "child (" << i + 1 << '/' << children.size() << ") ";
483  if (hasConverged) {
484  integ_dbg2 << " converged.";
485  } else {
486  integ_dbg2 << " failed.";
487  }
488  integ_dbg2 << " Area = " << child.Area() << " +- " << child.Err() << std::endl;
489 
490  newarea += child.Area();
491  newerror += child.Err();
492  }
493  integ_dbg2 << "Compare: newerr = " << newerror;
494  integ_dbg2 << " to parent err = " << parent.Err() << std::endl;
495 
496  finalerr += (newerror - parent.Err());
497  finalarea += newarea - parent.Area();
498 
499  Arg delta = parent.Area() - newarea;
500  if (newerror <= parent.Err() && fabs(delta) <= parent.Err() && newerror >= 0.99 * parent.Err()) {
501  integ_dbg2 << "roundoff type 1: delta/newarea = ";
502  integ_dbg2 << fabs(delta) / fabs(newarea);
503  integ_dbg2 << ", newerror/error = " << newerror / parent.Err() << std::endl;
504  roundoffType1++;
505  }
506  if (iteration >= 10 && newerror > parent.Err() && fabs(delta) <= newerror - parent.Err()) {
507  integ_dbg2 << "roundoff type 2: newerror/error = ";
508  integ_dbg2 << newerror / parent.Err() << std::endl;
509  roundoffType2 += std::min(newerror / parent.Err() - 1.0, Arg(1.0));
510  }
511 
512  tolerance = std::max(epsabs, epsrel * fabs(finalarea));
513  if (finalerr > tolerance) {
514  if (roundoffType1 >= 200) {
515  errorType = 1; // round off error
516  integ_dbg2 << "GKP: Round off error 1\n";
517  }
518  if (roundoffType2 >= 200.0) {
519  errorType = 2; // round off error
520  integ_dbg2 << "GKP: Round off error 2\n";
521  }
522  if (fabs((parent.Right() - parent.Left()) / (reg.Right() - reg.Left())) < Epsilon<double>()) {
523  errorType = 3; // found singularity
524  integ_dbg2 << "GKP: Probable singularity\n";
525  }
526  }
527  for (size_t i = 0; i < children.size(); i++) {
528  allregions.push(children[i]);
529  }
530  iteration++;
531  }
532 
533  // Recalculate finalarea in case there are any slight rounding errors
534  finalarea = 0.0;
535  finalerr = 0.0;
536  while (!allregions.empty()) {
537  IntRegion<Arg> const &r = allregions.top();
538  finalarea += r.Area();
539  finalerr += r.Err();
540  allregions.pop();
541  }
542  reg.SetArea(finalarea, finalerr);
543 
544  if (errorType == 1) {
546  s << "Type 1 roundoff's = " << roundoffType1;
547  s << ", Type 2 = " << roundoffType2 << std::endl;
548  s << "Roundoff error 1 prevents tolerance from being achieved ";
549  s << "in intGKP\n";
551  } else if (errorType == 2) {
553  s << "Type 1 roundoff's = " << roundoffType1;
554  s << ", Type 2 = " << roundoffType2 << std::endl;
555  s << "Roundoff error 2 prevents tolerance from being achieved ";
556  s << "in intGKP\n";
558  } else if (errorType == 3) {
560  s << "Bad integrand behavior found in the integration interval ";
561  s << "in intGKP\n";
563  }
564 }
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
#define integ_dbg2
Definition: Integrate.h:149
Reports errors that are due to events beyond the control of the program.
Definition: Runtime.h:104
T empty(T... args)
T endl(T... args)
T fabs(T... args)
T max(T... args)
T min(T... args)
bool intGKPNA(UnaryFunctionT func, IntRegion< Arg > &reg, Arg const epsabs, Arg const epsrel, std::map< Arg, Arg > *fxmap=nullptr)
Non-adaptive integration of the function f over the region 'reg'.
Definition: Integrate.h:298
T pop(T... args)
T push(T... args)
T size(T... args)
T str(T... args)
T top(T... args)

◆ intGKPNA()

template<typename UnaryFunctionT , typename Arg >
bool lsst::afw::math::details::intGKPNA ( UnaryFunctionT  func,
IntRegion< Arg > &  reg,
Arg const  epsabs,
Arg const  epsrel,
std::map< Arg, Arg > *  fxmap = nullptr 
)
inline

Non-adaptive integration of the function f over the region 'reg'.

Note
The algorithm computes first a Gaussian quadrature value then successive Kronrod/Patterson extensions to this result. The functions terminates when the difference between successive approximations (rescaled according to rescale_error) is less than either epsabs or epsrel * I, where I is the latest estimate of the integral. The order of the Gauss/Kronron/Patterson scheme is determined by which file is included above. Currently schemes starting with order 1 and order 10 are calculated. There seems to be little practical difference in the integration times using the two schemes, so I haven't bothered to calculate any more.

Definition at line 298 of file Integrate.h.

300  {
301  Arg const a = reg.Left();
302  Arg const b = reg.Right();
303 
304  Arg const halfLength = 0.5 * (b - a);
305  Arg const absHalfLength = fabs(halfLength);
306  Arg const center = 0.5 * (b + a);
307  Arg const fCenter = func(center);
308 #ifdef COUNTFEVAL
309  nfeval++;
310 #endif
311 
312  assert(gkp_wb<Arg>(0).size() == gkp_x<Arg>(0).size() + 1);
313  Arg area1 = gkp_wb<Arg>(0).back() * fCenter;
314  std::vector<Arg> fv1, fv2;
315  fv1.reserve(2 * gkp_x<Arg>(0).size() + 1);
316  fv2.reserve(2 * gkp_x<Arg>(0).size() + 1);
317  for (size_t k = 0; k < gkp_x<Arg>(0).size(); k++) {
318  Arg const abscissa = halfLength * gkp_x<Arg>(0)[k];
319  Arg const fval1 = func(center - abscissa);
320  Arg const fval2 = func(center + abscissa);
321  area1 += gkp_wb<Arg>(0)[k] * (fval1 + fval2);
322  fv1.push_back(fval1);
323  fv2.push_back(fval2);
324  if (fxmap) {
325  (*fxmap)[center - abscissa] = fval1;
326  (*fxmap)[center + abscissa] = fval2;
327  }
328  }
329 #ifdef COUNTFEVAL
330  nfeval += gkp_x<Arg>(0).size() * 2;
331 #endif
332 
333  integ_dbg2 << "level 0 rule: area = " << area1 << std::endl;
334 
335  Arg err = 0;
336  bool calcabsasc = true;
337  Arg resabs = 0.0, resasc = 0.0;
338  for (int level = 1; level < NGKPLEVELS; level++) {
339  assert(gkp_wa<Arg>(level).size() == fv1.size());
340  assert(gkp_wa<Arg>(level).size() == fv2.size());
341  assert(gkp_wb<Arg>(level).size() == gkp_x<Arg>(level).size() + 1);
342  Arg area2 = gkp_wb<Arg>(level).back() * fCenter;
343  // resabs = approximation to integral of abs(f)
344  if (calcabsasc) {
345  resabs = fabs(area2);
346  }
347  for (size_t k = 0; k < fv1.size(); k++) {
348  area2 += gkp_wa<Arg>(level)[k] * (fv1[k] + fv2[k]);
349  if (calcabsasc) {
350  resabs += gkp_wa<Arg>(level)[k] * (fabs(fv1[k]) + fabs(fv2[k]));
351  }
352  }
353  for (size_t k = 0; k < gkp_x<Arg>(level).size(); k++) {
354  Arg const abscissa = halfLength * gkp_x<Arg>(level)[k];
355  Arg const fval1 = func(center - abscissa);
356  Arg const fval2 = func(center + abscissa);
357  Arg const fval = fval1 + fval2;
358  area2 += gkp_wb<Arg>(level)[k] * fval;
359  if (calcabsasc) {
360  resabs += gkp_wb<Arg>(level)[k] * (fabs(fval1) + fabs(fval2));
361  }
362  fv1.push_back(fval1);
363  fv2.push_back(fval2);
364  if (fxmap) {
365  (*fxmap)[center - abscissa] = fval1;
366  (*fxmap)[center + abscissa] = fval2;
367  }
368  }
369 #ifdef COUNTFEVAL
370  nfeval += gkp_x<Arg>(level).size() * 2;
371 #endif
372  if (calcabsasc) {
373  Arg const mean = area1 * Arg(0.5);
374  // resasc = approximation to the integral of abs(f-mean)
375  resasc = gkp_wb<Arg>(level).back() * fabs(fCenter - mean);
376  for (size_t k = 0; k < gkp_wa<Arg>(level).size(); k++) {
377  resasc += gkp_wa<Arg>(level)[k] * (fabs(fv1[k] - mean) + fabs(fv2[k] - mean));
378  }
379  for (size_t k = 0; k < gkp_x<Arg>(level).size(); k++) {
380  resasc += gkp_wb<Arg>(level)[k] * (fabs(fv1[k] - mean) + fabs(fv2[k] - mean));
381  }
382  resasc *= absHalfLength;
383  resabs *= absHalfLength;
384  }
385  area2 *= halfLength;
386  err = rescale_error(fabs(area2 - area1), resabs, resasc);
387  if (err < resasc) {
388  calcabsasc = false;
389  }
390 
391  integ_dbg2 << "at level " << level << " area2 = " << area2;
392  integ_dbg2 << " +- " << err << std::endl;
393 
394  // test for convergence.
395  if (err < epsabs || err < epsrel * fabs(area2)) {
396  reg.SetArea(area2, err);
397  return true;
398  }
399  area1 = area2;
400  }
401 
402  // failed to converge
403  reg.SetArea(area1, err);
404 
405  integ_dbg2 << "Failed to reach tolerance with highest-order GKP rule";
406 
407  return false;
408 }
table::Key< int > b
table::Key< int > a
T rescale_error(T err, T const &resabs, T const &resasc)
Definition: Integrate.h:264
T push_back(T... args)
T reserve(T... args)

◆ MinRep()

template<class T >
T lsst::afw::math::details::MinRep ( )
inline

Definition at line 248 of file Integrate.h.

248  {
250 }

◆ norm()

template<class T >
T lsst::afw::math::details::norm ( const T &  x)
inline

Definition at line 160 of file Integrate.h.

160  {
161  return x * x;
162 }

◆ real()

template<class T >
T lsst::afw::math::details::real ( const T &  x)
inline

Definition at line 165 of file Integrate.h.

165  {
166  return x;
167 }

◆ rescale_error()

template<class T >
T lsst::afw::math::details::rescale_error ( err,
T const &  resabs,
T const &  resasc 
)
inline

Definition at line 264 of file Integrate.h.

264  {
265  if (resasc != 0.0 && err != 0.0) {
266  T const scale = (200.0 * err / resasc);
267  if (scale < 1.0) {
268  err = resasc * scale * sqrt(scale);
269  } else {
270  err = resasc;
271  }
272  }
273  if (resabs > MinRep<T>() / (50.0 * Epsilon<T>())) {
274  T const min_err = 50.0 * Epsilon<T>() * resabs;
275  if (min_err > err) {
276  err = min_err;
277  }
278  }
279  return err;
280 }
def scale(algorithm, min, max=None, frame=None)
Definition: ds9.py:108
T sqrt(T... args)