123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207 |
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mex.h"
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include <math.h>
- #include "mut.h"
- /* stirlerr(n) = log(n!) - log( sqrt(2*pi*n)*(n/e)^n ) */
- #define S0 0.083333333333333333333 /* 1/12 */
- #define S1 0.00277777777777777777778 /* 1/360 */
- #define S2 0.00079365079365079365079365 /* 1/1260 */
- #define S3 0.000595238095238095238095238 /* 1/1680 */
- #define S4 0.0008417508417508417508417508 /* 1/1188 */
- /*
- error for 0, 0.5, 1.0, 1.5, ..., 14.5, 15.0.
- */
- static double sferr_halves[31] = {
- 0.0, /* n=0 - wrong, place holder only */
- 0.1534264097200273452913848, /* 0.5 */
- 0.0810614667953272582196702, /* 1.0 */
- 0.0548141210519176538961390, /* 1.5 */
- 0.0413406959554092940938221, /* 2.0 */
- 0.03316287351993628748511048, /* 2.5 */
- 0.02767792568499833914878929, /* 3.0 */
- 0.02374616365629749597132920, /* 3.5 */
- 0.02079067210376509311152277, /* 4.0 */
- 0.01848845053267318523077934, /* 4.5 */
- 0.01664469118982119216319487, /* 5.0 */
- 0.01513497322191737887351255, /* 5.5 */
- 0.01387612882307074799874573, /* 6.0 */
- 0.01281046524292022692424986, /* 6.5 */
- 0.01189670994589177009505572, /* 7.0 */
- 0.01110455975820691732662991, /* 7.5 */
- 0.010411265261972096497478567, /* 8.0 */
- 0.009799416126158803298389475, /* 8.5 */
- 0.009255462182712732917728637, /* 9.0 */
- 0.008768700134139385462952823, /* 9.5 */
- 0.008330563433362871256469318, /* 10.0 */
- 0.007934114564314020547248100, /* 10.5 */
- 0.007573675487951840794972024, /* 11.0 */
- 0.007244554301320383179543912, /* 11.5 */
- 0.006942840107209529865664152, /* 12.0 */
- 0.006665247032707682442354394, /* 12.5 */
- 0.006408994188004207068439631, /* 13.0 */
- 0.006171712263039457647532867, /* 13.5 */
- 0.005951370112758847735624416, /* 14.0 */
- 0.005746216513010115682023589, /* 14.5 */
- 0.005554733551962801371038690 /* 15.0 */
- };
- double stirlerr(n)
- double n;
- { double nn;
- if (n<15.0)
- { nn = 2.0*n;
- if (nn==(int)nn) return(sferr_halves[(int)nn]);
- return(mut_lgamma(n+1.0) - (n+0.5)*log((double)n)+n - HF_LG_PIx2);
- }
- nn = (double)n;
- nn = nn*nn;
- if (n>500) return((S0-S1/nn)/n);
- if (n>80) return((S0-(S1-S2/nn)/nn)/n);
- if (n>35) return((S0-(S1-(S2-S3/nn)/nn)/nn)/n);
- return((S0-(S1-(S2-(S3-S4/nn)/nn)/nn)/nn)/n);
- }
- double bd0(x,np)
- double x, np;
- { double ej, s, s1, v;
- int j;
- if (fabs(x-np)<0.1*(x+np))
- {
- s = (x-np)*(x-np)/(x+np);
- v = (x-np)/(x+np);
- ej = 2*x*v; v = v*v;
- for (j=1; ;++j)
- { ej *= v;
- s1 = s+ej/((j<<1)+1);
- if (s1==s) return(s1);
- s = s1;
- }
- }
- return(x*log(x/np)+np-x);
- }
- /*
- Raw binomial probability calculation.
- (1) This has both p and q arguments, when one may be represented
- more accurately than the other (in particular, in df()).
- (2) This should NOT check that inputs x and n are integers. This
- should be done in the calling function, where necessary.
- (3) Does not check for 0<=p<=1 and 0<=q<=1 or NaN's. Do this in
- the calling function.
- */
- double dbinom_raw(x,n,p,q,give_log)
- double x, n, p, q;
- int give_log;
- { double f, lc;
- if (p==0.0) return((x==0) ? D_1 : D_0);
- if (q==0.0) return((x==n) ? D_1 : D_0);
- if (x==0)
- { lc = (p<0.1) ? -bd0(n,n*q) - n*p : n*log(q);
- return( DEXP(lc) );
- }
- if (x==n)
- { lc = (q<0.1) ? -bd0(n,n*p) - n*q : n*log(p);
- return( DEXP(lc) );
- }
- if ((x<0) | (x>n)) return( D_0 );
- lc = stirlerr(n) - stirlerr(x) - stirlerr(n-x)
- - bd0(x,n*p) - bd0(n-x,n*q);
- f = (PIx2*x*(n-x))/n;
- return( FEXP(f,lc) );
- }
- double dbinom(x,n,p,give_log)
- int x, n;
- double p;
- int give_log;
- {
- if ((p<0) | (p>1) | (n<0)) return(INVALID_PARAMS);
- if (x<0) return( D_0 );
-
- return( dbinom_raw((double)x,(double)n,p,1-p,give_log) );
- }
- /*
- Poisson probability lb^x exp(-lb) / x!.
- I don't check that x is an integer, since other functions
- that call dpois_raw() (i.e. dgamma) may use a fractional
- x argument.
- */
- double dpois_raw(x,lambda,give_log)
- int give_log;
- double x, lambda;
- {
- if (lambda==0) return( (x==0) ? D_1 : D_0 );
- if (x==0) return( DEXP(-lambda) );
- if (x<0) return( D_0 );
- return(FEXP( PIx2*x, -stirlerr(x)-bd0(x,lambda) ));
- }
- double dpois(x,lambda,give_log)
- int x, give_log;
- double lambda;
- {
- if (lambda<0) return(INVALID_PARAMS);
- if (x<0) return( D_0 );
- return( dpois_raw((double)x,lambda,give_log) );
- }
- double dbeta(x,a,b,give_log)
- double x, a, b;
- int give_log;
- { double f, p;
- if ((a<=0) | (b<=0)) return(INVALID_PARAMS);
- if ((x<=0) | (x>=1)) return(D_0);
- if (a<1)
- { if (b<1) /* a<1, b<1 */
- { f = a*b/((a+b)*x*(1-x));
- p = dbinom_raw(a,a+b,x,1-x,give_log);
- }
- else /* a<1, b>=1 */
- { f = a/x;
- p = dbinom_raw(a,a+b-1,x,1-x,give_log);
- }
- }
- else
- { if (b<1) /* a>=1, b<1 */
- { f = b/(1-x);
- p = dbinom_raw(a-1,a+b-1,x,1-x,give_log);
- }
- else /* a>=1, b>=1 */
- { f = a+b-1;
- p = dbinom_raw(a-1,(a-1)+(b-1),x,1-x,give_log);
- }
- }
- return( (give_log) ? p + log(f) : p*f );
- }
- /*
- * To evaluate the F density, write it as a Binomial probability
- * with p = x*m/(n+x*m). For m>=2, use the simplest conversion.
- * For m<2, (m-2)/2<0 so the conversion will not work, and we must use
- * a second conversion. Note the division by p; this seems unavoidable
- * for m < 2, since the F density has a singularity as x (or p) -> 0.
- */
- double df(x,m,n,give_log)
- double x, m, n;
- int give_log;
- { double p, q, f, dens;
- if ((m<=0) | (n<=0)) return(INVALID_PARAMS);
- if (x <= 0.0) return(D_0);
- f = 1.0/(n+x*m);
- q = n*f;
- p = x*m*f;
- if (m>=2)
- { f = m*q/2;
- dens = dbinom_raw((m-2)/2.0, (m+n-2)/2.0, p, q, give_log);
- }
- else
- { f = m*m*q / (2*p*(m+n));
- dens = dbinom_raw(m/2.0, (m+n)/2.0, p, q, give_log);
- }
- return((give_log) ? log(f)+dens : f*dens);
- }
- /*
- * Gamma density,
- * lb^r x^{r-1} exp(-lb*x)
- * p(x;r,lb) = -----------------------
- * (r-1)!
- *
- * If USE_SCALE is defined below, the lb argument will be interpreted
- * as a scale parameter (i.e. replace lb by 1/lb above). Otherwise,
- * it is interpreted as a rate parameter, as above.
- */
- /* #define USE_SCALE */
- double dgamma(x,r,lambda,give_log)
- int give_log;
- double x, r, lambda;
- { double pr;
- if ((r<=0) | (lambda<0)) return(INVALID_PARAMS);
- if (x<=0.0) return( D_0 );
- #ifdef USE_SCALE
- lambda = 1.0/lambda;
- #endif
- if (r<1)
- { pr = dpois_raw(r,lambda*x,give_log);
- return( (give_log) ? pr + log(r/x) : pr*r/x );
- }
- pr = dpois_raw(r-1.0,lambda*x,give_log);
- return( (give_log) ? pr + log(lambda) : lambda*pr);
- }
- double dchisq(x, df, give_log)
- double x, df;
- int give_log;
- {
- return(dgamma(x, df/2.0,
- 0.5
- ,give_log));
- /*
- #ifdef USE_SCALE
- 2.0
- #else
- 0.5
- #endif
- ,give_log));
- */
- }
- /*
- * Given a sequence of r successes and b failures, we sample n (\le b+r)
- * items without replacement. The hypergeometric probability is the
- * probability of x successes:
- *
- * dbinom(x,r,p) * dbinom(n-x,b,p)
- * p(x;r,b,n) = ---------------------------------
- * dbinom(n,r+b,p)
- *
- * for any p. For numerical stability, we take p=n/(r+b); with this choice,
- * the denominator is not exponentially small.
- */
- double dhyper(x,r,b,n,give_log)
- int x, r, b, n, give_log;
- { double p, q, p1, p2, p3;
- if ((r<0) | (b<0) | (n<0) | (n>r+b))
- return( INVALID_PARAMS );
- if (x<0) return(D_0);
- if (n==0) return((x==0) ? D_1 : D_0);
- p = ((double)n)/((double)(r+b));
- q = ((double)(r+b-n))/((double)(r+b));
- p1 = dbinom_raw((double)x,(double)r,p,q,give_log);
- p2 = dbinom_raw((double)(n-x),(double)b,p,q,give_log);
- p3 = dbinom_raw((double)n,(double)(r+b),p,q,give_log);
- return( (give_log) ? p1 + p2 - p3 : p1*p2/p3 );
- }
- /*
- probability of x failures before the nth success.
- */
- double dnbinom(x,n,p,give_log)
- double n, p;
- int x, give_log;
- { double prob, f;
- if ((p<0) | (p>1) | (n<=0)) return(INVALID_PARAMS);
- if (x<0) return( D_0 );
- prob = dbinom_raw(n,x+n,p,1-p,give_log);
- f = n/(n+x);
- return((give_log) ? log(f) + prob : f*prob);
- }
- double dt(x, df, give_log)
- double x, df;
- int give_log;
- { double t, u, f;
- if (df<=0.0) return(INVALID_PARAMS);
- /*
- exp(t) = Gamma((df+1)/2) /{ sqrt(df/2) * Gamma(df/2) }
- = sqrt(df/2) / ((df+1)/2) * Gamma((df+3)/2) / Gamma((df+2)/2).
- This form leads to a computation that should be stable for all
- values of df, including df -> 0 and df -> infinity.
- */
- t = -bd0(df/2.0,(df+1)/2.0) + stirlerr((df+1)/2.0) - stirlerr(df/2.0);
- if (x*x>df)
- u = log( 1+ x*x/df ) * df/2;
- else
- u = -bd0(df/2.0,(df+x*x)/2.0) + x*x/2.0;
- f = PIx2*(1+x*x/df);
- return( FEXP(f,t-u) );
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Provides mut_erf() and mut_erfc() functions. Also mut_pnorm().
- * Had too many problems with erf()'s built into math libraries
- * (when they existed). Hence the need to write my own...
- *
- * Algorithm from Walter Kr\"{a}mer, Frithjof Blomquist.
- * "Algorithms with Guaranteed Error Bounds for the Error Function
- * and Complementary Error Function"
- * Preprint 2000/2, Bergische Universt\"{a}t GH Wuppertal
- * http://www.math.uni-wuppertal.de/wrswt/preprints/prep_00_2.pdf
- *
- * Coded by Catherine Loader, September 2006.
- */
- #include "mut.h"
- double erf1(double x) /* erf; 0 < x < 0.65) */
- { double p[5] = {1.12837916709551256e0, /* 2/sqrt(pi) */
- 1.35894887627277916e-1,
- 4.03259488531795274e-2,
- 1.20339380863079457e-3,
- 6.49254556481904354e-5};
- double q[5] = {1.00000000000000000e0,
- 4.53767041780002545e-1,
- 8.69936222615385890e-2,
- 8.49717371168693357e-3,
- 3.64915280629351082e-4};
- double x2, p4, q4;
- x2 = x*x;
- p4 = p[0] + p[1]*x2 + p[2]*x2*x2 + p[3]*x2*x2*x2 + p[4]*x2*x2*x2*x2;
- q4 = q[0] + q[1]*x2 + q[2]*x2*x2 + q[3]*x2*x2*x2 + q[4]*x2*x2*x2*x2;
- return(x*p4/q4);
- }
- double erf2(double x) /* erfc; 0.65 <= x < 2.2 */
- { double p[6] = {9.99999992049799098e-1,
- 1.33154163936765307e0,
- 8.78115804155881782e-1,
- 3.31899559578213215e-1,
- 7.14193832506776067e-2,
- 7.06940843763253131e-3};
- double q[7] = {1.00000000000000000e0,
- 2.45992070144245533e0,
- 2.65383972869775752e0,
- 1.61876655543871376e0,
- 5.94651311286481502e-1,
- 1.26579413030177940e-1,
- 1.25304936549413393e-2};
- double x2, p5, q6;
- x2 = x*x;
- p5 = p[0] + p[1]*x + p[2]*x2 + p[3]*x2*x + p[4]*x2*x2 + p[5]*x2*x2*x;
- q6 = q[0] + q[1]*x + q[2]*x2 + q[3]*x2*x + q[4]*x2*x2 + q[5]*x2*x2*x + q[6]*x2*x2*x2;
- return( exp(-x2)*p5/q6 );
- }
- double erf3(double x) /* erfc; 2.2 < x <= 6 */
- { double p[6] = {9.99921140009714409e-1,
- 1.62356584489366647e0,
- 1.26739901455873222e0,
- 5.81528574177741135e-1,
- 1.57289620742838702e-1,
- 2.25716982919217555e-2};
- double q[7] = {1.00000000000000000e0,
- 2.75143870676376208e0,
- 3.37367334657284535e0,
- 2.38574194785344389e0,
- 1.05074004614827206e0,
- 2.78788439273628983e-1,
- 4.00072964526861362e-2};
- double x2, p5, q6;
- x2 = x*x;
- p5 = p[0] + p[1]*x + p[2]*x2 + p[3]*x2*x + p[4]*x2*x2 + p[5]*x2*x2*x;
- q6 = q[0] + q[1]*x + q[2]*x2 + q[3]*x2*x + q[4]*x2*x2 + q[5]*x2*x2*x + q[6]*x2*x2*x2;
- return( exp(-x2)*p5/q6 );
- }
- double erf4(double x) /* erfc; x > 6.0 */
- { double p[5] = {5.64189583547756078e-1,
- 8.80253746105525775e0,
- 3.84683103716117320e1,
- 4.77209965874436377e1,
- 8.08040729052301677e0};
- double q[5] = {1.00000000000000000e0,
- 1.61020914205869003e1,
- 7.54843505665954743e1,
- 1.12123870801026015e2,
- 3.73997570145040850e1};
- double x2, p4, q4;
- if (x>26.5432) return(0.0);
- x2 = 1.0/(x*x);
- p4 = p[0] + p[1]*x2 + p[2]*x2*x2 + p[3]*x2*x2*x2 + p[4]*x2*x2*x2*x2;
- q4 = q[0] + q[1]*x2 + q[2]*x2*x2 + q[3]*x2*x2*x2 + q[4]*x2*x2*x2*x2;
- return(exp(-x*x)*p4/(x*q4));
- }
- double mut_erfc(double x)
- { if (x<0.0) return(2.0-mut_erfc(-x));
- if (x==0.0) return(1.0);
- if (x<0.65) return(1.0-erf1(x));
- if (x<2.2) return(erf2(x));
- if (x<6.0) return(erf3(x));
- return(erf4(x));
- }
- double mut_erf(double x)
- {
- if (x<0.0) return(-mut_erf(-x));
- if (x==0.0) return(0.0);
- if (x<0.65) return(erf1(x));
- if (x<2.2) return(1.0-erf2(x));
- if (x<6.0) return(1.0-erf3(x));
- return(1.0-erf4(x));
- }
- double mut_pnorm(double x)
- { if (x<0.0) return(mut_erfc(-x/SQRT2)/2);
- return((1.0+mut_erf(x/SQRT2))/2);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mut.h"
- static double lookup_gamma[21] = {
- 0.0, /* place filler */
- 0.572364942924699971, /* log(G(0.5)) = log(sqrt(pi)) */
- 0.000000000000000000, /* log(G(1)) = log(0!) */
- -0.120782237635245301, /* log(G(3/2)) = log(sqrt(pi)/2)) */
- 0.000000000000000000, /* log(G(2)) = log(1!) */
- 0.284682870472919181, /* log(G(5/2)) = log(3sqrt(pi)/4) */
- 0.693147180559945286, /* log(G(3)) = log(2!) */
- 1.200973602347074287, /* etc */
- 1.791759469228054957,
- 2.453736570842442344,
- 3.178053830347945752,
- 3.957813967618716511,
- 4.787491742782045812,
- 5.662562059857141783,
- 6.579251212010101213,
- 7.534364236758732680,
- 8.525161361065414667,
- 9.549267257300996903,
- 10.604602902745250859,
- 11.689333420797268559,
- 12.801827480081469091 };
- /*
- * coefs are B(2n)/(2n(2n-1)) 2n(2n-1) =
- * 2n B(2n) 2n(2n-1) coef
- * 2 1/6 2 1/12
- * 4 -1/30 12 -1/360
- * 6 1/42 30 1/1260
- * 8 -1/30 56 -1/1680
- * 10 5/66 90 1/1188
- * 12 -691/2730 132 691/360360
- */
- double mut_lgamma(double x)
- { double f, z, x2, se;
- int ix;
- /* lookup table for common values.
- */
- ix = (int)(2*x);
- if (((ix>=1) & (ix<=20)) && (ix==2*x)) return(lookup_gamma[ix]);
- f = 1.0;
- while (x <= 15)
- { f *= x;
- x += 1.0;
- }
- x2 = 1.0/(x*x);
- z = (x-0.5)*log(x) - x + HF_LG_PIx2;
- se = (13860 - x2*(462 - x2*(132 - x2*(99 - 140*x2))))/(166320*x);
- return(z + se - log(f));
- }
- double mut_lgammai(int i) /* log(Gamma(i/2)) for integer i */
- { if (i>20) return(mut_lgamma(i/2.0));
- return(lookup_gamma[i]);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * A is a n*p matrix, find the cholesky decomposition
- * of the first p rows. In most applications, will want n=p.
- *
- * chol_dec(A,n,p) computes the decomoposition R'R=A.
- * (note that R is stored in the input A).
- * chol_solve(A,v,n,p) computes (R'R)^{-1}v
- * chol_hsolve(A,v,n,p) computes (R')^{-1}v
- * chol_isolve(A,v,n,p) computes (R)^{-1}v
- * chol_qf(A,v,n,p) computes ||(R')^{-1}v||^2.
- * chol_mult(A,v,n,p) computes (R'R)v
- *
- * The solve functions assume that A is already decomposed.
- * chol_solve(A,v,n,p) is equivalent to applying chol_hsolve()
- * and chol_isolve() in sequence.
- */
- #include <math.h>
- #include "mut.h"
- void chol_dec(A,n,p)
- double *A;
- int n, p;
- { int i, j, k;
- for (j=0; j<p; j++)
- { k = n*j+j;
- for (i=0; i<j; i++) A[k] -= A[n*j+i]*A[n*j+i];
- if (A[k]<=0)
- { for (i=j; i<p; i++) A[n*i+j] = 0.0; }
- else
- { A[k] = sqrt(A[k]);
- for (i=j+1; i<p; i++)
- { for (k=0; k<j; k++)
- A[n*i+j] -= A[n*i+k]*A[n*j+k];
- A[n*i+j] /= A[n*j+j];
- }
- }
- }
- for (j=0; j<p; j++)
- for (i=j+1; i<p; i++) A[n*j+i] = 0.0;
- }
- int chol_solve(A,v,n,p)
- double *A, *v;
- int n, p;
- { int i, j;
- for (i=0; i<p; i++)
- { for (j=0; j<i; j++) v[i] -= A[i*n+j]*v[j];
- v[i] /= A[i*n+i];
- }
- for (i=p-1; i>=0; i--)
- { for (j=i+1; j<p; j++) v[i] -= A[j*n+i]*v[j];
- v[i] /= A[i*n+i];
- }
- return(p);
- }
- int chol_hsolve(A,v,n,p)
- double *A, *v;
- int n, p;
- { int i, j;
- for (i=0; i<p; i++)
- { for (j=0; j<i; j++) v[i] -= A[i*n+j]*v[j];
- v[i] /= A[i*n+i];
- }
- return(p);
- }
- int chol_isolve(A,v,n,p)
- double *A, *v;
- int n, p;
- { int i, j;
- for (i=p-1; i>=0; i--)
- { for (j=i+1; j<p; j++) v[i] -= A[j*n+i]*v[j];
- v[i] /= A[i*n+i];
- }
- return(p);
- }
- double chol_qf(A,v,n,p)
- double *A, *v;
- int n, p;
- { int i, j;
- double sum;
-
- sum = 0.0;
- for (i=0; i<p; i++)
- { for (j=0; j<i; j++) v[i] -= A[i*n+j]*v[j];
- v[i] /= A[i*n+i];
- sum += v[i]*v[i];
- }
- return(sum);
- }
- int chol_mult(A,v,n,p)
- double *A, *v;
- int n, p;
- { int i, j;
- double sum;
- for (i=0; i<p; i++)
- { sum = 0;
- for (j=i; j<p; j++) sum += A[j*n+i]*v[j];
- v[i] = sum;
- }
- for (i=p-1; i>=0; i--)
- { sum = 0;
- for (j=0; j<=i; j++) sum += A[i*n+j]*v[j];
- v[i] = sum;
- }
- return(1);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include <stdio.h>
- #include <math.h>
- #include "mut.h"
- #define E_MAXIT 20
- #define E_TOL 1.0e-10
- #define SQR(x) ((x)*(x))
- double e_tol(D,p)
- double *D;
- int p;
- { double mx;
- int i;
- if (E_TOL <= 0.0) return(0.0);
- mx = D[0];
- for (i=1; i<p; i++) if (D[i*(p+1)]>mx) mx = D[i*(p+1)];
- return(E_TOL*mx);
- }
- void eig_dec(X,P,d)
- double *X, *P;
- int d;
- { int i, j, k, iter, ms;
- double c, s, r, u, v;
- for (i=0; i<d; i++)
- for (j=0; j<d; j++) P[i*d+j] = (i==j);
- for (iter=0; iter<E_MAXIT; iter++)
- { ms = 0;
- for (i=0; i<d; i++)
- for (j=i+1; j<d; j++)
- if (SQR(X[i*d+j]) > 1.0e-15*fabs(X[i*d+i]*X[j*d+j]))
- { c = (X[j*d+j]-X[i*d+i])/2;
- s = -X[i*d+j];
- r = sqrt(c*c+s*s);
- c /= r;
- s = sqrt((1-c)/2)*(2*(s>0)-1);
- c = sqrt((1+c)/2);
- for (k=0; k<d; k++)
- { u = X[i*d+k]; v = X[j*d+k];
- X[i*d+k] = u*c+v*s;
- X[j*d+k] = v*c-u*s;
- }
- for (k=0; k<d; k++)
- { u = X[k*d+i]; v = X[k*d+j];
- X[k*d+i] = u*c+v*s;
- X[k*d+j] = v*c-u*s;
- }
- X[i*d+j] = X[j*d+i] = 0.0;
- for (k=0; k<d; k++)
- { u = P[k*d+i]; v = P[k*d+j];
- P[k*d+i] = u*c+v*s;
- P[k*d+j] = v*c-u*s;
- }
- ms = 1;
- }
- if (ms==0) return;
- }
- mut_printf("eig_dec not converged\n");
- }
- int eig_solve(J,x)
- jacobian *J;
- double *x;
- { int d, i, j, rank;
- double *D, *P, *Q, *w;
- double tol;
- D = J->Z;
- P = Q = J->Q;
- d = J->p;
- w = J->wk;
- tol = e_tol(D,d);
- rank = 0;
- for (i=0; i<d; i++)
- { w[i] = 0.0;
- for (j=0; j<d; j++) w[i] += P[j*d+i]*x[j];
- }
- for (i=0; i<d; i++)
- if (D[i*d+i]>tol)
- { w[i] /= D[i*(d+1)];
- rank++;
- }
- for (i=0; i<d; i++)
- { x[i] = 0.0;
- for (j=0; j<d; j++) x[i] += Q[i*d+j]*w[j];
- }
- return(rank);
- }
- int eig_hsolve(J,v)
- jacobian *J;
- double *v;
- { int i, j, p, rank;
- double *D, *Q, *w;
- double tol;
- D = J->Z;
- Q = J->Q;
- p = J->p;
- w = J->wk;
- tol = e_tol(D,p);
- rank = 0;
- for (i=0; i<p; i++)
- { w[i] = 0.0;
- for (j=0; j<p; j++) w[i] += Q[j*p+i]*v[j];
- }
- for (i=0; i<p; i++)
- { if (D[i*p+i]>tol)
- { v[i] = w[i]/sqrt(D[i*(p+1)]);
- rank++;
- }
- else v[i] = 0.0;
- }
- return(rank);
- }
- int eig_isolve(J,v)
- jacobian *J;
- double *v;
- { int i, j, p, rank;
- double *D, *Q, *w;
- double tol;
- D = J->Z;
- Q = J->Q;
- p = J->p;
- w = J->wk;
- tol = e_tol(D,p);
- rank = 0;
- for (i=0; i<p; i++)
- { if (D[i*p+i]>tol)
- { v[i] = w[i]/sqrt(D[i*(p+1)]);
- rank++;
- }
- else v[i] = 0.0;
- }
- for (i=0; i<p; i++)
- { w[i] = 0.0;
- for (j=0; j<p; j++) w[i] += Q[i*p+j]*v[j];
- }
- return(rank);
- }
- double eig_qf(J,v)
- jacobian *J;
- double *v;
- { int i, j, p;
- double sum, tol;
- p = J->p;
- sum = 0.0;
- tol = e_tol(J->Z,p);
- for (i=0; i<p; i++)
- if (J->Z[i*p+i]>tol)
- { J->wk[i] = 0.0;
- for (j=0; j<p; j++) J->wk[i] += J->Q[j*p+i]*v[j];
- sum += J->wk[i]*J->wk[i]/J->Z[i*p+i];
- }
- return(sum);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Integrate a function f over a circle or disc.
- */
- #include "mut.h"
- void setM(M,r,s,c,b)
- double *M, r, s, c;
- int b;
- { M[0] =-r*s; M[1] = r*c;
- M[2] = b*c; M[3] = b*s;
- M[4] =-r*c; M[5] = -s;
- M[6] = -s; M[7] = 0.0;
- M[8] =-r*s; M[9] = c;
- M[10]= c; M[11]= 0.0;
- }
- void integ_circ(f,r,orig,res,mint,b)
- int (*f)(), mint, b;
- double r, *orig, *res;
- { double y, x[2], theta, tres[MXRESULT], M[12], c, s;
- int i, j, nr;
-
- y = 0;
- for (i=0; i<mint; i++)
- { theta = 2*PI*(double)i/(double)mint;
- c = cos(theta); s = sin(theta);
- x[0] = orig[0]+r*c;
- x[1] = orig[1]+r*s;
- if (b!=0)
- { M[0] =-r*s; M[1] = r*c;
- M[2] = b*c; M[3] = b*s;
- M[4] =-r*c; M[5] = -s;
- M[6] = -s; M[7] = 0.0;
- M[8] =-r*s; M[9] = c;
- M[10]= c; M[11]= 0.0;
- }
- nr = f(x,2,tres,M);
- if (i==0) setzero(res,nr);
- for (j=0; j<nr; j++) res[j] += tres[j];
- }
- y = 2 * PI * ((b==0)?r:1.0) / mint;
- for (j=0; j<nr; j++) res[j] *= y;
- }
- void integ_disc(f,fb,fl,res,resb,mg)
- int (*f)(), (*fb)(), *mg;
- double *fl, *res, *resb;
- { double x[2], y, r, tres[MXRESULT], *orig, rmin, rmax, theta, c, s, M[12];
- int ct, ctb, i, j, k, nr, nrb, w;
- orig = &fl[2];
- rmax = fl[1];
- rmin = fl[0];
- y = 0.0;
- ct = ctb = 0;
- for (j=0; j<mg[1]; j++)
- { theta = 2*PI*(double)j/(double)mg[1];
- c = cos(theta); s = sin(theta);
- for (i= (rmin>0) ? 0 : 1; i<=mg[0]; i++)
- { r = rmin + (rmax-rmin)*i/mg[0];
- w = (2+2*(i&1)-(i==0)-(i==mg[0]));
- x[0] = orig[0] + r*c;
- x[1] = orig[1] + r*s;
- nr = f(x,2,tres,NULL);
- if (ct==0) setzero(res,nr);
- for (k=0; k<nr; k++) res[k] += w*r*tres[k];
- ct++;
- if (((i==0) | (i==mg[0])) && (fb!=NULL))
- { setM(M,r,s,c,1-2*(i==0));
- nrb = fb(x,2,tres,M);
- if (ctb==0) setzero(resb,nrb);
- ctb++;
- for (k=0; k<nrb; k++) resb[k] += tres[k];
- }
- }
- }
- /* for (i= (rmin>0) ? 0 : 1; i<=mg[0]; i++)
- {
- r = rmin + (rmax-rmin)*i/mg[0];
- w = (2+2*(i&1)-(i==0)-(i==mg[0]));
- for (j=0; j<mg[1]; j++)
- { theta = 2*PI*(double)j/(double)mg[1];
- c = cos(theta); s = sin(theta);
- x[0] = orig[0] + r*c;
- x[1] = orig[1] + r*s;
- nr = f(x,2,tres,NULL);
- if (ct==0) setzero(res,nr);
- ct++;
- for (k=0; k<nr; k++) res[k] += w*r*tres[k];
- if (((i==0) | (i==mg[0])) && (fb!=NULL))
- { setM(M,r,s,c,1-2*(i==0));
- nrb = fb(x,2,tres,M);
- if (ctb==0) setzero(resb,nrb);
- ctb++;
- for (k=0; k<nrb; k++) resb[k] += tres[k];
- }
- }
- } */
- for (j=0; j<nr; j++) res[j] *= 2*PI*(rmax-rmin)/(3*mg[0]*mg[1]);
- for (j=0; j<nrb; j++) resb[j] *= 2*PI/mg[1];
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Multivariate integration of a vector-valued function
- * using Monte-Carlo method.
- *
- * uses drand48() random number generator. Does not seed.
- */
- #include <stdlib.h>
- #include "mut.h"
- extern void setzero();
- static double M[(1+MXIDIM)*MXIDIM*MXIDIM];
- void monte(f,ll,ur,d,res,n)
- int (*f)(), d, n;
- double *ll, *ur, *res;
- {
- int i, j, nr;
- #ifdef WIN
- mut_printf("Sorry, Monte-Carlo Integration not enabled.\n");
- for (i=0; i<n; i++) res[i] = 0.0;
- #else
- double z, x[MXIDIM], tres[MXRESULT];
- srand48(234L);
- for (i=0; i<n; i++)
- { for (j=0; j<d; j++) x[j] = ll[j] + (ur[j]-ll[j])*drand48();
- nr = f(x,d,tres,NULL);
- if (i==0) setzero(res,nr);
- for (j=0; j<nr; j++) res[j] += tres[j];
- }
- z = 1;
- for (i=0; i<d; i++) z *= (ur[i]-ll[i]);
- for (i=0; i<nr; i++) res[i] *= z/n;
- #endif
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Multivariate integration of a vector-valued function
- * using Simpson's rule.
- */
- #include <math.h>
- #include "mut.h"
- extern void setzero();
- static double M[(1+MXIDIM)*MXIDIM*MXIDIM];
- /* third order corners */
- void simp3(fd,x,d,resd,delta,wt,i0,i1,mg,ct,res2,index)
- int (*fd)(), d, wt, i0, i1, *mg, ct, *index;
- double *x, *resd, *delta, *res2;
- { int k, l, m, nrd;
- double zb;
- for (k=i1+1; k<d; k++) if ((index[k]==0) | (index[k]==mg[k]))
- {
- setzero(M,d*d);
- m = 0; zb = 1.0;
- for (l=0; l<d; l++)
- if ((l!=i0) & (l!=i1) & (l!=k))
- { M[m*d+l] = 1.0;
- m++;
- zb *= delta[l];
- }
- M[(d-3)*d+i0] = (index[i0]==0) ? -1 : 1;
- M[(d-2)*d+i1] = (index[i1]==0) ? -1 : 1;
- M[(d-1)*d+k] = (index[k]==0) ? -1 : 1;
- nrd = fd(x,d,res2,M);
- if ((ct==0) & (i0==0) & (i1==1) & (k==2)) setzero(resd,nrd);
- for (l=0; l<nrd; l++)
- resd[l] += wt*zb*res2[l];
- }
- }
- /* second order corners */
- void simp2(fc,fd,x,d,resc,resd,delta,wt,i0,mg,ct,res2,index)
- int (*fc)(), (*fd)(), d, wt, i0, *mg, ct, *index;
- double *x, *resc, *resd, *delta, *res2;
- { int j, k, l, nrc;
- double zb;
- for (j=i0+1; j<d; j++) if ((index[j]==0) | (index[j]==mg[j]))
- { setzero(M,d*d);
- l = 0; zb = 1;
- for (k=0; k<d; k++) if ((k!=i0) & (k!=j))
- { M[l*d+k] = 1.0;
- l++;
- zb *= delta[k];
- }
- M[(d-2)*d+i0] = (index[i0]==0) ? -1 : 1;
- M[(d-1)*d+j] = (index[j]==0) ? -1 : 1;
- nrc = fc(x,d,res2,M);
- if ((ct==0) & (i0==0) & (j==1)) setzero(resc,nrc);
- for (k=0; k<nrc; k++) resc[k] += wt*zb*res2[k];
-
- if (fd!=NULL)
- simp3(fd,x,d,resd,delta,wt,i0,j,mg,ct,res2,index);
- }
- }
- /* first order boundary */
- void simp1(fb,fc,fd,x,d,resb,resc,resd,delta,wt,mg,ct,res2,index)
- int (*fb)(), (*fc)(), (*fd)(), d, wt, *mg, ct, *index;
- double *x, *resb, *resc, *resd, *delta, *res2;
- { int i, j, k, nrb;
- double zb;
- for (i=0; i<d; i++) if ((index[i]==0) | (index[i]==mg[i]))
- { setzero(M,(1+d)*d*d);
- k = 0;
- for (j=0; j<d; j++) if (j!=i)
- { M[k*d+j] = 1;
- k++;
- }
- M[(d-1)*d+i] = (index[i]==0) ? -1 : 1;
- nrb = fb(x,d,res2,M);
- zb = 1;
- for (j=0; j<d; j++) if (i!=j) zb *= delta[j];
- if ((ct==0) && (i==0))
- for (j=0; j<nrb; j++) resb[j] = 0.0;
- for (j=0; j<nrb; j++) resb[j] += wt*zb*res2[j];
- if (fc!=NULL)
- simp2(fc,fd,x,d,resc,resd,delta,wt,i,mg,ct,res2,index);
- }
- }
- void simpson4(f,fb,fc,fd,ll,ur,d,res,resb,resc,resd,mg,res2)
- int (*f)(), (*fb)(), (*fc)(), (*fd)(), d, *mg;
- double *ll, *ur, *res, *resb, *resc, *resd, *res2;
- { int ct, i, j, nr, wt, index[MXIDIM];
- double x[MXIDIM], delta[MXIDIM], z;
- for (i=0; i<d; i++)
- { index[i] = 0;
- x[i] = ll[i];
- if (mg[i]&1) mg[i]++;
- delta[i] = (ur[i]-ll[i])/(3*mg[i]);
- }
- ct = 0;
- while(1)
- { wt = 1;
- for (i=0; i<d; i++)
- wt *= (4-2*(index[i]%2==0)-(index[i]==0)-(index[i]==mg[i]));
- nr = f(x,d,res2,NULL);
- if (ct==0) setzero(res,nr);
- for (i=0; i<nr; i++) res[i] += wt*res2[i];
- if (fb!=NULL)
- simp1(fb,fc,fd,x,d,resb,resc,resd,delta,wt,mg,ct,res2,index);
- /* compute next grid point */
- for (i=0; i<d; i++)
- { index[i]++;
- if (index[i]>mg[i])
- { index[i] = 0;
- x[i] = ll[i];
- if (i==d-1) /* done */
- { z = 1.0;
- for (j=0; j<d; j++) z *= delta[j];
- for (j=0; j<nr; j++) res[j] *= z;
- return;
- }
- }
- else
- { x[i] = ll[i] + 3*delta[i]*index[i];
- i = d;
- }
- }
- ct++;
- }
- }
- void simpsonm(f,ll,ur,d,res,mg,res2)
- int (*f)(), d, *mg;
- double *ll, *ur, *res, *res2;
- { simpson4(f,NULL,NULL,NULL,ll,ur,d,res,NULL,NULL,NULL,mg,res2);
- }
- double simpson(f,l0,l1,m)
- double (*f)(), l0, l1;
- int m;
- { double x, sum;
- int i;
- sum = 0;
- for (i=0; i<=m; i++)
- { x = ((m-i)*l0 + i*l1)/m;
- sum += (2+2*(i&1)-(i==0)-(i==m)) * f(x);
- }
- return( (l1-l0) * sum / (3*m) );
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mut.h"
- static double *res, *resb, *orig, rmin, rmax;
- static int ct0;
- void sphM(M,r,u)
- double *M, r, *u;
- { double h, u1[3], u2[3];
- /* set the orthogonal unit vectors. */
- h = sqrt(u[0]*u[0]+u[1]*u[1]);
- if (h<=0)
- { u1[0] = u2[1] = 1.0;
- u1[1] = u1[2] = u2[0] = u2[2] = 0.0;
- }
- else
- { u1[0] = u[1]/h; u1[1] = -u[0]/h; u1[2] = 0.0;
- u2[0] = u[2]*u[0]/h; u2[1] = u[2]*u[1]/h; u2[2] = -h;
- }
- /* parameterize the sphere as r(cos(t)cos(v)u + sin(t)u1 + cos(t)sin(v)u2).
- * first layer of M is (dx/dt, dx/dv, dx/dr) at t=v=0.
- */
- M[0] = r*u1[0]; M[1] = r*u1[1]; M[2] = r*u1[2];
- M[3] = r*u2[0]; M[4] = r*u2[1]; M[5] = r*u2[2];
- M[6] = u[0]; M[7] = u[1]; M[8] = u[2];
- /* next layers are second derivative matrix of components of x(r,t,v).
- * d^2x/dt^2 = d^2x/dv^2 = -ru; d^2x/dtdv = 0;
- * d^2x/drdt = u1; d^2x/drdv = u2; d^2x/dr^2 = 0.
- */
- M[9] = M[13] = -r*u[0];
- M[11]= M[15] = u1[0];
- M[14]= M[16] = u2[0];
- M[10]= M[12] = M[17] = 0.0;
- M[18]= M[22] = -r*u[1];
- M[20]= M[24] = u1[1];
- M[23]= M[25] = u2[1];
- M[19]= M[21] = M[26] = 0.0;
- M[27]= M[31] = -r*u[1];
- M[29]= M[33] = u1[1];
- M[32]= M[34] = u2[1];
- M[28]= M[30] = M[35] = 0.0;
- }
- double ip3(a,b)
- double *a, *b;
- { return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
- }
- void rn3(a)
- double *a;
- { double s;
- s = sqrt(ip3(a,a));
- a[0] /= s; a[1] /= s; a[2] /= s;
- }
- double sptarea(a,b,c)
- double *a, *b, *c;
- { double ea, eb, ec, yab, yac, ybc, sab, sac, sbc;
- double ab[3], ac[3], bc[3], x1[3], x2[3];
- ab[0] = a[0]-b[0]; ab[1] = a[1]-b[1]; ab[2] = a[2]-b[2];
- ac[0] = a[0]-c[0]; ac[1] = a[1]-c[1]; ac[2] = a[2]-c[2];
- bc[0] = b[0]-c[0]; bc[1] = b[1]-c[1]; bc[2] = b[2]-c[2];
-
- yab = ip3(ab,a); yac = ip3(ac,a); ybc = ip3(bc,b);
- x1[0] = ab[0] - yab*a[0]; x2[0] = ac[0] - yac*a[0];
- x1[1] = ab[1] - yab*a[1]; x2[1] = ac[1] - yac*a[1];
- x1[2] = ab[2] - yab*a[2]; x2[2] = ac[2] - yac*a[2];
- sab = ip3(x1,x1); sac = ip3(x2,x2);
- ea = acos(ip3(x1,x2)/sqrt(sab*sac));
- x1[0] = ab[0] + yab*b[0]; x2[0] = bc[0] - ybc*b[0];
- x1[1] = ab[1] + yab*b[1]; x2[1] = bc[1] - ybc*b[1];
- x1[2] = ab[2] + yab*b[2]; x2[2] = bc[2] - ybc*b[2];
- sbc = ip3(x2,x2);
- eb = acos(ip3(x1,x2)/sqrt(sab*sbc));
- x1[0] = ac[0] + yac*c[0]; x2[0] = bc[0] + ybc*c[0];
- x1[1] = ac[1] + yac*c[1]; x2[1] = bc[1] + ybc*c[1];
- x1[2] = ac[2] + yac*c[2]; x2[2] = bc[2] + ybc*c[2];
- ec = acos(ip3(x1,x2)/sqrt(sac*sbc));
- /*
- * Euler's formula is a+b+c-PI, except I've cheated...
- * a=ea, c=ec, b=PI-eb, which is more stable.
- */
- return(ea+ec-eb);
- }
- void li(x,f,fb,mint,ar)
- double *x, ar;
- int (*f)(), (*fb)(), mint;
- { int i, j, nr, nrb, ct1, w;
- double u[3], r, M[36];
- double sres[MXRESULT], tres[MXRESULT];
- /* divide mint by 2, and force to even (Simpson's rule...)
- * to make comparable with rectangular interpretation of mint
- */
- mint <<= 1;
- if (mint&1) mint++;
- ct1 = 0;
- for (i= (rmin==0) ? 1 : 0; i<=mint; i++)
- {
- r = rmin + (rmax-rmin)*i/mint;
- w = 2+2*(i&1)-(i==0)-(i==mint);
- u[0] = orig[0]+x[0]*r;
- u[1] = orig[1]+x[1]*r;
- u[2] = orig[2]+x[2]*r;
- nr = f(u,3,tres,NULL);
- if (ct1==0) setzero(sres,nr);
- for (j=0; j<nr; j++)
- sres[j] += w*r*r*tres[j];
- ct1++;
- if ((fb!=NULL) && (i==mint)) /* boundary */
- { sphM(M,rmax,x);
- nrb = fb(u,3,tres,M);
- if (ct0==0) for (j=0; j<nrb; j++) resb[j] = 0.0;
- for (j=0; j<nrb; j++)
- resb[j] += tres[j]*ar;
- }
- }
- if (ct0==0) for (j=0; j<nr; j++) res[j] = 0.0;
- ct0++;
- for (j=0; j<nr; j++)
- res[j] += sres[j] * ar * (rmax-rmin)/(3*mint);
- }
- void sphint(f,fb,a,b,c,lev,mint,cent)
- double *a, *b, *c;
- int (*f)(), (*fb)(), lev, mint, cent;
- { double x[3], ab[3], ac[3], bc[3], ar;
- int i;
- if (lev>1)
- { ab[0] = a[0]+b[0]; ab[1] = a[1]+b[1]; ab[2] = a[2]+b[2]; rn3(ab);
- ac[0] = a[0]+c[0]; ac[1] = a[1]+c[1]; ac[2] = a[2]+c[2]; rn3(ac);
- bc[0] = b[0]+c[0]; bc[1] = b[1]+c[1]; bc[2] = b[2]+c[2]; rn3(bc);
- lev >>= 1;
- if (cent==0)
- { sphint(f,fb,a,ab,ac,lev,mint,1);
- sphint(f,fb,ab,bc,ac,lev,mint,0);
- }
- else
- { sphint(f,fb,a,ab,ac,lev,mint,1);
- sphint(f,fb,b,ab,bc,lev,mint,1);
- sphint(f,fb,c,ac,bc,lev,mint,1);
- sphint(f,fb,ab,bc,ac,lev,mint,1);
- }
- return;
- }
- x[0] = a[0]+b[0]+c[0];
- x[1] = a[1]+b[1]+c[1];
- x[2] = a[2]+b[2]+c[2];
- rn3(x);
- ar = sptarea(a,b,c);
- for (i=0; i<8; i++)
- { if (i>0)
- { x[0] = -x[0];
- if (i%2 == 0) x[1] = -x[1];
- if (i==4) x[2] = -x[2];
- }
- switch(cent)
- { case 2: /* the reflection and its 120', 240' rotations */
- ab[0] = x[0]; ab[1] = x[2]; ab[2] = x[1]; li(ab,f,fb,mint,ar);
- ab[0] = x[2]; ab[1] = x[1]; ab[2] = x[0]; li(ab,f,fb,mint,ar);
- ab[0] = x[1]; ab[1] = x[0]; ab[2] = x[2]; li(ab,f,fb,mint,ar);
- case 1: /* and the 120' and 240' rotations */
- ab[0] = x[1]; ab[1] = x[2]; ab[2] = x[0]; li(ab,f,fb,mint,ar);
- ac[0] = x[2]; ac[1] = x[0]; ac[2] = x[1]; li(ac,f,fb,mint,ar);
- case 0: /* and the triangle itself. */
- li( x,f,fb,mint,ar);
- }
- }
- }
- void integ_sphere(f,fb,fl,Res,Resb,mg)
- double *fl, *Res, *Resb;
- int (*f)(), (*fb)(), *mg;
- { double a[3], b[3], c[3];
- a[0] = 1; a[1] = a[2] = 0;
- b[1] = 1; b[0] = b[2] = 0;
- c[2] = 1; c[0] = c[1] = 0;
-
- res = Res;
- resb=Resb;
- orig = &fl[2];
- rmin = fl[0];
- rmax = fl[1];
- ct0 = 0;
- sphint(f,fb,a,b,c,mg[1],mg[0],0);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * solving symmetric equations using the jacobian structure. Currently, three
- * methods can be used: cholesky decomposition, eigenvalues, eigenvalues on
- * the correlation matrix.
- *
- * jacob_dec(J,meth) decompose the matrix, meth=JAC_CHOL, JAC_EIG, JAC_EIGD
- * jacob_solve(J,v) J^{-1}v
- * jacob_hsolve(J,v) (R')^{-1/2}v
- * jacob_isolve(J,v) (R)^{-1/2}v
- * jacob_qf(J,v) v' J^{-1} v
- * jacob_mult(J,v) (R'R) v (pres. CHOL only)
- * where for each decomposition, R'R=J, although the different decomp's will
- * produce different R's.
- *
- * To set up the J matrix:
- * first, allocate storage: jac_alloc(J,p,wk)
- * where p=dimension of matrix, wk is a numeric vector of length
- * jac_reqd(p) (or NULL, to allocate automatically).
- * now, copy the numeric values to J->Z (numeric vector with length p*p).
- * (or, just set J->Z to point to the data vector. But remember this
- * will be overwritten by the decomposition).
- * finally, set:
- * J->st=JAC_RAW;
- * J->p = p;
- *
- * now, call jac_dec(J,meth) (optional) and the solve functions as required.
- *
- */
- #include "math.h"
- #include "mut.h"
- #define DEF_METH JAC_EIGD
- int jac_reqd(int p) { return(2*p*(p+1)); }
- double *jac_alloc(J,p,wk)
- jacobian *J;
- int p;
- double *wk;
- { if (wk==NULL)
- wk = (double *)calloc(2*p*(p+1),sizeof(double));
- if ( wk == NULL ) {
- printf("Problem allocating memory for wk\n");fflush(stdout);
- }
- J->Z = wk; wk += p*p;
- J->Q = wk; wk += p*p;
- J->wk= wk; wk += p;
- J->dg= wk; wk += p;
- return(wk);
- }
- void jacob_dec(J, meth)
- jacobian *J;
- int meth;
- { int i, j, p;
- if (J->st != JAC_RAW) return;
- J->sm = J->st = meth;
- switch(meth)
- { case JAC_EIG:
- eig_dec(J->Z,J->Q,J->p);
- return;
- case JAC_EIGD:
- p = J->p;
- for (i=0; i<p; i++)
- J->dg[i] = (J->Z[i*(p+1)]<=0) ? 0.0 : 1/sqrt(J->Z[i*(p+1)]);
- for (i=0; i<p; i++)
- for (j=0; j<p; j++)
- J->Z[i*p+j] *= J->dg[i]*J->dg[j];
- eig_dec(J->Z,J->Q,J->p);
- J->st = JAC_EIGD;
- return;
- case JAC_CHOL:
- chol_dec(J->Z,J->p,J->p);
- return;
- default: mut_printf("jacob_dec: unknown method %d",meth);
- }
- }
- int jacob_solve(J,v) /* (X^T W X)^{-1} v */
- jacobian *J;
- double *v;
- { int i, rank;
- if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);
- switch(J->st)
- { case JAC_EIG:
- return(eig_solve(J,v));
- case JAC_EIGD:
- for (i=0; i<J->p; i++) v[i] *= J->dg[i];
- rank = eig_solve(J,v);
- for (i=0; i<J->p; i++) v[i] *= J->dg[i];
- return(rank);
- case JAC_CHOL:
- return(chol_solve(J->Z,v,J->p,J->p));
- }
- mut_printf("jacob_solve: unknown method %d",J->st);
- return(0);
- }
- int jacob_hsolve(J,v) /* J^{-1/2} v */
- jacobian *J;
- double *v;
- { int i;
- if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);
- switch(J->st)
- { case JAC_EIG:
- return(eig_hsolve(J,v));
- case JAC_EIGD: /* eigenvalues on corr matrix */
- for (i=0; i<J->p; i++) v[i] *= J->dg[i];
- return(eig_hsolve(J,v));
- case JAC_CHOL:
- return(chol_hsolve(J->Z,v,J->p,J->p));
- }
- mut_printf("jacob_hsolve: unknown method %d\n",J->st);
- return(0);
- }
- int jacob_isolve(J,v) /* J^{-1/2} v */
- jacobian *J;
- double *v;
- { int i, r;
- if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);
- switch(J->st)
- { case JAC_EIG:
- return(eig_isolve(J,v));
- case JAC_EIGD: /* eigenvalues on corr matrix */
- r = eig_isolve(J,v);
- for (i=0; i<J->p; i++) v[i] *= J->dg[i];
- return(r);
- case JAC_CHOL:
- return(chol_isolve(J->Z,v,J->p,J->p));
- }
- mut_printf("jacob_hsolve: unknown method %d\n",J->st);
- return(0);
- }
- double jacob_qf(J,v) /* vT J^{-1} v */
- jacobian *J;
- double *v;
- { int i;
- if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);
- switch (J->st)
- { case JAC_EIG:
- return(eig_qf(J,v));
- case JAC_EIGD:
- for (i=0; i<J->p; i++) v[i] *= J->dg[i];
- return(eig_qf(J,v));
- case JAC_CHOL:
- return(chol_qf(J->Z,v,J->p,J->p));
- default:
- mut_printf("jacob_qf: invalid method\n");
- return(0.0);
- }
- }
- int jacob_mult(J,v) /* J v */
- jacobian *J;
- double *v;
- {
- if (J->st == JAC_RAW) jacob_dec(J,DEF_METH);
- switch (J->st)
- { case JAC_CHOL:
- return(chol_mult(J->Z,v,J->p,J->p));
- default:
- mut_printf("jacob_mult: invalid method\n");
- return(0);
- }
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Routines for maximization of a one dimensional function f()
- * over an interval [xlo,xhi]. In all cases. the flag argument
- * controls the return:
- * flag='x', the maximizer xmax is returned.
- * otherwise, maximum f(xmax) is returned.
- *
- * max_grid(f,xlo,xhi,n,flag)
- * grid maximization of f() over [xlo,xhi] with n intervals.
- *
- * max_golden(f,xlo,xhi,n,tol,err,flag)
- * golden section maximization.
- * If n>2, an initial grid search is performed with n intervals
- * (this helps deal with local maxima).
- * convergence criterion is |x-xmax| < tol.
- * err is an error flag.
- * if flag='x', return value is xmax.
- * otherwise, return value is f(xmax).
- *
- * max_quad(f,xlo,xhi,n,tol,err,flag)
- * quadratic maximization.
- *
- * max_nr()
- * newton-raphson, handles multivariate case.
- *
- * TODO: additional error checking, non-convergence stop.
- */
- #include <math.h>
- #include "mut.h"
- #define max_val(a,b) ((flag=='x') ? a : b)
- double max_grid(f,xlo,xhi,n,flag)
- double (*f)(), xlo, xhi;
- int n;
- char flag;
- { int i, mi;
- double x, y, mx, my;
- for (i=0; i<=n; i++)
- { x = xlo + (xhi-xlo)*i/n;
- y = f(x);
- if ((i==0) || (y>my))
- { mx = x;
- my = y;
- mi = i;
- }
- }
- if (mi==0) return(max_val(xlo,my));
- if (mi==n) return(max_val(xhi,my));
- return(max_val(mx,my));
- }
- double max_golden(f,xlo,xhi,n,tol,err,flag)
- double (*f)(), xhi, xlo, tol;
- int n, *err;
- char flag;
- { double dlt, x0, x1, x2, x3, y0, y1, y2, y3;
- *err = 0;
- if (n>2)
- { dlt = (xhi-xlo)/n;
- x0 = max_grid(f,xlo,xhi,n,'x');
- if (xlo<x0) xlo = x0-dlt;
- if (xhi>x0) xhi = x0+dlt;
- }
- x0 = xlo; y0 = f(xlo);
- x3 = xhi; y3 = f(xhi);
- x1 = gold_rat*x0 + (1-gold_rat)*x3; y1 = f(x1);
- x2 = gold_rat*x3 + (1-gold_rat)*x0; y2 = f(x2);
- while (fabs(x3-x0)>tol)
- { if ((y1>=y0) && (y1>=y2))
- { x3 = x2; y3 = y2;
- x2 = x1; y2 = y1;
- x1 = gold_rat*x0 + (1-gold_rat)*x3; y1 = f(x1);
- }
- else if ((y2>=y3) && (y2>=y1))
- { x0 = x1; y0 = y1;
- x1 = x2; y1 = y2;
- x2 = gold_rat*x3 + (1-gold_rat)*x0; y2 = f(x2);
- }
- else
- { if (y3>y0) { x0 = x2; y0 = y2; }
- else { x3 = x1; y3 = y1; }
- x1 = gold_rat*x0 + (1-gold_rat)*x3; y1 = f(x1);
- x2 = gold_rat*x3 + (1-gold_rat)*x0; y2 = f(x2);
- }
- }
- if (y0>=y1) return(max_val(x0,y0));
- if (y3>=y2) return(max_val(x3,y3));
- return((y1>y2) ? max_val(x1,y1) : max_val(x2,y2));
- }
- double max_quad(f,xlo,xhi,n,tol,err,flag)
- double (*f)(), xhi, xlo, tol;
- int n, *err;
- char flag;
- { double x0, x1, x2, xnew, y0, y1, y2, ynew, a, b;
- *err = 0;
- if (n>2)
- { x0 = max_grid(f,xlo,xhi,n,'x');
- if (xlo<x0) xlo = x0-1.0/n;
- if (xhi>x0) xhi = x0+1.0/n;
- }
- x0 = xlo; y0 = f(x0);
- x2 = xhi; y2 = f(x2);
- x1 = (x0+x2)/2; y1 = f(x1);
- while (x2-x0>tol)
- {
- /* first, check (y0,y1,y2) is a peak. If not,
- * next interval is the halve with larger of (y0,y2).
- */
- if ((y0>y1) | (y2>y1))
- {
- if (y0>y2) { x2 = x1; y2 = y1; }
- else { x0 = x1; y0 = y1; }
- x1 = (x0+x2)/2;
- y1 = f(x1);
- }
- else /* peak */
- { a = (y1-y0)*(x2-x1) + (y1-y2)*(x1-x0);
- b = ((y1-y0)*(x2-x1)*(x2+x1) + (y1-y2)*(x1-x0)*(x1+x0))/2;
- /* quadratic maximizer is b/a. But first check if a's too
- * small, since we may be close to constant.
- */
- if ((a<=0) | (b<x0*a) | (b>x2*a))
- { /* split the larger halve */
- xnew = ((x2-x1) > (x1-x0)) ? (x1+x2)/2 : (x0+x1)/2;
- }
- else
- { xnew = b/a;
- if (10*xnew < (9*x0+x1)) xnew = (9*x0+x1)/10;
- if (10*xnew > (9*x2+x1)) xnew = (9*x2+x1)/10;
- if (fabs(xnew-x1) < 0.001*(x2-x0))
- {
- if ((x2-x1) > (x1-x0))
- xnew = (99*x1+x2)/100;
- else
- xnew = (99*x1+x0)/100;
- }
- }
- ynew = f(xnew);
- if (xnew>x1)
- { if (ynew >= y1) { x0 = x1; y0 = y1; x1 = xnew; y1 = ynew; }
- else { x2 = xnew; y2 = ynew; }
- }
- else
- { if (ynew >= y1) { x2 = x1; y2 = y1; x1 = xnew; y1 = ynew; }
- else { x0 = xnew; y0 = ynew; }
- }
- }
- }
- return(max_val(x1,y1));
- }
- double max_nr(F, coef, old_coef, f1, delta, J, p, maxit, tol, err)
- double *coef, *old_coef, *f1, *delta, tol;
- int (*F)(), p, maxit, *err;
- jacobian *J;
- { double old_f, f, lambda;
- int i, j, fr;
- double nc, nd, cut;
- int rank;
- *err = NR_OK;
- J->p = p;
- fr = F(coef, &f, f1, J->Z); J->st = JAC_RAW;
- for (i=0; i<maxit; i++)
- { memcpy(old_coef,coef,p*sizeof(double));
- old_f = f;
- rank = jacob_solve(J,f1);
- memcpy(delta,f1,p*sizeof(double));
- if (rank==0) /* NR won't move! */
- delta[0] = -f/f1[0];
- lambda = 1.0;
- nc = innerprod(old_coef,old_coef,p);
- nd = innerprod(delta, delta, p);
- cut = sqrt(nc/nd);
- if (cut>1.0) cut = 1.0;
- cut *= 0.0001;
- do
- { for (j=0; j<p; j++) coef[j] = old_coef[j] + lambda*delta[j];
- f = old_f - 1.0;
- fr = F(coef, &f, f1, J->Z); J->st = JAC_RAW;
- if (fr==NR_BREAK) return(old_f);
- lambda = (fr==NR_REDUCE) ? lambda/2 : lambda/10.0;
- } while ((lambda>cut) & (f <= old_f - 1.0e-3));
- if (f < old_f - 1.0e-3)
- { *err = NR_NDIV;
- return(f);
- }
- if (fr==NR_REDUCE) return(f);
- if (fabs(f-old_f) < tol) return(f);
- }
- *err = NR_NCON;
- return(f);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include <math.h>
- #include "mut.h"
- /* qr decomposition of X (n*p organized by column).
- * Take w for the ride, if not NULL.
- */
- void qr(X,n,p,w)
- double *X, *w;
- int n, p;
- { int i, j, k, mi;
- double c, s, mx, nx, t;
- for (j=0; j<p; j++)
- { mi = j;
- mx = fabs(X[(n+1)*j]);
- nx = mx*mx;
- /* find the largest remaining element in j'th column, row mi.
- * flip that row with row j.
- */
- for (i=j+1; i<n; i++)
- { nx += X[j*n+i]*X[j*n+i];
- if (fabs(X[j*n+i])>mx)
- { mi = i;
- mx = fabs(X[j*n+i]);
- }
- }
- for (i=j; i<p; i++)
- { t = X[i*n+j];
- X[i*n+j] = X[i*n+mi];
- X[i*n+mi] = t;
- }
- if (w!=NULL) { t = w[j]; w[j] = w[mi]; w[mi] = t; }
- /* want the diag. element -ve, so we do the `good' Householder reflect.
- */
- if (X[(n+1)*j]>0)
- { for (i=j; i<p; i++) X[i*n+j] = -X[i*n+j];
- if (w!=NULL) w[j] = -w[j];
- }
- nx = sqrt(nx);
- c = nx*(nx-X[(n+1)*j]);
- if (c!=0)
- { for (i=j+1; i<p; i++)
- { s = 0;
- for (k=j; k<n; k++)
- s += X[i*n+k]*X[j*n+k];
- s = (s-nx*X[i*n+j])/c;
- for (k=j; k<n; k++)
- X[i*n+k] -= s*X[j*n+k];
- X[i*n+j] += s*nx;
- }
- if (w != NULL)
- { s = 0;
- for (k=j; k<n; k++)
- s += w[k]*X[n*j+k];
- s = (s-nx*w[j])/c;
- for (k=j; k<n; k++)
- w[k] -= s*X[n*j+k];
- w[j] += s*nx;
- }
- X[j*n+j] = nx;
- }
- }
- }
- void qrinvx(R,x,n,p)
- double *R, *x;
- int n, p;
- { int i, j;
- for (i=p-1; i>=0; i--)
- { for (j=i+1; j<p; j++) x[i] -= R[j*n+i]*x[j];
- x[i] /= R[i*n+i];
- }
- }
- void qrtinvx(R,x,n,p)
- double *R, *x;
- int n, p;
- { int i, j;
- for (i=0; i<p; i++)
- { for (j=0; j<i; j++) x[i] -= R[i*n+j]*x[j];
- x[i] /= R[i*n+i];
- }
- }
- void qrsolv(R,x,n,p)
- double *R, *x;
- int n, p;
- { qrtinvx(R,x,n,p);
- qrinvx(R,x,n,p);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * solve f(x)=c by various methods, with varying stability etc...
- * xlo and xhi should be initial bounds for the solution.
- * convergence criterion is |f(x)-c| < tol.
- *
- * double solve_bisect(f,c,xmin,xmax,tol,bd_flag,err)
- * double solve_secant(f,c,xmin,xmax,tol,bd_flag,err)
- * Bisection and secant methods for solving of f(x)=c.
- * xmin and xmax are starting values and bound for solution.
- * tol = convergence criterion, |f(x)-c| < tol.
- * bd_flag = if (xmin,xmax) doesn't bound a solution, what action to take?
- * BDF_NONE returns error.
- * BDF_EXPRIGHT increases xmax.
- * BDF_EXPLEFT decreases xmin.
- * err = error flag.
- * The (xmin,xmax) bound is not formally necessary for the secant method.
- * But having such a bound vastly improves stability; the code performs
- * a bisection step whenever the iterations run outside the bounds.
- *
- * double solve_nr(f,f1,c,x0,tol,err)
- * Newton-Raphson solution of f(x)=c.
- * f1 = f'(x).
- * x0 = starting value.
- * tol = convergence criteria, |f(x)-c| < tol.
- * err = error flag.
- * No stability checks at present.
- *
- * double solve_fp(f,x0,tol)
- * fixed-point iteration to solve f(x)=x.
- * x0 = starting value.
- * tol = convergence criteria, stops when |f(x)-x| < tol.
- * Convergence requires |f'(x)|<1 in neighborhood of true solution;
- * f'(x) \approx 0 gives the fastest convergence.
- * No stability checks at present.
- *
- * TODO: additional error checking, non-convergence stop.
- */
- #include <math.h>
- #include "mut.h"
- typedef struct {
- double xmin, xmax, x0, x1;
- double ymin, ymax, y0, y1;
- } solvest;
- int step_expand(f,c,sv,bd_flag)
- double (*f)(), c;
- solvest *sv;
- int bd_flag;
- { double x, y;
- if (sv->ymin*sv->ymax <= 0.0) return(0);
- if (bd_flag == BDF_NONE)
- { mut_printf("invalid bracket\n");
- return(1); /* error */
- }
- if (bd_flag == BDF_EXPRIGHT)
- { while (sv->ymin*sv->ymax > 0)
- { x = sv->xmax + 2*(sv->xmax-sv->xmin);
- y = f(x) - c;
- sv->xmin = sv->xmax; sv->xmax = x;
- sv->ymin = sv->ymax; sv->ymax = y;
- }
- return(0);
- }
- if (bd_flag == BDF_EXPLEFT)
- { while (sv->ymin*sv->ymax > 0)
- { x = sv->xmin - 2*(sv->xmax-sv->xmin);
- y = f(x) - c;
- sv->xmax = sv->xmin; sv->xmin = x;
- sv->ymax = sv->ymin; sv->ymin = y;
- }
- return(0);
- }
- mut_printf("step_expand: unknown bd_flag %d.\n",bd_flag);
- return(1);
- }
- int step_addin(sv,x,y)
- solvest *sv;
- double x, y;
- { sv->x1 = sv->x0; sv->x0 = x;
- sv->y1 = sv->y0; sv->y0 = y;
- if (y*sv->ymin > 0)
- { sv->xmin = x;
- sv->ymin = y;
- return(0);
- }
- if (y*sv->ymax > 0)
- { sv->xmax = x;
- sv->ymax = y;
- return(0);
- }
- if (y==0)
- { sv->xmin = sv->xmax = x;
- sv->ymin = sv->ymax = 0;
- return(0);
- }
- return(1);
- }
- int step_bisect(f,c,sv)
- double (*f)(), c;
- solvest *sv;
- { double x, y;
- x = sv->x0 = (sv->xmin + sv->xmax)/2;
- y = sv->y0 = f(x)-c;
- return(step_addin(sv,x,y));
- }
- double solve_bisect(f,c,xmin,xmax,tol,bd_flag,err)
- double (*f)(), c, xmin, xmax, tol;
- int bd_flag, *err;
- { solvest sv;
- int z;
- *err = 0;
- sv.xmin = xmin; sv.ymin = f(xmin)-c;
- sv.xmax = xmax; sv.ymax = f(xmax)-c;
- *err = step_expand(f,c,&sv,bd_flag);
- if (*err>0) return(sv.xmin);
- while(1) /* infinite loop if f is discontinuous */
- { z = step_bisect(f,c,&sv);
- if (z)
- { *err = 1;
- return(sv.x0);
- }
- if (fabs(sv.y0)<tol) return(sv.x0);
- }
- }
- int step_secant(f,c,sv)
- double (*f)(), c;
- solvest *sv;
- { double x, y;
- if (sv->y0==sv->y1) return(step_bisect(f,c,sv));
- x = sv->x0 + (sv->x1-sv->x0)*sv->y0/(sv->y0-sv->y1);
- if ((x<=sv->xmin) | (x>=sv->xmax)) return(step_bisect(f,c,sv));
- y = f(x)-c;
- return(step_addin(sv,x,y));
- }
- double solve_secant(f,c,xmin,xmax,tol,bd_flag,err)
- double (*f)(), c, xmin, xmax, tol;
- int bd_flag, *err;
- { solvest sv;
- int z;
- *err = 0;
- sv.xmin = xmin; sv.ymin = f(xmin)-c;
- sv.xmax = xmax; sv.ymax = f(xmax)-c;
- *err = step_expand(f,c,&sv,bd_flag);
- if (*err>0) return(sv.xmin);
- sv.x0 = sv.xmin; sv.y0 = sv.ymin;
- sv.x1 = sv.xmax; sv.y1 = sv.ymax;
- while(1) /* infinite loop if f is discontinuous */
- { z = step_secant(f,c,&sv);
- if (z)
- { *err = 1;
- return(sv.x0);
- }
- if (fabs(sv.y0)<tol) return(sv.x0);
- }
- }
- double solve_nr(f,f1,c,x0,tol,err)
- double (*f)(), (*f1)(), c, x0, tol;
- int *err;
- { double y;
- do
- { y = f(x0)-c;
- x0 -= y/f1(x0);
- } while (fabs(y)>tol);
- return(x0);
- }
- double solve_fp(f,x0,tol,maxit)
- double (*f)(), x0, tol;
- int maxit;
- { double x1;
- int i;
- for (i=0; i<maxit; i++)
- { x1 = f(x0);
- if (fabs(x1-x0)<tol) return(x1);
- x0 = x1;
- }
- return(x1); /* although it hasn't converged */
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mut.h"
- void svd(x,p,q,d,mxit) /* svd of square matrix */
- double *x, *p, *q;
- int d, mxit;
- { int i, j, k, iter, ms, zer;
- double r, u, v, cp, cm, sp, sm, c1, c2, s1, s2, mx;
- for (i=0; i<d; i++)
- for (j=0; j<d; j++) p[i*d+j] = q[i*d+j] = (i==j);
- for (iter=0; iter<mxit; iter++)
- { ms = 0;
- for (i=0; i<d; i++)
- for (j=i+1; j<d; j++)
- { s1 = fabs(x[i*d+j]);
- s2 = fabs(x[j*d+i]);
- mx = (s1>s2) ? s1 : s2;
- zer = 1;
- if (mx*mx>1.0e-15*fabs(x[i*d+i]*x[j*d+j]))
- { if (fabs(x[i*(d+1)])<fabs(x[j*(d+1)]))
- { for (k=0; k<d; k++)
- { u = x[i*d+k]; x[i*d+k] = x[j*d+k]; x[j*d+k] = u;
- u = p[k*d+i]; p[k*d+i] = p[k*d+j]; p[k*d+j] = u;
- }
- for (k=0; k<d; k++)
- { u = x[k*d+i]; x[k*d+i] = x[k*d+j]; x[k*d+j] = u;
- u = q[k*d+i]; q[k*d+i] = q[k*d+j]; q[k*d+j] = u;
- }
- }
- cp = x[i*(d+1)]+x[j*(d+1)];
- sp = x[j*d+i]-x[i*d+j];
- r = sqrt(cp*cp+sp*sp);
- if (r>0) { cp /= r; sp /= r; }
- else { cp = 1.0; zer = 0;}
- cm = x[i*(d+1)]-x[j*(d+1)];
- sm = x[i*d+j]+x[j*d+i];
- r = sqrt(cm*cm+sm*sm);
- if (r>0) { cm /= r; sm /= r; }
- else { cm = 1.0; zer = 0;}
- c1 = cm+cp;
- s1 = sm+sp;
- r = sqrt(c1*c1+s1*s1);
- if (r>0) { c1 /= r; s1 /= r; }
- else { c1 = 1.0; zer = 0;}
- if (fabs(s1)>ms) ms = fabs(s1);
- c2 = cm+cp;
- s2 = sp-sm;
- r = sqrt(c2*c2+s2*s2);
- if (r>0) { c2 /= r; s2 /= r; }
- else { c2 = 1.0; zer = 0;}
- for (k=0; k<d; k++)
- { u = x[i*d+k]; v = x[j*d+k];
- x[i*d+k] = c1*u+s1*v;
- x[j*d+k] = c1*v-s1*u;
- u = p[k*d+i]; v = p[k*d+j];
- p[k*d+i] = c1*u+s1*v;
- p[k*d+j] = c1*v-s1*u;
- }
- for (k=0; k<d; k++)
- { u = x[k*d+i]; v = x[k*d+j];
- x[k*d+i] = c2*u-s2*v;
- x[k*d+j] = s2*u+c2*v;
- u = q[k*d+i]; v = q[k*d+j];
- q[k*d+i] = c2*u-s2*v;
- q[k*d+j] = s2*u+c2*v;
- }
- if (zer) x[i*d+j] = x[j*d+i] = 0.0;
- ms = 1;
- }
- }
- if (ms==0) iter=mxit+10;
- }
- if (iter==mxit) mut_printf("Warning: svd not converged.\n");
- for (i=0; i<d; i++)
- if (x[i*d+i]<0)
- { x[i*d+i] = -x[i*d+i];
- for (j=0; j<d; j++) p[j*d+i] = -p[j*d+i];
- }
- }
- int svdsolve(x,w,P,D,Q,d,tol) /* original X = PDQ^T; comp. QD^{-1}P^T x */
- double *x, *w, *P, *D, *Q, tol;
- int d;
- { int i, j, rank;
- double mx;
- if (tol>0)
- { mx = D[0];
- for (i=1; i<d; i++) if (D[i*(d+1)]>mx) mx = D[i*(d+1)];
- tol *= mx;
- }
- rank = 0;
- for (i=0; i<d; i++)
- { w[i] = 0.0;
- for (j=0; j<d; j++) w[i] += P[j*d+i]*x[j];
- }
- for (i=0; i<d; i++)
- if (D[i*d+i]>tol)
- { w[i] /= D[i*(d+1)];
- rank++;
- }
- for (i=0; i<d; i++)
- { x[i] = 0.0;
- for (j=0; j<d; j++) x[i] += Q[i*d+j]*w[j];
- }
- return(rank);
- }
- void hsvdsolve(x,w,P,D,Q,d,tol) /* original X = PDQ^T; comp. D^{-1/2}P^T x */
- double *x, *w, *P, *D, *Q, tol;
- int d;
- { int i, j;
- double mx;
- if (tol>0)
- { mx = D[0];
- for (i=1; i<d; i++) if (D[i*(d+1)]>mx) mx = D[i*(d+1)];
- tol *= mx;
- }
- for (i=0; i<d; i++)
- { w[i] = 0.0;
- for (j=0; j<d; j++) w[i] += P[j*d+i]*x[j];
- }
- for (i=0; i<d; i++) if (D[i*d+i]>tol) w[i] /= sqrt(D[i*(d+1)]);
- for (i=0; i<d; i++) x[i] = w[i];
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Includes some miscellaneous vector functions:
- * setzero(v,p) sets all elements of v to 0.
- * unitvec(x,k,p) sets x to k'th unit vector e_k.
- * innerprod(v1,v2,p) inner product.
- * addouter(A,v1,v2,p,c) A <- A + c * v_1 v2^T
- * multmatscal(A,z,n) A <- A*z
- * matrixmultiply(A,B,C,m,n,p) C(m*p) <- A(m*n) * B(n*p)
- * transpose(x,m,n) inline transpose
- * m_trace(x,n) trace
- * vecsum(x,n) sum elements.
- */
- #include "mut.h"
- void setzero(v,p)
- double *v;
- int p;
- { int i;
- for (i=0; i<p; i++) v[i] = 0.0;
- }
- void unitvec(x,k,p)
- double *x;
- int k, p;
- { setzero(x,p);
- x[k] = 1.0;
- }
- double innerprod(v1,v2,p)
- double *v1, *v2;
- int p;
- { int i;
- double s;
- s = 0;
- for (i=0; i<p; i++) s += v1[i]*v2[i];
- return(s);
- }
- void addouter(A,v1,v2,p,c)
- double *A, *v1, *v2, c;
- int p;
- { int i, j;
- for (i=0; i<p; i++)
- for (j=0; j<p; j++)
- A[i*p+j] += c*v1[i]*v2[j];
- }
- void multmatscal(A,z,n)
- double *A, z;
- int n;
- { int i;
- for (i=0; i<n; i++) A[i] *= z;
- }
- /* matrix multiply A (m*n) times B (n*p).
- * store in C (m*p).
- * all matrices stored by column.
- */
- void matrixmultiply(A,B,C,m,n,p)
- double *A, *B, *C;
- int m, n, p;
- { int i, j, k, ij;
- for (i=0; i<m; i++)
- for (j=0; j<p; j++)
- { ij = j*m+i;
- C[ij] = 0.0;
- for (k=0; k<n; k++)
- C[ij] += A[k*m+i] * B[j*n+k];
- }
- }
- /*
- * transpose() transposes an m*n matrix in place.
- * At input, the matrix has n rows, m columns and
- * x[0..n-1] is the is the first column.
- * At output, the matrix has m rows, n columns and
- * x[0..m-1] is the first column.
- */
- void transpose(x,m,n)
- double *x;
- int m, n;
- { int t0, t, ti, tj;
- double z;
- for (t0=1; t0<m*n-2; t0++)
- { ti = t0%m; tj = t0/m;
- do
- { t = ti*n+tj;
- ti= t%m;
- tj= t/m;
- } while (t<t0);
- z = x[t];
- x[t] = x[t0];
- x[t0] = z;
- }
- }
- /* trace of an n*n square matrix. */
- double m_trace(x,n)
- double *x;
- int n;
- { int i;
- double sum;
- sum = 0;
- for (i=0; i<n; i++)
- sum += x[i*(n+1)];
- return(sum);
- }
- double vecsum(v,n)
- double *v;
- int n;
- { int i;
- double sum;
- sum = 0.0;
- for (i=0; i<n; i++) sum += v[i];
- return(sum);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- miscellaneous functions that may not be defined in the math
- libraries. The implementations are crude.
- mut_daws(x) -- dawson's function
- mut_exp(x) -- exp(x), but it won't overflow.
- where required, these must be #define'd in header files.
- also includes
- ptail(x) -- exp(x*x/2)*int_{-\infty}^x exp(-u^2/2)du for x < -6.
- logit(x) -- logistic function.
- expit(x) -- inverse of logit.
- factorial(n)-- factorial
- */
- #include "mut.h"
- double mut_exp(x)
- double x;
- { if (x>700.0) return(1.014232054735004e+304);
- return(exp(x));
- }
- double mut_daws(x)
- double x;
- { static double val[] = {
- 0, 0.24485619356002, 0.46034428261948, 0.62399959848185, 0.72477845900708,
- 0.76388186132749, 0.75213621001998, 0.70541701910853, 0.63998807456541,
- 0.56917098836654, 0.50187821196415, 0.44274283060424, 0.39316687916687,
- 0.35260646480842, 0.31964847250685, 0.29271122077502, 0.27039629581340,
- 0.25160207761769, 0.23551176224443, 0.22153505358518, 0.20924575719548,
- 0.19833146819662, 0.18855782729305, 0.17974461154688, 0.17175005072385 };
- double h, f0, f1, f2, y, z, xx;
- int j, m;
- if (x<0) return(-mut_daws(-x));
- if (x>6)
- { /* Tail series: 1/x + 1/x^3 + 1.3/x^5 + 1.3.5/x^7 + ... */
- y = z = 1/x;
- j = 0;
- while (((f0=(2*j+1)/(x*x))<1) && (y>1.0e-10*z))
- { y *= f0;
- z += y;
- j++;
- }
- return(z);
- }
- m = (int) (4*x);
- h = x-0.25*m;
- if (h>0.125)
- { m++;
- h = h-0.25;
- }
- xx = 0.25*m;
- f0 = val[m];
- f1 = 1-xx*f0;
- z = f0+h*f1;
- y = h;
- j = 2;
- while (fabs(y)>z*1.0e-10)
- { f2 = -(j-1)*f0-xx*f1;
- y *= h/j;
- z += y*f2;
- f0 = f1; f1 = f2;
- j++;
- }
- return(z);
- }
- double ptail(x) /* exp(x*x/2)*int_{-\infty}^x exp(-u^2/2)du for x < -6 */
- double x;
- { double y, z, f0;
- int j;
- y = z = -1.0/x;
- j = 0;
- while ((fabs(f0= -(2*j+1)/(x*x))<1) && (fabs(y)>1.0e-10*z))
- { y *= f0;
- z += y;
- j++;
- }
- return(z);
- }
- double logit(x)
- double x;
- { return(log(x/(1-x)));
- }
- double expit(x)
- double x;
- { double u;
- if (x<0)
- { u = exp(x);
- return(u/(1+u));
- }
- return(1/(1+exp(-x)));
- }
- int factorial(n)
- int n;
- { if (n<=1) return(1.0);
- return(n*factorial(n-1));
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Constrained maximization of a bivariate function.
- * maxbvgrid(f,x,ll,ur,m0,m1)
- * maximizes over a grid of m0*m1 points. Returns the maximum,
- * and the maximizer through the array x. Usually this is a starter,
- * to choose between local maxima, followed by other routines to refine.
- *
- * maxbvstep(f,x,ymax,h,ll,ur,err)
- * essentially multivariate bisection. A 3x3 grid of points is
- * built around the starting value (x,ymax). This grid is moved
- * around (step size h[0] and h[1] in the two dimensions) until
- * the maximum is in the middle. Then, the step size is halved.
- * Usually, this will be called in a loop.
- * The error flag is set if the maximum can't be centered in a
- * reasonable number of steps.
- *
- * maxbv(f,x,h,ll,ur,m0,m1,tol)
- * combines the two previous functions. It begins with a grid search
- * (if m0>0 and m1>0), followed by refinement. Refines until both h
- * components are < tol.
- */
- #include "mut.h"
- #define max(a,b) ((a)>(b) ? (a) : (b))
- #define min(a,b) ((a)<(b) ? (a) : (b))
- double maxbvgrid(f,x,ll,ur,m0,m1,con)
- double (*f)(), *x, *ll, *ur;
- int m0, m1, *con;
- { int i, j, im, jm;
- double y, ymax;
- im = -1;
- for (i=0; i<=m0; i++)
- { x[0] = ((m0-i)*ll[0] + i*ur[0])/m0;
- for (j=0; j<=m1; j++)
- { x[1] = ((m1-j)*ll[1] + j*ur[1])/m1;
- y = f(x);
- if ((im==-1) || (y>ymax))
- { im = i; jm = j;
- ymax = y;
- }
- }
- }
- x[0] = ((m0-im)*ll[0] + im*ur[0])/m0;
- x[1] = ((m1-jm)*ll[1] + jm*ur[1])/m1;
- con[0] = (im==m0)-(im==0);
- con[1] = (jm==m1)-(jm==0);
- return(ymax);
- }
- double maxbvstep(f,x,ymax,h,ll,ur,err,con)
- double (*f)(), *x, ymax, *h, *ll, *ur;
- int *err, *con;
- { int i, j, ij, imax, steps, cts[2];
- double newx, X[9][2], y[9];
- imax =4; y[4] = ymax;
- for (i=(con[0]==-1)-1; i<2-(con[0]==1); i++)
- for (j=(con[1]==-1)-1; j<2-(con[1]==1); j++)
- { ij = 3*i+j+4;
- X[ij][0] = x[0]+i*h[0];
- if (X[ij][0] < ll[0]+0.001*h[0]) X[ij][0] = ll[0];
- if (X[ij][0] > ur[0]-0.001*h[0]) X[ij][0] = ur[0];
- X[ij][1] = x[1]+j*h[1];
- if (X[ij][1] < ll[1]+0.001*h[1]) X[ij][1] = ll[1];
- if (X[ij][1] > ur[1]-0.001*h[1]) X[ij][1] = ur[1];
- if (ij != 4)
- { y[ij] = f(X[ij]);
- if (y[ij]>ymax) { imax = ij; ymax = y[ij]; }
- }
- }
- steps = 0;
- cts[0] = cts[1] = 0;
- while ((steps<20) && (imax != 4))
- { steps++;
- if ((con[0]>-1) && ((imax/3)==0)) /* shift right */
- {
- cts[0]--;
- for (i=8; i>2; i--)
- { X[i][0] = X[i-3][0]; y[i] = y[i-3];
- }
- imax = imax+3;
- if (X[imax][0]==ll[0])
- con[0] = -1;
- else
- { newx = X[imax][0]-h[0];
- if (newx < ll[0]+0.001*h[0]) newx = ll[0];
- for (i=(con[1]==-1); i<3-(con[1]==1); i++)
- { X[i][0] = newx;
- y[i] = f(X[i]);
- if (y[i]>ymax) { ymax = y[i]; imax = i; }
- }
- con[0] = 0;
- }
- }
- if ((con[0]<1) && ((imax/3)==2)) /* shift left */
- {
- cts[0]++;
- for (i=0; i<6; i++)
- { X[i][0] = X[i+3][0]; y[i] = y[i+3];
- }
- imax = imax-3;
- if (X[imax][0]==ur[0])
- con[0] = 1;
- else
- { newx = X[imax][0]+h[0];
- if (newx > ur[0]-0.001*h[0]) newx = ur[0];
- for (i=6+(con[1]==-1); i<9-(con[1]==1); i++)
- { X[i][0] = newx;
- y[i] = f(X[i]);
- if (y[i]>ymax) { ymax = y[i]; imax = i; }
- }
- con[0] = 0;
- }
- }
- if ((con[1]>-1) && ((imax%3)==0)) /* shift up */
- {
- cts[1]--;
- for (i=9; i>0; i--) if (i%3 > 0)
- { X[i][1] = X[i-1][1]; y[i] = y[i-1];
- }
- imax = imax+1;
- if (X[imax][1]==ll[1])
- con[1] = -1;
- else
- { newx = X[imax][1]-h[1];
- if (newx < ll[1]+0.001*h[1]) newx = ll[1];
- for (i=3*(con[0]==-1); i<7-(con[0]==1); i=i+3)
- { X[i][1] = newx;
- y[i] = f(X[i]);
- if (y[i]>ymax) { ymax = y[i]; imax = i; }
- }
- con[1] = 0;
- }
- }
- if ((con[1]<1) && ((imax%3)==2)) /* shift down */
- {
- cts[1]++;
- for (i=0; i<9; i++) if (i%3 < 2)
- { X[i][1] = X[i+1][1]; y[i] = y[i+1];
- }
- imax = imax-1;
- if (X[imax][1]==ur[1])
- con[1] = 1;
- else
- { newx = X[imax][1]+h[1];
- if (newx > ur[1]-0.001*h[1]) newx = ur[1];
- for (i=2+3*(con[0]==-1); i<9-(con[0]==1); i=i+3)
- { X[i][1] = newx;
- y[i] = f(X[i]);
- if (y[i]>ymax) { ymax = y[i]; imax = i; }
- }
- con[1] = 0;
- }
- }
- /* if we've taken 3 steps in one direction, try increasing the
- * corresponding h.
- */
- if ((cts[0]==-2) | (cts[0]==2))
- { h[0] = 2*h[0]; cts[0] = 0; }
- if ((cts[1]==-2) | (cts[1]==2))
- { h[1] = 2*h[1]; cts[1] = 0; }
- }
- if (steps==40)
- *err = 1;
- else
- {
- h[0] /= 2.0; h[1] /= 2.0;
- *err = 0;
- }
- x[0] = X[imax][0];
- x[1] = X[imax][1];
- return(y[imax]);
- }
- #define BQMmaxp 5
- int boxquadmin(J,b0,p,x0,ll,ur)
- jacobian *J;
- double *b0, *x0, *ll, *ur;
- int p;
- { double b[BQMmaxp], x[BQMmaxp], L[BQMmaxp*BQMmaxp], C[BQMmaxp*BQMmaxp], d[BQMmaxp];
- double f, fmin;
- int i, imin, m, con[BQMmaxp], rlx;
- if (p>BQMmaxp) mut_printf("boxquadmin: maxp is 5.\n");
- if (J->st != JAC_RAW) mut_printf("boxquadmin: must start with JAC_RAW.\n");
- m = 0;
- setzero(L,p*p);
- setzero(x,p);
- memcpy(C,J->Z,p*p*sizeof(double));
- for (i=0; i<p; i++) con[i] = 0;
- do
- {
- /* first, keep minimizing and add constraints, one at a time.
- */
- do
- {
- matrixmultiply(C,x,b,p,p,1);
- for (i=0; i<p; i++) b[i] += b0[i];
- conquadmin(J,b,p,L,d,m);
- /* if C matrix is not pd, don't even bother.
- * this relies on having used cholesky dec.
- */
- if ((J->Z[0]==0.0) | (J->Z[3]==0.0)) return(1);
- fmin = 1.0;
- for (i=0; i<p; i++) if (con[i]==0)
- { f = 1.0;
- if (x0[i]+x[i]+b[i] < ll[i]) f = (ll[i]-x[i]-x0[i])/b[i];
- if (x0[i]+x[i]+b[i] > ur[i]) f = (ur[i]-x[i]-x0[i])/b[i];
- if (f<fmin) fmin = f;
- imin = i;
- }
- for (i=0; i<p; i++) x[i] += fmin*b[i];
- if (fmin<1.0)
- { L[m*p+imin] = 1;
- m++;
- con[imin] = (b[imin]<0) ? -1 : 1;
- }
- } while ((fmin < 1.0) & (m<p));
- /* now, can I relax any constraints?
- * compute slopes at current point. Can relax if:
- * slope is -ve on a lower boundary.
- * slope is +ve on an upper boundary.
- */
- rlx = 0;
- if (m>0)
- { matrixmultiply(C,x,b,p,p,1);
- for (i=0; i<p; i++) b[i] += b0[i];
- for (i=0; i<p; i++)
- { if ((con[i]==-1)&& (b[i]<0)) { con[i] = 0; rlx = 1; }
- if ((con[i]==1) && (b[i]>0)) { con[i] = 0; rlx = 1; }
- }
- if (rlx) /* reconstruct the constraint matrix */
- { setzero(L,p*p); m = 0;
- for (i=0; i<p; i++) if (con[i] != 0)
- { L[m*p+i] = 1;
- m++;
- }
- }
- }
- } while (rlx);
- memcpy(b0,x,p*sizeof(double)); /* this is how far we should move from x0 */
- return(0);
- }
- double maxquadstep(f,x,ymax,h,ll,ur,err,con)
- double (*f)(), *x, ymax, *h, *ll, *ur;
- int *err, *con;
- { jacobian J;
- double b[2], c[2], d, jwork[12];
- double x0, x1, y0, y1, ym, h0, xl[2], xu[2], xi[2];
- int i, m;
-
- *err = 0;
- /* first, can we relax any of the initial constraints?
- * if so, just do one step away from the boundary, and
- * return for restart.
- */
- for (i=0; i<2; i++)
- if (con[i] != 0)
- { xi[0] = x[0]; xi[1] = x[1];
- xi[i] = x[i]-con[i]*h[i];
- y0 = f(xi);
- if (y0>ymax)
- { memcpy(x,xi,2*sizeof(double));
- con[i] = 0;
- return(y0);
- }
- }
- /* now, all initial constraints remain active.
- */
- m = 9;
- for (i=0; i<2; i++) if (con[i]==0)
- { m /= 3;
- xl[0] = x[0]; xl[1] = x[1];
- xl[i] = max(x[i]-h[i],ll[i]); y0 = f(xl);
- x0 = xl[i]-x[i]; y0 -= ymax;
- xu[0] = x[0]; xu[1] = x[1];
- xu[i] = min(x[i]+h[i],ur[i]); y1 = f(xu);
- x1 = xu[i]-x[i]; y1 -= ymax;
- if (x0*x1*(x1-x0)==0) { *err = 1; return(0.0); }
- b[i] = (x0*x0*y1-x1*x1*y0)/(x0*x1*(x0-x1));
- c[i] = 2*(x0*y1-x1*y0)/(x0*x1*(x1-x0));
- if (c[i] >= 0.0) { *err = 1; return(0.0); }
- xi[i] = (b[i]<0) ? xl[i] : xu[i];
- }
- else { c[i] = -1.0; b[i] = 0.0; } /* enforce initial constraints */
- if ((con[0]==0) && (con[1]==0))
- { x0 = xi[0]-x[0];
- x1 = xi[1]-x[1];
- ym = f(xi) - ymax - b[0]*x0 - c[0]*x0*x0/2 - b[1]*x1 - c[1]*x1*x1/2;
- d = ym/(x0*x1);
- }
- else d = 0.0;
- /* now, maximize the quadratic.
- * y[4] + b0*x0 + b1*x1 + 0.5(c0*x0*x0 + c1*x1*x1 + 2*d*x0*x1)
- * -ve everything, to call quadmin.
- */
- jac_alloc(&J,2,jwork);
- J.Z[0] = -c[0];
- J.Z[1] = J.Z[2] = -d;
- J.Z[3] = -c[1];
- J.st = JAC_RAW;
- J.p = 2;
- b[0] = -b[0]; b[1] = -b[1];
- *err = boxquadmin(&J,b,2,x,ll,ur);
- if (*err) return(ymax);
- /* test to see if this step successfully increases...
- */
- for (i=0; i<2; i++)
- { xi[i] = x[i]+b[i];
- if (xi[i]<ll[i]+1e-8*h[i]) xi[i] = ll[i];
- if (xi[i]>ur[i]-1e-8*h[i]) xi[i] = ur[i];
- }
- y1 = f(xi);
- if (y1 < ymax) /* no increase */
- { *err = 1;
- return(ymax);
- }
- /* wonderful. update x, h, with the restriction that h can't decrease
- * by a factor over 10, or increase by over 2.
- */
- for (i=0; i<2; i++)
- { x[i] = xi[i];
- if (x[i]==ll[i]) con[i] = -1;
- if (x[i]==ur[i]) con[i] = 1;
- h0 = fabs(b[i]);
- h0 = min(h0,2*h[i]);
- h0 = max(h0,h[i]/10);
- h[i] = min(h0,(ur[i]-ll[i])/2.0);
- }
- return(y1);
- }
- double maxbv(f,x,h,ll,ur,m0,m1,tol)
- double (*f)(), *x, *h, *ll, *ur, tol;
- int m0, m1;
- { double ymax;
- int err, con[2];
- con[0] = con[1] = 0;
- if ((m0>0) & (m1>0))
- {
- ymax = maxbvgrid(f,x,ll,ur,m0,m1,con);
- h[0] = (ur[0]-ll[0])/(2*m0);
- h[1] = (ur[1]-ll[1])/(2*m1);
- }
- else
- { x[0] = (ll[0]+ur[0])/2;
- x[1] = (ll[1]+ur[1])/2;
- h[0] = (ur[0]-ll[0])/2;
- h[1] = (ur[1]-ll[1])/2;
- ymax = f(x);
- }
- while ((h[0]>tol) | (h[1]>tol))
- { ymax = maxbvstep(f,x,ymax,h,ll,ur,&err,con);
- if (err) mut_printf("maxbvstep failure\n");
- }
- return(ymax);
- }
- double maxbvq(f,x,h,ll,ur,m0,m1,tol)
- double (*f)(), *x, *h, *ll, *ur, tol;
- int m0, m1;
- { double ymax;
- int err, con[2];
- con[0] = con[1] = 0;
- if ((m0>0) & (m1>0))
- {
- ymax = maxbvgrid(f,x,ll,ur,m0,m1,con);
- h[0] = (ur[0]-ll[0])/(2*m0);
- h[1] = (ur[1]-ll[1])/(2*m1);
- }
- else
- { x[0] = (ll[0]+ur[0])/2;
- x[1] = (ll[1]+ur[1])/2;
- h[0] = (ur[0]-ll[0])/2;
- h[1] = (ur[1]-ll[1])/2;
- ymax = f(x);
- }
- while ((h[0]>tol) | (h[1]>tol))
- { /* first, try a quadratric step */
- ymax = maxquadstep(f,x,ymax,h,ll,ur,&err,con);
- /* if the quadratic step fails, move the grid around */
- if (err)
- {
- ymax = maxbvstep(f,x,ymax,h,ll,ur,&err,con);
- if (err)
- { mut_printf("maxbvstep failure\n");
- return(ymax);
- }
- }
- }
- return(ymax);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mut.h"
- prf mut_printf = (prf)printf;
- void mut_redirect(newprf)
- prf newprf;
- { mut_printf = newprf;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * function to find order of observations in an array.
- *
- * mut_order(x,ind,i0,i1)
- * x array to find order of.
- * ind integer array of indexes.
- * i0,i1 (integers) range to order.
- *
- * at output, ind[i0...i1] are permuted so that
- * x[ind[i0]] <= x[ind[i0+1]] <= ... <= x[ind[i1]].
- * (with ties, output order of corresponding indices is arbitrary).
- * The array x is unchanged.
- *
- * Typically, if x has length n, then i0=0, i1=n-1 and
- * ind is (any permutation of) 0...n-1.
- */
- #include "mut.h"
- double med3(x0,x1,x2)
- double x0, x1, x2;
- { if (x0<x1)
- { if (x2<x0) return(x0);
- if (x1<x2) return(x1);
- return(x2);
- }
- /* x1 < x0 */
- if (x2<x1) return(x1);
- if (x0<x2) return(x0);
- return(x2);
- }
- void mut_order(x,ind,i0,i1)
- double *x;
- int *ind, i0, i1;
- { double piv;
- int i, l, r, z;
- if (i1<=i0) return;
- piv = med3(x[ind[i0]],x[ind[i1]],x[ind[(i0+i1)/2]]);
- l = i0; r = i0-1;
- /* at each stage,
- * x[i0..l-1] < piv
- * x[l..r] = piv
- * x[r+1..i-1] > piv
- * then, decide where to put x[i].
- */
- for (i=i0; i<=i1; i++)
- { if (x[ind[i]]==piv)
- { r++;
- z = ind[i]; ind[i] = ind[r]; ind[r] = z;
- }
- else if (x[ind[i]]<piv)
- { r++;
- z = ind[i]; ind[i] = ind[r]; ind[r] = ind[l]; ind[l] = z;
- l++;
- }
- }
- if (l>i0) mut_order(x,ind,i0,l-1);
- if (r<i1) mut_order(x,ind,r+1,i1);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mut.h"
- #define LOG_2 0.6931471805599453094172321214581765680755
- #define IBETA_LARGE 1.0e30
- #define IBETA_SMALL 1.0e-30
- #define IGAMMA_LARGE 1.0e30
- #define DOUBLE_EP 2.2204460492503131E-16
- double ibeta(x, a, b)
- double x, a, b;
- { int flipped = 0, i, k, count;
- double I = 0, temp, pn[6], ak, bk, next, prev, factor, val;
- if (x <= 0) return(0);
- if (x >= 1) return(1);
- /* use ibeta(x,a,b) = 1-ibeta(1-x,b,z) */
- if ((a+b+1)*x > (a+1))
- { flipped = 1;
- temp = a;
- a = b;
- b = temp;
- x = 1 - x;
- }
- pn[0] = 0.0;
- pn[2] = pn[3] = pn[1] = 1.0;
- count = 1;
- val = x/(1.0-x);
- bk = 1.0;
- next = 1.0;
- do
- { count++;
- k = count/2;
- prev = next;
- if (count%2 == 0)
- ak = -((a+k-1.0)*(b-k)*val)/((a+2.0*k-2.0)*(a+2.0*k-1.0));
- else
- ak = ((a+b+k-1.0)*k*val)/((a+2.0*k)*(a+2.0*k-1.0));
- pn[4] = bk*pn[2] + ak*pn[0];
- pn[5] = bk*pn[3] + ak*pn[1];
- next = pn[4] / pn[5];
- for (i=0; i<=3; i++)
- pn[i] = pn[i+2];
- if (fabs(pn[4]) >= IBETA_LARGE)
- for (i=0; i<=3; i++)
- pn[i] /= IBETA_LARGE;
- if (fabs(pn[4]) <= IBETA_SMALL)
- for (i=0; i<=3; i++)
- pn[i] /= IBETA_SMALL;
- } while (fabs(next-prev) > DOUBLE_EP*prev);
- /* factor = a*log(x) + (b-1)*log(1-x);
- factor -= mut_lgamma(a+1) + mut_lgamma(b) - mut_lgamma(a+b); */
- factor = dbeta(x,a,b,1) + log(x/a);
- I = exp(factor) * next;
- return(flipped ? 1-I : I);
- }
- /*
- * Incomplete gamma function.
- * int_0^x u^{df-1} e^{-u} du / Gamma(df).
- */
- double igamma(x, df)
- double x, df;
- { double factor, term, gintegral, pn[6], rn, ak, bk;
- int i, count, k;
- if (x <= 0.0) return(0.0);
- if (df < 1.0)
- return( dgamma(x,df+1.0,1.0,0) + igamma(x,df+1.0) );
- factor = x * dgamma(x,df,1.0,0);
- /* factor = exp(df*log(x) - x - lgamma(df)); */
- if (x > 1.0 && x >= df)
- {
- pn[0] = 0.0;
- pn[2] = pn[1] = 1.0;
- pn[3] = x;
- count = 1;
- rn = 1.0 / x;
- do
- { count++;
- k = count / 2;
- gintegral = rn;
- if (count%2 == 0)
- { bk = 1.0;
- ak = (double)k - df;
- } else
- { bk = x;
- ak = (double)k;
- }
- pn[4] = bk*pn[2] + ak*pn[0];
- pn[5] = bk*pn[3] + ak*pn[1];
- rn = pn[4] / pn[5];
- for (i=0; i<4; i++)
- pn[i] = pn[i+2];
- if (pn[4] > IGAMMA_LARGE)
- for (i=0; i<4; i++)
- pn[i] /= IGAMMA_LARGE;
- } while (fabs(gintegral-rn) > DOUBLE_EP*rn);
- gintegral = 1.0 - factor*rn;
- }
- else
- { /* For x<df, use the series
- * dpois(df,x)*( 1 + x/(df+1) + x^2/((df+1)(df+2)) + ... )
- * This could be slow if df large and x/df is close to 1.
- */
- gintegral = term = 1.0;
- rn = df;
- do
- { rn += 1.0;
- term *= x/rn;
- gintegral += term;
- } while (term > DOUBLE_EP*gintegral);
- gintegral *= factor/df;
- }
- return(gintegral);
- }
- double pf(q, df1, df2)
- double q, df1, df2;
- { return(ibeta(q*df1/(df2+q*df1), df1/2, df2/2));
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mut.h"
- #include <string.h>
- /* quadmin: minimize the quadratic,
- * 2<x,b> + x^T A x.
- * x = -A^{-1} b.
- *
- * conquadmin: min. subject to L'x = d (m constraints)
- * x = -A^{-1}(b+Ly) (y = Lagrange multiplier)
- * y = -(L'A^{-1}L)^{-1} (L'A^{-1}b)
- * x = -A^{-1}b + A^{-1}L (L'A^{-1}L)^{-1} [(L'A^{-1})b + d]
- * (non-zero d to be added!!)
- *
- * qprogmin: min. subject to L'x >= 0.
- */
- void quadmin(J,b,p)
- jacobian *J;
- double *b;
- int p;
- { int i;
- jacob_dec(J,JAC_CHOL);
- i = jacob_solve(J,b);
- if (i<p) mut_printf("quadmin singular %2d %2d\n",i,p);
- for (i=0; i<p; i++) b[i] = -b[i];
- }
- /* project vector a (length n) onto
- * columns of X (n rows, m columns, organized by column).
- * store result in y.
- */
- #define pmaxm 10
- #define pmaxn 100
- void project(a,X,y,n,m)
- double *a, *X, *y;
- int n, m;
- { double xta[pmaxm], R[pmaxn*pmaxm];
- int i;
- if (n>pmaxn) mut_printf("project: n too large\n");
- if (m>pmaxm) mut_printf("project: m too large\n");
- for (i=0; i<m; i++) xta[i] = innerprod(a,&X[i*n],n);
- memcpy(R,X,m*n*sizeof(double));
- qr(R,n,m,NULL);
- qrsolv(R,xta,n,m);
- matrixmultiply(X,xta,y,n,m,1);
- }
- void resproj(a,X,y,n,m)
- double *a, *X, *y;
- int n, m;
- { int i;
- project(a,X,y,n,m);
- for (i=0; i<n; i++) y[i] = a[i]-y[i];
- }
- /* x = -A^{-1}b + A^{-1}L (L'A^{-1}L)^{-1} [(L'A^{-1})b + d] */
- void conquadmin(J,b,n,L,d,m)
- jacobian *J;
- double *b, *L, *d;
- int m, n;
- { double bp[10], L0[100];
- int i, j;
- if (n>10) mut_printf("conquadmin: max. n is 10.\n");
- memcpy(L0,L,n*m*sizeof(double));
- jacob_dec(J,JAC_CHOL);
- for (i=0; i<m; i++) jacob_hsolve(J,&L[i*n]);
- jacob_hsolve(J,b);
- resproj(b,L,bp,n,m);
- jacob_isolve(J,bp);
- for (i=0; i<n; i++) b[i] = -bp[i];
- qr(L,n,m,NULL);
- qrsolv(L,d,n,m);
- for (i=0; i<n; i++)
- { bp[i] = 0;
- for (j=0; j<m; j++) bp[i] += L0[j*n+i]*d[j];
- }
- jacob_solve(J,bp);
- for (i=0; i<n; i++) b[i] += bp[i];
- }
- void qactivemin(J,b,n,L,d,m,ac)
- jacobian *J;
- double *b, *L, *d;
- int m, n, *ac;
- { int i, nac;
- double M[100], dd[10];
- nac = 0;
- for (i=0; i<m; i++) if (ac[i]>0)
- { memcpy(&M[nac*n],&L[i*n],n*sizeof(double));
- dd[nac] = d[i];
- nac++;
- }
- conquadmin(J,b,n,M,dd,nac);
- }
- /* return 1 for full step; 0 if new constraint imposed. */
- int movefrom(x0,x,n,L,d,m,ac)
- double *x0, *x, *L, *d;
- int n, m, *ac;
- { int i, imin;
- double c0, c1, lb, lmin;
- lmin = 1.0;
- for (i=0; i<m; i++) if (ac[i]==0)
- { c1 = innerprod(&L[i*n],x,n)-d[i];
- if (c1<0.0)
- { c0 = innerprod(&L[i*n],x0,n)-d[i];
- if (c0<0.0)
- { if (c1<c0) { lmin = 0.0; imin = 1; }
- }
- else
- { lb = c0/(c0-c1);
- if (lb<lmin) { lmin = lb; imin = i; }
- }
- }
- }
- for (i=0; i<n; i++)
- x0[i] = lmin*x[i]+(1-lmin)*x0[i];
- if (lmin==1.0) return(1);
- ac[imin] = 1;
- return(0);
- }
- int qstep(J,b,x0,n,L,d,m,ac,deac)
- jacobian *J;
- double *b, *x0, *L, *d;
- int m, n, *ac, deac;
- { double x[10];
- int i;
- if (m>10) mut_printf("qstep: too many constraints.\n");
- if (deac)
- { for (i=0; i<m; i++) if (ac[i]==1)
- { ac[i] = 0;
- memcpy(x,b,n*sizeof(double));
- qactivemin(J,x,n,L,d,m,ac);
- if (innerprod(&L[i*n],x,n)>d[i]) /* deactivate this constraint; should rem. */
- i = m+10;
- else
- ac[i] = 1;
- }
- if (i==m) return(0); /* no deactivation possible */
- }
- do
- { if (!deac)
- { memcpy(x,b,n*sizeof(double));
- qactivemin(J,x,n,L,d,m,ac);
- }
- i = movefrom(x0,x,n,L,d,m,ac);
- deac = 0;
- } while (i==0);
- return(1);
- }
- /*
- * x0 is starting value; should satisfy constraints.
- * L is n*m constraint matrix.
- * ac is active constraint vector:
- * ac[i]=0, inactive.
- * ac[i]=1, active, but can be deactivated.
- * ac[i]=2, active, cannot be deactivated.
- */
- void qprogmin(J,b,x0,n,L,d,m,ac)
- jacobian *J;
- double *b, *x0, *L, *d;
- int m, n, *ac;
- { int i;
- for (i=0; i<m; i++) if (ac[i]==0)
- { if (innerprod(&L[i*n],x0,n) < d[i]) ac[i] = 1; }
- jacob_dec(J,JAC_CHOL);
- qstep(J,b,x0,n,L,d,m,ac,0);
- while (qstep(J,b,x0,n,L,d,m,ac,1));
- }
- void qpm(A,b,x0,n,L,d,m,ac)
- double *A, *b, *x0, *L, *d;
- int *n, *m, *ac;
- { jacobian J;
- double wk[1000];
- jac_alloc(&J,*n,wk);
- memcpy(J.Z,A,(*n)*(*n)*sizeof(double));
- J.p = *n;
- J.st = JAC_RAW;
- qprogmin(&J,b,x0,*n,L,d,*m,ac);
- }
|