12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355 |
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "mex.h"
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- extern void fitoptions();
- static double hmin, gmin, sig2, pen, vr, tb;
- static lfit *blf;
- static design *bdes;
- int procvbind(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { double s0, s1, bi;
- int i, ii, k;
- k = procv_var(des,lf,v);
- wdiag(&lf->lfd, &lf->sp, des,des->wd,&lf->dv,0,1,0);
- s0 = s1 = 0.0;
- for (i=0; i<des->n; i++)
- { ii = des->ind[i];
- s0+= prwt(&lf->lfd,ii)*des->wd[i]*des->wd[i];
- bi = prwt(&lf->lfd,ii)*fabs(des->wd[i]*ipower(dist(des,ii),deg(&lf->sp)+1));
- s1+= bi*bi;
- }
- vr += s0;
- tb += s1;
- return(k);
- }
- double bcri(h,c,cri)
- double h;
- int c, cri;
- { double num, den, res[10];
- int (*pv)();
- if (c==DALP)
- blf->sp.nn = h;
- else
- blf->sp.fixh = h;
- if ((cri&63)==BIND)
- { pv = procvbind;
- vr = tb = 0.0;
- }
- else pv = procvstd;
- if (cri<64) startlf(bdes,blf,pv,0);
- switch(cri&63)
- { case BGCV:
- ressumm(blf,bdes,res);
- num = -2*blf->lfd.n*res[0];
- den = blf->lfd.n-res[1];
- return(num/(den*den));
- case BCP:
- ressumm(blf,bdes,res);
- return(-2*res[0]/sig2-blf->lfd.n+pen*res[1]);
- case BIND:
- return(vr+pen*pen*tb);
- }
- LERR(("bcri: unknown criterion"));
- return(0.0);
- }
- void bsel2(h0,g0,ifact,c,cri)
- double h0, g0, ifact;
- int c, cri;
- { int done, inc;
- double h1, g1;
- h1 = h0; g1 = g0;
- done = inc = 0;
- while (!done)
- { h1 *= 1+ifact;
- g0 = g1;
- g1 = bcri(h1,c,cri);
- if (g1<gmin) { hmin = h1; gmin = g1; }
- if (g1>g0) inc++; else inc = 0;
- switch(cri)
- { case BIND:
- done = (inc>=4) & (vr<blf->fp.nv);
- break;
- default:
- done = (inc>=4);
- }
- }
- }
- void bsel3(h0,g0,ifact,c,cri)
- double h0, g0, ifact;
- int c, cri;
- { double h1, g1;
- int i;
- hmin = h0; gmin = g0;
- for (i=-1; i<=1; i++) if (i!=0)
- { h1 = h0*(1+i*ifact);
- g1 = bcri(h1,c,cri);
- if (g1<gmin) { hmin = h1; gmin = g1; }
- }
- return;
- }
- void bselect(lf,des,c,cri,pn)
- lfit *lf;
- design *des;
- int c, cri;
- double pn;
- { double h0, g0, ifact;
- int i;
- pen = pn;
- blf = lf;
- bdes = des;
- if (cri==BIND) pen /= factorial(deg(&lf->sp)+1);
- hmin = h0 = (c==DFXH) ? fixh(&lf->sp) : nn(&lf->sp);
- if (h0==0) LERR(("bselect: initial bandwidth is 0"));
- if (lf_error) return;
- sig2 = 1.0;
- gmin = g0 = bcri(h0,c,cri);
- if (cri==BCP)
- { sig2 = rv(&lf->fp);
- g0 = gmin = bcri(h0,c,cri+64);
- }
-
- ifact = 0.3;
- bsel2(h0,g0,ifact,c,cri);
- for (i=0; i<5; i++)
- { ifact = ifact/2;
- bsel3(hmin,gmin,ifact,c,cri);
- }
- if (c==DFXH)
- fixh(&lf->sp) = hmin;
- else
- nn(&lf->sp) = hmin;
- startlf(des,lf,procvstd,0);
- ressumm(lf,des,lf->fp.kap);
- }
- double compsda(x,h,n)
- double *x, h;
- int n;
- /* n/(n-1) * int( fhat''(x)^2 dx ); bandwidth h */
- { int i, j;
- double ik, sd, z;
- ik = wint(1,NULL,0,WGAUS);
- sd = 0;
- for (i=0; i<n; i++)
- for (j=i; j<n; j++)
- { z = (x[i]-x[j])/h;
- sd += (2-(i==j))*Wconv4(z,WGAUS)/(ik*ik);
- }
- sd = sd/(n*(n-1)*h*h*h*h*h);
- return(sd);
- }
- double widthsj(x,lambda,n)
- double *x, lambda;
- int n;
- { double ik, a, b, td, sa, z, c, c1, c2, c3;
- int i, j;
- a = GFACT*0.920*lambda*exp(-log((double)n)/7)/SQRT2;
- b = GFACT*0.912*lambda*exp(-log((double)n)/9)/SQRT2;
- ik = wint(1,NULL,0,WGAUS);
- td = 0;
- for (i=0; i<n; i++)
- for (j=i; j<n; j++)
- { z = (x[i]-x[j])/b;
- td += (2-(i==j))*Wconv6(z,WGAUS)/(ik*ik);
- }
- td = -td/(n*(n-1));
- j = 2.0;
- c1 = Wconv4(0.0,WGAUS);
- c2 = wint(1,&j,1,WGAUS);
- c3 = Wconv(0.0,WGAUS); /* (2*c1/(c2*c3))^(1/7)=1.357 */
- sa = compsda(x,a,n);
- c = b*exp(log(c1*ik/(c2*c3*GFACT*GFACT*GFACT*GFACT)*sa/td)/7)*SQRT2;
- return(c);
- }
- void kdecri(x,h,res,c,k,ker,n)
- double *x, h, *res, c;
- int k, ker, n;
- { int i, j;
- double degfree, dfd, pen, s, r0, r1, d0, d1, ik, wij;
- if (h<=0) WARN(("kdecri, h = %6.4f",h));
- res[0] = res[1] = 0.0;
- ik = wint(1,NULL,0,ker);
- switch(k)
- { case 1: /* aic */
- pen = 2.0;
- for (i=0; i<n; i++)
- { r0 = d0 = 0.0;
- for (j=0; j<n; j++)
- { s = (x[i]-x[j])/h;
- r0 += W(s,ker);
- d0 += s*s*Wd(s,ker);
- }
- d0 = -(d0+r0)/(n*h*h*ik); /* d0 = d/dh fhat(xi) */
- r0 /= n*h*ik; /* r0 = fhat(xi) */
- res[0] += -2*log(r0)+pen*W(0.0,ker)/(n*h*ik*r0);
- res[1] += -2*d0/r0-pen*W(0.0,ker)/(n*h*ik*r0)*(d0/r0+1.0/h);
- }
- return;
- case 2: /* ocv */
- for (i=0; i<n; i++)
- { r0 = 0.0; d0 = 0.0;
- for (j=0; j<n; j++) if (i!=j)
- { s = (x[i]-x[j])/h;
- r0 += W(s,ker);
- d0 += s*s*Wd(s,ker);
- }
- d0 = -(d0+r0)/((n-1)*h*h);
- r0 = r0/((n-1)*h);
- res[0] -= log(r0);
- res[1] -= d0/r0;
- }
- return;
- case 3: /* lscv */
- r0 = r1 = d0 = d1 = degfree = 0.0;
- for (i=0; i<n; i++)
- { dfd = 0.0;
- for (j=0; j<n; j++)
- { s = (x[i]-x[j])/h;
- wij = W(s,ker);
- dfd += wij;
- /*
- * r0 = \int fhat * fhat = sum_{i,j} W*W( (Xi-Xj)/h ) / n^2 h.
- * d0 is it's derivative wrt h.
- *
- * r1 = 1/n sum( f_{-i}(X_i) ).
- * d1 is it's derivative wrt h.
- *
- * degfree = sum_i ( W_0 / sum_j W( (Xi-Xj)/h ) ) is fitted d.f.
- */
- r0 += Wconv(s,ker);
- d0 += -s*s*Wconv1(s,ker);
- if (i != j)
- { r1 += wij;
- d1 += -s*s*Wd(s,ker);
- }
- }
- degfree += 1.0/dfd;
- }
- d1 -= r1;
- d0 -= r0;
- res[0] = r0/(n*n*h*ik*ik) - 2*r1/(n*(n-1)*h*ik);
- res[1] = d0/(n*n*h*h*ik*ik) - 2*d1/(n*(n-1)*h*h*ik);
- res[2] = degfree;
- return;
- case 4: /* bcv */
- r0 = d0 = 0.0;
- for (i=0; i<n; i++)
- for (j=i+1; j<n; j++)
- { s = (x[i]-x[j])/h;
- r0 += 2*Wconv4(s,ker);
- d0 += 2*s*Wconv5(s,ker);
- }
- d0 = (-d0-r0)/(n*n*h*h*ik*ik);
- r0 = r0/(n*n*h*ik*ik);
- j = 2.0;
- d1 = wint(1,&j,1,ker);
- r1 = Wconv(0.0,ker);
- res[0] = (d1*d1*r0/4+r1/(n*h))/(ik*ik);
- res[1] = (d1*d1*d0/4-r1/(n*h*h))/(ik*ik);
- return;
- case 5: /* sjpi */
- s = c*exp(5*log(h)/7)/SQRT2;
- d0 = compsda(x,s,n);
- res[0] = d0; /* this is S(alpha) in SJ */
- res[1] = exp(log(Wikk(WGAUS,0)/(d0*n))/5)-h;
- return;
- case 6: /* gas-k-k */
- s = exp(log(1.0*n)/10)*h;
- d0 = compsda(x,s,n);
- res[0] = d0;
- res[1] = exp(log(Wikk(WGAUS,0)/(d0*n))/5)-h;
- return;
- }
- LERR(("kdecri: what???"));
- return;
- }
- double esolve(x,j,h0,h1,k,c,ker,n)
- double *x, h0, h1, c;
- int j, k, ker, n;
- { double h[7], d[7], r[7], res[4], min, minh, fact;
- int i, nc;
- min = 1.0e30; minh = 0.0;
- fact = 1.00001;
- h[6] = h0; kdecri(x,h[6],res,c,j,ker,n);
- r[6] = res[0]; d[6] = res[1];
- if (lf_error) return(0.0);
- nc = 0;
- for (i=0; i<k; i++)
- { h[5] = h[6]; r[5] = r[6]; d[5] = d[6];
- h[6] = h0*exp((i+1)*log(h1/h0)/k);
- kdecri(x,h[6],res,c,j,ker,n);
- r[6] = res[0]; d[6] = res[1];
- if (lf_error) return(0.0);
- if (d[5]*d[6]<0)
- { h[2] = h[0] = h[5]; d[2] = d[0] = d[5]; r[2] = r[0] = r[5];
- h[3] = h[1] = h[6]; d[3] = d[1] = d[6]; r[3] = r[1] = r[6];
- while ((h[3]>fact*h[2])|(h[2]>fact*h[3]))
- { h[4] = h[3]-d[3]*(h[3]-h[2])/(d[3]-d[2]);
- if ((h[4]<h[0]) | (h[4]>h[1])) h[4] = (h[0]+h[1])/2;
- kdecri(x,h[4],res,c,j,ker,n);
- r[4] = res[0]; d[4] = res[1];
- if (lf_error) return(0.0);
- h[2] = h[3]; h[3] = h[4];
- d[2] = d[3]; d[3] = d[4];
- r[2] = r[3]; r[3] = r[4];
- if (d[4]*d[0]>0) { h[0] = h[4]; d[0] = d[4]; r[0] = r[4]; }
- else { h[1] = h[4]; d[1] = d[4]; r[1] = r[4]; }
- }
- if (j>=4) return(h[4]); /* first min for BCV etc */
- if (r[4]<=min) { min = r[4]; minh = h[4]; }
- nc++;
- }
- }
- if (nc==0) minh = (r[5]<r[6]) ? h0 : h1;
- return(minh);
- }
- void kdeselect(band,x,ind,h0,h1,meth,nm,ker,n)
- double h0, h1, *band, *x;
- int *ind, nm, ker, n, *meth;
- { double scale, c;
- int i, k;
- k = n/4;
- for (i=0; i<n; i++) ind[i] = i;
- scale = kordstat(x,n+1-k,n,ind) - kordstat(x,k,n,ind);
- c = widthsj(x,scale,n);
- for (i=0; i<nm; i++)
- band[i] = esolve(x,meth[i],h0,h1,10,c,ker,n);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * The function dens_integrate(lf,des,z) is used to integrate a density
- * estimate (z=1) or the density squared (z=2). This is used to renormalize
- * the estimate (function dens_renorm) or in the computation of LSCV
- * (in modlscv.c). The implementation is presently for d=1.
- *
- * The computation orders the fit points selected by locfit, and
- * integrates analytically over each interval. For the log-link,
- * the interpolant used is peicewise quadratic (with one knot in
- * the middle of each interval); this differs from the cubic interpolant
- * used elsewhere in Locfit.
- *
- * TODO: allow for xlim. What can be done simply in >=2 dimensions?
- */
- #include "lfev.h"
- /*
- * Finds the order of observations in the array x, and
- * stores in integer array ind.
- * At input, lset l=0 and r=length(x)-1.
- * At output, x[ind[0]] <= x[ind[1]] <= ...
- */
- void lforder(ind,x,l,r)
- int *ind, l, r;
- double *x;
- { double piv;
- int i, i0, i1;
- piv = (x[ind[l]]+x[ind[r]])/2;
- i0 = l; i1 = r;
- while (i0<=i1)
- { while ((i0<=i1) && (x[ind[i0]]<=piv)) i0++;
- while ((i0<=i1) && (x[ind[i1]]>piv)) i1--;
- if (i0<i1)
- { ISWAP(ind[i0],ind[i1]);
- i0++; i1--;
- }
- }
- /* now, x[ind[l..i1]] <= piv < x[ind[i0..r]].
- put the ties in the middle */
- while ((i1>=l) && (x[ind[i1]]==piv)) i1--;
- for (i=l; i<=i1; i++)
- if (x[ind[i]]==piv)
- { ISWAP(ind[i],ind[i1]);
- while (x[ind[i1]]==piv) i1--;
- }
- if (l<i1) lforder(ind,x,l,i1);
- if (i0<r) lforder(ind,x,i0,r);
- }
- /*
- * estdiv integrates the density between fit points x0 and x1.
- * f0, f1 are function values, d0, d1 are derivatives.
- */
- double estdiv(x0,x1,f0,f1,d0,d1,lin)
- double x0, x1, f0, f1, d0, d1;
- int lin;
- { double cf[4], I[2], dlt, e0, e1;
- if (x0==x1) return(0.0);
- if (lin==LIDENT)
- {
- /* cf are integrals of hermite polynomials.
- * Then adjust for x1-x0.
- */
- cf[0] = cf[1] = 0.5;
- cf[2] = 1.0/12.0; cf[3] = -cf[2];
- return( (cf[0]*f0+cf[1]*f1)*(x1-x0)
- + (cf[2]*d0+cf[3]*d1)*(x1-x0)*(x1-x0) );
- }
- /*
- * this is for LLOG
- */
- dlt = (x1-x0)/2;
- cf[0] = f0;
- cf[1] = d0;
- cf[2] = ( 2*(f1-f0) - dlt*(d1+3*d0) )/(4*dlt*dlt);
- recurint(0.0,dlt,cf,I,0,WRECT);
- e0 = I[0];
- cf[0] = f1;
- cf[1] = -d1;
- cf[2] = ( 2*(f0-f1) + dlt*(d0+3*d1) )/( 4*dlt*dlt );
- recurint(0.0,dlt,cf,I,0,WRECT);
- e1 = I[0];
- return(e0+e1);
- }
- /*
- * Evaluate the integral of the density estimate to the power z.
- * This would be severely messed up, if I ever implement parcomp
- * for densities.
- */
- double dens_integrate(lf,des,z)
- lfit *lf;
- design *des;
- int z;
- { int has_deriv, i, i0, i1, nv, *ind;
- double *xev, *fit, *deriv, sum, term;
- double d0, d1, f0, f1;
- fitpt *fp;
- fp = &lf->fp;
- if (fp->d >= 2)
- { WARN(("dens_integrate requires d=1"));
- return(0.0);
- }
- has_deriv = (deg(&lf->sp) > 0); /* not right? */
- fit = fp->coef;
- if (has_deriv)
- deriv = &fit[fp->nvm];
- xev = evp(fp);
- /*
- * order the vertices
- */
- nv = fp->nv;
- if (lf->lfd.n<nv) return(0.0);
- ind = des->ind;
- for (i=0; i<nv; i++) ind[i] = i;
- lforder(ind,xev,0,nv-1);
- sum = 0.0;
- /*
- * Estimate the contribution of the boundaries.
- * should really check flim here.
- */
- i0 = ind[0]; i1 = ind[1];
- f1 = fit[i0];
- d1 = (has_deriv) ? deriv[i0] :
- (fit[i1]-fit[i0])/(xev[i1]-xev[i0]);
- if (d1 <= 0) WARN(("dens_integrate - ouch!"));
- if (z==2)
- { if (link(&lf->sp)==LLOG)
- { f1 *= 2; d1 *= 2; }
- else
- { d1 = 2*d1*f1; f1 = f1*f1; }
- }
- term = (link(&lf->sp)==LIDENT) ? f1*f1/(2*d1) : exp(f1)/d1;
- sum += term;
- i0 = ind[nv-2]; i1 = ind[nv-1];
- f0 = fit[i1];
- d0 = (has_deriv) ? deriv[i1] :
- (fit[i1]-fit[i0])/(xev[i1]-xev[i0]);
- if (d0 >= 0) WARN(("dens_integrate - ouch!"));
- if (z==2)
- { if (link(&lf->sp)==LLOG)
- { f0 *= 2; d0 *= 2; }
- else
- { d0 = 2*d0*f0; f0 = f0*f0; }
- }
- term = (link(&lf->sp)==LIDENT) ? -f0*f0/(2*d0) : exp(f0)/d0;
- sum += term;
-
- for (i=1; i<nv; i++)
- { i0 = ind[i-1]; i1 = ind[i];
- f0 = fit[i0]; f1 = fit[i1];
- d0 = (has_deriv) ? deriv[i0] :
- (f1-f0)/(xev[i1]-xev[i0]);
- d1 = (has_deriv) ? deriv[i1] : d0;
- if (z==2)
- { if (link(&lf->sp)==LLOG)
- { f0 *= 2; f1 *= 2; d0 *= 2; d1 *= 2; }
- else
- { d0 *= 2*f0; d1 *= 2*f1; f0 = f0*f0; f1 = f1*f1; }
- }
- term = estdiv(xev[i0],xev[i1],f0,f1,d0,d1,link(&lf->sp));
- sum += term;
- }
- return(sum);
- }
- void dens_renorm(lf,des)
- lfit *lf;
- design *des;
- { int i;
- double sum;
- sum = dens_integrate(lf,des,1);
- if (sum==0.0) return;
- sum = log(sum);
- for (i=0; i<lf->fp.nv; i++) lf->fp.coef[i] -= sum;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * This file contains functions for constructing and
- * interpolating the adaptive tree structure. This is
- * the default evaluation structure used by Locfit.
- */
- #include "lfev.h"
- /*
- Guess the number of fitting points.
- Needs improving!
- */
- void atree_guessnv(evs,nvm,ncm,vc,d,alp)
- evstruc *evs;
- double alp;
- int *nvm, *ncm, *vc, d;
- { double a0, cu, ifl;
- int i, nv, nc;
- *ncm = 1<<30; *nvm = 1<<30;
- *vc = 1 << d;
- if (alp>0)
- { a0 = (alp > 1) ? 1 : 1/alp;
- if (cut(evs)<0.01)
- { WARN(("guessnv: cut too small."));
- cut(evs) = 0.01;
- }
- cu = 1;
- for (i=0; i<d; i++) cu *= MIN(1.0,cut(evs));
- nv = (int)((5*a0/cu)**vc); /* this allows 10*a0/cu splits */
- nc = (int)(10*a0/cu+1); /* and 10*a0/cu cells */
- if (nv<*nvm) *nvm = nv;
- if (nc<*ncm) *ncm = nc;
- }
- if (*nvm == 1<<30) /* by default, allow 100 splits */
- { *nvm = 102**vc;
- *ncm = 201;
- }
- /* inflation based on mk */
- ifl = mk(evs)/100.0;
- *nvm = *vc+(int)(ifl**nvm);
- *ncm = (int)(ifl**ncm);
-
- }
- /*
- Determine whether a cell in the tree needs splitting.
- If so, return the split variable (0..d-1).
- Otherwise, return -1.
- */
- int atree_split(lf,ce,le,ll,ur)
- lfit *lf;
- int *ce;
- double *le, *ll, *ur;
- { int d, vc, i, is;
- double h, hmin, score[MXDIM];
- d = lf->fp.d; vc = 1<<d;
- hmin = 0.0;
- for (i=0; i<vc; i++)
- { h = lf->fp.h[ce[i]];
- if ((h>0) && ((hmin==0)|(h<hmin))) hmin = h;
- }
- is = 0;
- for (i=0; i<d; i++)
- { le[i] = (ur[i]-ll[i])/lf->lfd.sca[i];
- if ((lf->lfd.sty[i]==STCPAR) || (hmin==0))
- score[i] = 2*(ur[i]-ll[i])/(lf->evs.fl[i+d]-lf->evs.fl[i]);
- else
- score[i] = le[i]/hmin;
- if (score[i]>score[is]) is = i;
- }
- if (cut(&lf->evs)<score[is]) return(is);
- return(-1);
- }
- /*
- recursively grow the tree structure, begining with the parent cell.
- */
- void atree_grow(des,lf,ce,ct,term,ll,ur)
- design *des;
- lfit *lf;
- int *ce, *ct, *term;
- double *ll, *ur;
- { int nce[1<<MXDIM];
- int i, i0, i1, d, vc, pv, tk, ns;
- double le[MXDIM], z;
- d = lf->fp.d; vc = 1<<d;
- /* does this cell need splitting?
- If not, wrap up and return.
- */
- ns = atree_split(lf,ce,le,ll,ur);
- if (ns==-1)
- { if (ct != NULL) /* reconstructing terminal cells */
- { for (i=0; i<vc; i++) term[*ct*vc+i] = ce[i];
- (*ct)++;
- }
- return;
- }
- /* split the cell at the midpoint on side ns */
- tk = 1<<ns;
- for (i=0; i<vc; i++)
- { if ((i&tk)==0) nce[i] = ce[i];
- else
- { i0 = ce[i];
- i1 = ce[i-tk];
- pv = (lf->lfd.sty[i]!=STCPAR) &&
- (le[ns] < (cut(&lf->evs)*MIN(lf->fp.h[i0],lf->fp.h[i1])));
- nce[i] = newsplit(des,lf,i0,i1,pv);
- if (lf_error) return;
- }
- }
- z = ur[ns]; ur[ns] = (z+ll[ns])/2;
- atree_grow(des,lf,nce,ct,term,ll,ur);
- if (lf_error) return;
- ur[ns] = z;
- for (i=0; i<vc; i++)
- nce[i] = ((i&tk)== 0) ? nce[i+tk] : ce[i];
- z = ll[ns]; ll[ns] = (z+ur[ns])/2;
- atree_grow(des,lf,nce,ct,term,ll,ur);
- if (lf_error) return;
- ll[ns] = z;
- }
- void atree_start(des,lf)
- design *des;
- lfit *lf;
- { int d, i, j, k, vc, ncm, nvm;
- double ll[MXDIM], ur[MXDIM];
- if (lf_debug>1) mut_printf(" In atree_start\n");
- d = lf->fp.d;
- atree_guessnv(&lf->evs,&nvm,&ncm,&vc,d,nn(&lf->sp));
- if (lf_debug>2) mut_printf(" atree_start: nvm %d ncm %d\n",nvm,ncm);
- trchck(lf,nvm,ncm,vc);
- /* Set the lower left, upper right limits. */
- for (j=0; j<d; j++)
- { ll[j] = lf->evs.fl[j];
- ur[j] = lf->evs.fl[j+d];
- }
- /* Set the initial cell; fit at the vertices. */
- for (i=0; i<vc; i++)
- { j = i;
- for (k=0; k<d; ++k)
- { evptx(&lf->fp,i,k) = (j%2) ? ur[k] : ll[k];
- j >>= 1;
- }
- lf->evs.ce[i] = i;
- PROC_VERTEX(des,lf,i);
- if (lf_error) return;
- lf->evs.s[i] = 0;
- }
- lf->fp.nv = vc;
- /* build the tree */
- atree_grow(des,lf,lf->evs.ce,NULL,NULL,ll,ur);
- lf->evs.nce = 1;
- }
- double atree_int(lf,x,what)
- lfit *lf;
- double *x;
- int what;
- { double vv[64][64], *ll, *ur, h, xx[MXDIM];
- int lo, tk, ns, nv, nc, d, i, vc;
- int ce[64];
- fitpt *fp;
- evstruc *evs;
- fp = &lf->fp;
- evs= &lf->evs;
- d = fp->d;
- vc = 1<<d;
- for (i=0; i<vc; i++)
- { setzero(vv[i],vc);
- nc = exvval(fp,vv[i],i,d,what,1);
- ce[i] = evs->ce[i];
- }
- ns = 0;
- while(ns!=-1)
- { ll = evpt(fp,ce[0]); ur = evpt(fp,ce[vc-1]);
- ns = atree_split(lf,ce,xx,ll,ur);
- if (ns!=-1)
- { tk = 1<<ns;
- h = ur[ns]-ll[ns];
- lo = (2*(x[ns]-ll[ns])) < h;
- for (i=0; i<vc; i++) if ((tk&i)==0)
- { nv = findpt(fp,evs,(int)ce[i],(int)ce[i+tk]);
- if (nv==-1) LERR(("Descend tree problem"));
- if (lf_error) return(0.0);
- if (lo)
- { ce[i+tk] = nv;
- if (evs->s[nv]) exvvalpv(vv[i+tk],vv[i],vv[i+tk],d,ns,h,nc);
- else exvval(fp,vv[i+tk],nv,d,what,1);
- }
- else
- { ce[i] = nv;
- if (evs->s[nv]) exvvalpv(vv[i],vv[i],vv[i+tk],d,ns,h,nc);
- else exvval(fp,vv[i],nv,d,what,1);
- } }
- } }
- ll = evpt(fp,ce[0]); ur = evpt(fp,ce[vc-1]);
- return(rectcell_interp(x,vv,ll,ur,d,nc));
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- double linear_interp(h,d,f0,f1)
- double h, d, f0, f1;
- { if (d==0) return(f0);
- return( ( (d-h)*f0 + h*f1 ) / d );
- }
- void hermite2(x,z,phi)
- double x, z, *phi;
- { double h;
- if (z==0)
- { phi[0] = 1.0; phi[1] = phi[2] = phi[3] = 0.0;
- return;
- }
- h = x/z;
- if (h<0)
- { phi[0] = 1; phi[1] = 0;
- phi[2] = h; phi[3] = 0;
- return;
- }
- if (h>1)
- { phi[0] = 0; phi[1] = 1;
- phi[2] = 0; phi[3] = h-1;
- return;
- }
- phi[1] = h*h*(3-2*h);
- phi[0] = 1-phi[1];
- phi[2] = h*(1-h)*(1-h);
- phi[3] = h*h*(h - 1);
- }
- double cubic_interp(h,f0,f1,d0,d1)
- double h, f0, f1, d0, d1;
- { double phi[4];
- hermite2(h,1.0,phi);
- return(phi[0]*f0+phi[1]*f1+phi[2]*d0+phi[3]*d1);
- }
- double cubintd(h,f0,f1,d0,d1)
- double h, f0, f1, d0, d1;
- { double phi[4];
- phi[1] = 6*h*(1-h);
- phi[0] = -phi[1];
- phi[2] = (1-h)*(1-3*h);
- phi[3] = h*(3*h-2);
- return(phi[0]*f0+phi[1]*f1+phi[2]*d0+phi[3]*d1);
- }
- /*
- interpolate over a rectangular cell.
- x = interpolation point.
- vv = array of vertex values.
- ll = lower left corner.
- ur = upper right corner.
- d = dimension.
- nc = no of coefficients.
- */
- double rectcell_interp(x,vv,ll,ur,d,nc)
- double *x, vv[64][64], *ll, *ur;
- int d, nc;
- { double phi[4];
- int i, j, k, tk;
- tk = 1<<d;
- for (i=0; i<tk; i++) if (vv[i][0]==NOSLN) return(NOSLN);
- /* no derivatives - use multilinear interpolation */
- if (nc==1)
- { for (i=d-1; i>=0; i--)
- { tk = 1<<i;
- for (j=0; j<tk; j++)
- vv[j][0] = linear_interp(x[i]-ll[i],ur[i]-ll[i],vv[j][0],vv[j+tk][0]);
- }
- return(vv[0][0]);
- }
- /* with derivatives -- use cubic */
- if (nc==d+1)
- { for (i=d-1; i>=0; i--)
- { hermite2(x[i]-ll[i],ur[i]-ll[i],phi);
- tk = 1<<i;
- phi[2] *= ur[i]-ll[i];
- phi[3] *= ur[i]-ll[i];
- for (j=0; j<tk; j++)
- { vv[j][0] = phi[0]*vv[j][0] + phi[1]*vv[j+tk][0]
- + phi[2]*vv[j][i+1] + phi[3]*vv[j+tk][i+1];
- for (k=1; k<=i; k++)
- vv[j][k] = phi[0]*vv[j][k] + phi[1]*vv[j+tk][k];
- }
- }
- return(vv[0][0]);
- }
- /* with all coefs -- use multicubic */
- for (i=d-1; i>=0; i--)
- { hermite2(x[i]-ll[i],ur[i]-ll[i],phi);
- tk = 1<<i;
- phi[2] *= ur[i]-ll[i];
- phi[3] *= ur[i]-ll[i];
- for (j=0; j<tk; j++)
- for (k=0; k<tk; k++)
- vv[j][k] = phi[0]*vv[j][k] + phi[1]*vv[j+tk][k]
- + phi[2]*vv[j][k+tk] + phi[3]*vv[j+tk][k+tk];
- }
- return(vv[0][0]);
- }
- int exvval(fp,vv,nv,d,what,z)
- fitpt *fp;
- double *vv;
- int nv, d, z, what;
- { int i, k;
- double *values;
- k = (z) ? 1<<d : d+1;
- for (i=1; i<k; i++) vv[i] = 0.0;
- switch(what)
- { case PCOEF:
- values = fp->coef;
- break;
- case PVARI:
- case PNLX:
- values = fp->nlx;
- break;
- case PT0:
- values = fp->t0;
- break;
- case PBAND:
- vv[0] = fp->h[nv];
- return(1);
- case PDEGR:
- vv[0] = fp->deg[nv];
- return(1);
- case PLIK:
- vv[0] = fp->lik[nv];
- return(1);
- case PRDF:
- vv[0] = fp->lik[2*fp->nvm+nv];
- return(1);
- default:
- LERR(("Invalid what in exvval"));
- return(0);
- }
- vv[0] = values[nv];
- if (!fp->hasd) return(1);
- if (z)
- { for (i=0; i<d; i++) vv[1<<i] = values[(i+1)*fp->nvm+nv];
- return(1<<d);
- }
- else
- { for (i=1; i<=d; i++) vv[i] = values[i*fp->nvm+nv];
- return(d+1);
- }
- }
- void exvvalpv(vv,vl,vr,d,k,dl,nc)
- double *vv, *vl, *vr, dl;
- int d, k, nc;
- { int i, tk, td;
- double f0, f1;
- if (nc==1)
- { vv[0] = (vl[0]+vr[0])/2;
- return;
- }
- tk = 1<<k;
- td = 1<<d;
- for (i=0; i<td; i++) if ((i&tk)==0)
- { f0 = (vl[i]+vr[i])/2 + dl*(vl[i+tk]-vr[i+tk])/8;
- f1 = 1.5*(vr[i]-vl[i])/dl - (vl[i+tk]+vr[i+tk])/4;
- vv[i] = f0;
- vv[i+tk] = f1;
- }
- }
- double grid_int(fp,evs,x,what)
- fitpt *fp;
- evstruc *evs;
- double *x;
- int what;
- { int d, i, j, jj, nc, sk, v[MXDIM], vc, z0, nce[1<<MXDIM], *mg;
- double *ll, *ur, vv[64][64], z;
- d = fp->d;
- ll = evpt(fp,0); ur = evpt(fp,fp->nv-1);
- mg = mg(evs);
- z0 = 0; vc = 1<<d;
- for (j=d-1; j>=0; j--)
- { v[j] = (int)((mg[j]-1)*(x[j]-ll[j])/(ur[j]-ll[j]));
- if (v[j]<0) v[j]=0;
- if (v[j]>=mg[j]-1) v[j] = mg[j]-2;
- z0 = z0*mg[j]+v[j];
- }
- nce[0] = z0; nce[1] = z0+1; sk = jj = 1;
- for (i=1; i<d; i++)
- { sk *= mg[i-1];
- jj<<=1;
- for (j=0; j<jj; j++)
- nce[j+jj] = nce[j]+sk;
- }
- for (i=0; i<vc; i++)
- nc = exvval(fp,vv[i],nce[i],d,what,1);
- ll = evpt(fp,nce[0]);
- ur = evpt(fp,nce[vc-1]);
- z = rectcell_interp(x,vv,ll,ur,d,nc);
- return(z);
- }
- double fitp_int(fp,x,what,i)
- fitpt *fp;
- double *x;
- int what, i;
- { double vv[1+MXDIM];
- exvval(fp,vv,i,fp->d,what,0);
- return(vv[0]);
- }
- double xbar_int(fp,x,what)
- fitpt *fp;
- double *x;
- int what;
- { int i, nc;
- double vv[1+MXDIM], f;
- nc = exvval(fp,vv,0,fp->d,what,0);
- f = vv[0];
- if (nc>1)
- for (i=0; i<fp->d; i++)
- f += vv[i+1]*(x[i]-evptx(fp,0,i));
- return(f);
- }
- double dointpoint(lf,x,what,ev,j)
- lfit *lf;
- double *x;
- int what, ev, j;
- { double xf, f, link[LLEN];
- int i, rt;
- fitpt *fp;
- evstruc *evs;
- fp = &lf->fp; evs = &lf->evs;
- for (i=0; i<fp->d; i++) if (lf->lfd.sty[i]==STANGL)
- { xf = floor(x[i]/(2*PI*lf->lfd.sca[i]));
- x[i] -= xf*2*PI*lf->lfd.sca[i];
- }
- if (what > 64)
- { rt = what-64;
- what = PCOEF;
- }
- else rt = 0;
- switch(ev)
- { case EGRID: f = grid_int(fp,evs,x,what); break;
- case EKDTR: f = kdtre_int(fp,evs,x,what); break;
- case ETREE: f = atree_int(lf,x,what); break;
- case EPHULL: f = triang_int(lf,x,what); break;
- case EFITP: f = fitp_int(fp,x,what,j); break;
- case EXBAR: f = xbar_int(fp,x,what); break;
- case ENONE: f = 0; break;
- case ESPHR: f = sphere_int(lf,x,what); break;
- default: LERR(("dointpoint: cannot interpolate structure %d",ev));
- }
- if (((what==PT0)|(what==PNLX)) && (f<0)) f = 0.0;
- f += addparcomp(lf,x,what);
- if (rt>0)
- {
- stdlinks(link,&lf->lfd,&lf->sp,j,f,rsc(fp));
- f = resid(resp(&lf->lfd,j),prwt(&lf->lfd,j),f,fam(&lf->sp),rt,link);
- }
- return(f);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Routines for building and interpolating the kd tree.
- * Initially, this started from the loess code.
- *
- * Todo: EKDCE isn't working.
- */
- #include "lfev.h"
- void newcell();
- static int nterm;
- void kdtre_guessnv(evs,nvm,ncm,vc,n,d,alp)
- evstruc *evs;
- double alp;
- int *nvm, *ncm, *vc, n, d;
- { int k;
- if (ev(evs) == EKDTR)
- { nterm = (int)(cut(evs)/4 * n * MIN(alp,1.0) );
- k = 2*n/nterm;
- *vc = 1<<d;
- *ncm = 2*k+1;
- *nvm = (k+2)**vc/2;
- return;
- }
- if (ev(evs) == EKDCE)
- { nterm = (int)(n * alp);
- *vc = 1;
- *nvm = 1+(int)(2*n/nterm);
- *ncm = 2**nvm+1;
- return;
- }
- *nvm = *ncm = *vc = 0;
- return;
- }
- /*
- Split x[pi[l..r]] into two equal sized sets.
- Let m=(l+r)/2.
- At return,
- x[pi[l..m]] < x[pi[m+1..r]].
- Assuming no ties:
- If l+r is odd, the sets have the same size.
- If l+r is even, the low set is larger by 1.
- If there are ties, all ties go in the low set.
- */
- int ksmall(l, r, m, x, pi)
- int l, r, m, *pi;
- double *x;
- {
- int il, ir, jl, jr;
- double t;
- while(l<r)
- { t = x[pi[m]];
- /*
- permute the observations so that
- x[pi[l..il]] < t <= x[pi[ir..r]].
- */
- ir = l; il = r;
- while (ir<il)
- { while ((ir<=r) && (x[pi[ir]] < t)) ir++;
- while ((il>=l) && (x[pi[il]]>= t)) il--;
- if (ir<il) ISWAP(pi[ir],pi[il]);
- }
- /*
- move = t to the middle:
- x[pi[l..il]] < t
- x[pi[jl..jr]] = t
- x[pi[ir..r]] > t
- */
- jl = ir; jr = r;
- while (ir<jr)
- { while ((ir<=r) && (x[pi[ir]]== t)) ir++;
- while ((jr>=jl) && (x[pi[jr]] > t)) jr--;
- if (ir<jr) ISWAP(pi[ir],pi[jr]);
- }
- /*
- we're done if m is in the middle, jl <= m <= jr.
- */
- if ((jl<=m) & (jr>=m)) return(jr);
- /*
- update l or r.
- */
- if (m>=ir) l = ir;
- if (m<=il) r = il;
- }
- if (l==r) return(l);
- LERR(("ksmall failure"));
- return(0);
- }
- int terminal(lf,p,pi,fc,d,m,split_val)
- lfit *lf;
- int p, d, fc, *m, *pi;
- double *split_val;
- { int i, k, lo, hi, split_var;
- double max, min, score, max_score, t;
- /*
- if there are fewer than fc points in the cell, this cell
- is terminal.
- */
- lo = lf->evs.lo[p]; hi = lf->evs.hi[p];
- if (hi-lo < fc) return(-1);
- /* determine the split variable */
- max_score = 0.0; split_var = 0;
- for (k=0; k<d; k++)
- { max = min = datum(&lf->lfd, k, pi[lo]);
- for (i=lo+1; i<=hi; i++)
- { t = datum(&lf->lfd,k,pi[i]);
- if (t<min) min = t;
- if (t>max) max = t;
- }
- score = (max-min) / lf->lfd.sca[k];
- if (score > max_score)
- { max_score = score;
- split_var = k;
- }
- }
- if (max_score==0) /* all points in the cell are equal */
- return(-1);
- *m = ksmall(lo,hi,(lo+hi)/2, dvari(&lf->lfd,split_var), pi);
- *split_val = datum(&lf->lfd, split_var, pi[*m]);
- if (*m==hi) /* all observations go lo */
- return(-1);
- return(split_var);
- }
- void kdtre_start(des,lf)
- design *des;
- lfit *lf;
- {
- int i, j, vc, d, nc, nv, ncm, nvm, k, m, n, p, *pi;
- double sv;
- d = lf->lfd.d; n = lf->lfd.n; pi = des->ind;
- kdtre_guessnv(&lf->evs,&nvm,&ncm,&vc,n,d,nn(&lf->sp));
- trchck(lf,nvm,ncm,vc);
- nv = 0;
- if (ev(&lf->evs) != EKDCE)
- { for (i=0; i<vc; i++)
- { j = i;
- for (k=0; k<d; ++k)
- { evptx(&lf->fp,i,k) = lf->evs.fl[d*(j%2)+k];
- j >>= 1;
- }
- }
- nv = vc;
- for (j=0; j<vc; j++) lf->evs.ce[j] = j;
- }
- for (i=0; i<n; i++) pi[i] = i;
- p = 0; nc = 1;
- lf->evs.lo[p] = 0; lf->evs.hi[p] = n-1;
- lf->evs.s[p] = -1;
- while (p<nc)
- { k = terminal(lf,p,pi,nterm,d,&m,&sv);
- if (k>=0)
- {
- if ((ncm<nc+2) | (2*nvm<2*nv+vc))
- { WARN(("Insufficient space for full tree"));
- lf->evs.nce = nc; lf->fp.nv = nv;
- return;
- }
- /* new lo cell has obsn's lo[p]..m */
- lf->evs.lo[nc] = lf->evs.lo[p];
- lf->evs.hi[nc] = m;
- lf->evs.s[nc] = -1;
- /* new hi cell has obsn's m+1..hi[p] */
- lf->evs.lo[nc+1] = m+1;
- lf->evs.hi[nc+1] = lf->evs.hi[p];
- lf->evs.s[nc+1] = -1;
- /* cell p is split on variable k, value sv */
- lf->evs.s[p] = k;
- lf->evs.sv[p] = sv;
- lf->evs.lo[p] = nc; lf->evs.hi[p] = nc+1;
- nc=nc+2; i = nv;
- /* now compute the new vertices. */
- if (ev(&lf->evs) != EKDCE)
- newcell(&nv,vc,evp(&lf->fp), d, k, sv,
- &lf->evs.ce[p*vc], &lf->evs.ce[(nc-2)*vc], &lf->evs.ce[(nc-1)*vc]);
- }
- else if (ev(&lf->evs)==EKDCE) /* new vertex at cell center */
- { sv = 0;
- for (i=0; i<d; i++) evptx(&lf->fp,nv,i) = 0;
- for (j=lf->evs.lo[p]; j<=lf->evs.hi[p]; j++)
- { sv += prwt(&lf->lfd,(int)pi[j]);
- for (i=0; i<d; i++)
- evptx(&lf->fp,nv,i) += datum(&lf->lfd,i,pi[j])*prwt(&lf->lfd,(int)pi[j]);
- }
- for (i=0; i<d; i++) evptx(&lf->fp,nv,i) /= sv;
- lf->lfd.n = lf->evs.hi[p] - lf->evs.lo[p] + 1;
- des->ind = &pi[lf->evs.lo[p]]; /* why? */
- PROC_VERTEX(des,lf,nv);
- lf->lfd.n = n; des->ind = pi;
- nv++;
- }
- p++;
- }
- /* We've built the tree. Now do the fitting. */
- if (ev(&lf->evs)==EKDTR)
- for (i=0; i<nv; i++) PROC_VERTEX(des,lf,i);
- lf->evs.nce = nc; lf->fp.nv = nv;
- return;
- }
- void newcell(nv,vc,xev, d, k, split_val, cpar, clef, crig)
- double *xev, split_val;
- int *cpar, *clef, *crig;
- int *nv, vc, d, k;
- { int i, ii, j, j2, tk, match;
- tk = 1<<k;
- for (i=0; i<vc; i++)
- { if ((i&tk) == 0)
- { for (j=0; j<d; j++) xev[*nv*d+j] = xev[d*cpar[i]+j];
- xev[*nv*d+k] = split_val;
- match = 0; j = vc; /* no matches in first vc points */
- while ((j<*nv) && (!match))
- { j2 = 0;
- while ((j2<d) && (xev[*nv*d+j2] == xev[j*d+j2])) j2++;
- match = (j2==d);
- if (!match) j++;
- }
- ii = i+tk;
- clef[i] = cpar[i];
- clef[ii]= crig[i] = j;
- crig[ii]= cpar[ii];
- if (!match) (*nv)++;
- }
- }
- return;
- }
- extern void hermite2();
- double blend(fp,evs,s,x,ll,ur,j,nt,t,what)
- fitpt *fp;
- evstruc *evs;
- double s, *x, *ll, *ur;
- int j, nt, *t, what;
- {
- int *ce, k, k1, m, nc, j0, j1;
- double v0, v1, xibar, g0[3], g1[3], gg[4], gp[4], phi[4];
- ce = evs->ce;
- for (k=0; k<4; k++) /* North South East West */
- { k1 = (k>1);
- v0 = ll[k1]; v1 = ur[k1];
- j0 = ce[j+2*(k==0)+(k==2)];
- j1 = ce[j+3-2*(k==1)-(k==3)];
- xibar = (k%2==0) ? ur[k<2] : ll[k<2];
- m = nt;
- while ((m>=0) && ((evs->s[t[m]] != (k<=1)) | (evs->sv[t[m]] != xibar))) m--;
- if (m >= 0)
- { m = (k%2==1) ? evs->lo[t[m]] : evs->hi[t[m]];
- while (evs->s[m] != -1)
- m = (x[evs->s[m]] < evs->sv[m]) ? evs->lo[m] : evs->hi[m];
- if (v0 < evptx(fp,ce[4*m+2*(k==1)+(k==3)],k1))
- { j0 = ce[4*m+2*(k==1)+(k==3)];
- v0 = evptx(fp,j0,k1);
- }
- if (evptx(fp,ce[4*m+3-2*(k==0)-(k==2)],k1) < v1)
- { j1 = ce[4*m+3-2*(k==0)-(k==2)];
- v1 = evptx(fp,j1,k1);
- }
- }
- nc = exvval(fp,g0,j0,2,what,0);
- nc = exvval(fp,g1,j1,2,what,0);
- if (nc==1)
- gg[k] = linear_interp((x[(k>1)]-v0),v1-v0,g0[0],g1[0]);
- else
- { hermite2(x[(k>1)]-v0,v1-v0,phi);
- gg[k] = phi[0]*g0[0]+phi[1]*g1[0]+(phi[2]*g0[1+k1]+phi[3]*g1[1+k1])*(v1-v0);
- gp[k] = phi[0]*g0[2-k1] + phi[1]*g1[2-k1];
- }
- }
- s = -s;
- if (nc==1)
- for (k=0; k<2; k++)
- s += linear_interp(x[k]-ll[k],ur[k]-ll[k],gg[3-2*k],gg[2-2*k]);
- else
- for (k=0; k<2; k++) /* EW NS */
- { hermite2(x[k]-ll[k],ur[k]-ll[k],phi);
- s += phi[0]*gg[3-2*k] + phi[1]*gg[2-2*k]
- +(phi[2]*gp[3-2*k] + phi[3]*gp[2-2*k]) * (ur[k]-ll[k]);
- }
- return(s);
- }
- double kdtre_int(fp,evs,x,what)
- fitpt *fp;
- evstruc *evs;
- double *x;
- int what;
- {
- int *ce, k, vc, t[20], nt, nc, j, d;
- double *ll, *ur, ff, vv[64][64];
- d = fp->d;
- vc = 1<<d;
- if (d > 6) { LERR(("d too large in kdint")); return(NOSLN); }
- /* descend the tree to find the terminal cell */
- nt = 0; t[nt] = 0; k = 0;
- while (evs->s[k] != -1)
- { nt++;
- if (nt>=20) { LERR(("Too many levels in kdint")); return(NOSLN); }
- k = t[nt] = (x[evs->s[k]] < evs->sv[k]) ? evs->lo[k] : evs->hi[k];
- }
- ce = &evs->ce[k*vc];
- ll = evpt(fp,ce[0]);
- ur = evpt(fp,ce[vc-1]);
- nc = 0;
- for (j=0; j<vc; j++) nc = exvval(fp,vv[j],(int)ce[j],d,what,0);
- ff = rectcell_interp(x,vv,ll,ur,d,nc);
- if (d==2) ff = blend(fp,evs,ff,x,ll,ur,k*vc,nt,t,what);
- return(ff);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- /*
- * convert eval. structure string to numeric code.
- */
- #define NETYPE 11
- static char *etype[NETYPE]= { "tree", "phull", "data", "grid", "kdtree",
- "kdcenter", "cross", "preset", "xbar", "none",
- "sphere" };
- static int evals[NETYPE]= { ETREE, EPHULL, EDATA, EGRID, EKDTR,
- EKDCE, ECROS, EPRES, EXBAR, ENONE, ESPHR };
- int lfevstr(char *z)
- { return(pmatch(z, etype, evals, NETYPE, -1));
- }
- void evstruc_init(evs)
- evstruc *evs;
- { int i;
- ev(evs) = ETREE;
- mk(evs) = 100;
- cut(evs) = 0.8;
- for (i=0; i<MXDIM; i++)
- { evs->fl[i] = evs->fl[i+MXDIM] = 0.0;
- evs->mg[i] = 10;
- }
- evs->nce = evs->ncm = 0;
- }
- int evstruc_reqi(nvm,ncm,vc)
- int nvm, ncm, vc;
- { return(ncm*vc+3*MAX(ncm,nvm));
- }
- /* al=1: allows dynamic allocation.
- * al=0: inhibit. use with caution.
- */
- void evstruc_alloc(evs,nvm,ncm,vc,al)
- evstruc *evs;
- int nvm, ncm, vc, al;
- { int rw, *k;
- if (al)
- { rw = evstruc_reqi(nvm,ncm,vc);
- if (evs->liw<rw)
- { evs->iwk = (int *)calloc(rw,sizeof(int));
- if ( evs->iwk == NULL ) {
- printf("Problem allocating memory for evs->iwk\n");fflush(stdout);
- }
- evs->liw = rw;
- }
- }
- k = evs->iwk;
- evs->ce = k; k += vc*ncm;
- evs->s = k; k += MAX(ncm,nvm);
- evs->lo = k; k += MAX(ncm,nvm);
- evs->hi = k; k += MAX(ncm,nvm);
- }
- void guessnv(evs,sp,mdl,n,d,lw,nvc)
- evstruc *evs;
- smpar *sp;
- module *mdl;
- int n, d, *lw, *nvc;
- { int i, nvm, ncm, vc;
- npar(sp) = calcp(sp,d);
- switch(ev(evs))
- { case ETREE:
- atree_guessnv(evs,&nvm,&ncm,&vc,d,nn(sp));
- break;
- case EPHULL:
- nvm = ncm = mk(evs)*d;
- vc = d+1;
- break;
- case EDATA:
- case ECROS:
- nvm = n;
- ncm = vc = 0;
- break;
- case EKDTR:
- case EKDCE:
- kdtre_guessnv(evs,&nvm,&ncm,&vc,n,d,nn(sp));
- break;
- case EGRID:
- nvm = 1;
- for (i=0; i<d; i++) nvm *= evs->mg[i];
- ncm = 0;
- vc = 1<<d;
- break;
- case EXBAR:
- case ENONE:
- nvm = 1;
- ncm = vc = 0;
- break;
- case EPRES:
- nvm = evs->mg[0];
- ncm = vc = 0;
- break;
- default:
- LERR(("guessnv: I don't know this evaluation structure."));
- nvm = ncm = vc = 0;
- }
- lw[0] = des_reqd(n,npar(sp));
- lw[1] = lfit_reqd(d,nvm,ncm,mdl);
- lw[2] = evstruc_reqi(nvm,ncm,vc);
- lw[6] = des_reqi(n,npar(sp));
- lw[3] = pc_reqd(d,npar(sp));
- lw[4] = mdl->keepv;
- lw[5] = mdl->keepc;
- if (nvc==NULL) return;
- nvc[0] = nvm;
- nvc[1] = ncm;
- nvc[2] = vc;
- nvc[3] = nvc[4] = 0;
- }
- /*
- * trchck checks the working space on the lfit structure
- * has space for nvm vertices and ncm cells.
- */
- void lfit_alloc(lf)
- lfit *lf;
- { lf->fp.lwk = lf->fp.lev = lf->evs.liw = lf->pc.lwk = 0;
- lf->lf_init_id = LF_INIT_ID;
- }
- int lfit_reqd(d,nvm,ncm,mdl)
- int d, nvm, ncm;
- module *mdl;
- { int z;
- z = mdl->keepv;
- return(nvm*z+ncm);
- }
- void trchck(lf,nvm,ncm,vc)
- lfit *lf;
- int nvm, ncm, vc;
- { int rw, d, *k;
- double *z;
- if (lf->lf_init_id != LF_INIT_ID) lfit_alloc(lf);
- lf->fp.nvm = nvm; lf->evs.ncm = ncm;
- d = lf->lfd.d;
- if (lf->fp.lev < d*nvm)
- { lf->fp.xev = (double *)calloc(d*nvm,sizeof(double));
- if ( lf->fp.xev == NULL ) {
- printf("Problem allocating memory for lf->fp.xev\n");fflush(stdout);
- }
- lf->fp.lev = d*nvm;
- }
- rw = lfit_reqd(d,nvm,ncm,&lf->mdl);
- if (lf->fp.lwk < rw)
- {
- lf->fp.coef = (double *)calloc(rw,sizeof(double));
- if ( lf->fp.coef == NULL ) {
- printf("Problem allocating memory for lf->fp.coef\n");fflush(stdout);
- }
- lf->fp.lwk = rw;
- }
- z = lf->fp.wk = lf->fp.coef;
- lf->fp.h = NULL;
- if (!lf->mdl.isset) mut_printf("module not set.\n");
- else
- { if (lf->mdl.alloc!=NULL) lf->mdl.alloc(lf);
- z += KEEPV(lf) * nvm;
- }
- lf->evs.sv = z; z += ncm;
- evstruc_alloc(&lf->evs,nvm,ncm,vc,1);
- }
- void data_guessnv(nvm,ncm,vc,n)
- int *nvm, *ncm, *vc, n;
- { *nvm = n;
- *ncm = *vc = 0;
- }
- void dataf(des,lf)
- design *des;
- lfit *lf;
- {
- int d, i, j, ncm, nv, vc;
- d = lf->lfd.d;
- data_guessnv(&nv,&ncm,&vc,lf->lfd.n);
- trchck(lf,nv,ncm,vc);
- for (i=0; i<nv; i++)
- for (j=0; j<d; j++) evptx(&lf->fp,i,j) = datum(&lf->lfd,j,i);
- for (i=0; i<nv; i++)
- {
- PROC_VERTEX(des,lf,i);
- lf->evs.s[i] = 0;
- }
- lf->fp.nv = lf->fp.nvm = nv; lf->evs.nce = 0;
- }
- void xbar_guessnv(nvm,ncm,vc)
- int *nvm, *ncm, *vc;
- { *nvm = 1;
- *ncm = *vc = 0;
- return;
- }
- void xbarf(des,lf)
- design *des;
- lfit *lf;
- { int i, d, nvm, ncm, vc;
- d = lf->lfd.d;
- xbar_guessnv(&nvm,&ncm,&vc);
- trchck(lf,1,0,0);
- for (i=0; i<d; i++) evptx(&lf->fp,0,i) = lf->pc.xbar[i];
- PROC_VERTEX(des,lf,0);
- lf->evs.s[0] = 0;
- lf->fp.nv = 1; lf->evs.nce = 0;
- }
- void preset(des,lf)
- design *des;
- lfit *lf;
- { int i, nv;
- nv = lf->fp.nvm;
- trchck(lf,nv,0,0);
- for (i=0; i<nv; i++)
- {
- PROC_VERTEX(des,lf,i);
- lf->evs.s[i] = 0;
- }
- lf->fp.nv = nv; lf->evs.nce = 0;
- }
- void crossf(des,lf)
- design *des;
- lfit *lf;
- { int d, i, j, n, nv, ncm, vc;
- double w;
- n = lf->lfd.n; d = lf->lfd.d;
- data_guessnv(&nv,&ncm,&vc,n);
- trchck(lf,nv,ncm,vc);
- if (lf->lfd.w==NULL) LERR(("crossf() needs prior weights"));
- for (i=0; i<n; i++)
- for (j=0; j<d; j++) evptx(&lf->fp,i,j) = datum(&lf->lfd,j,i);
- for (i=0; i<n; i++)
- { lf->evs.s[i] = 0;
- w = prwt(&lf->lfd,i);
- lf->lfd.w[i] = 0;
- PROC_VERTEX(des,lf,i);
- lf->lfd.w[i] = w;
- }
- lf->fp.nv = n; lf->evs.nce = 0;
- }
- void gridf(des,lf)
- design *des;
- lfit *lf;
- { int d, i, j, nv, u0, u1, z;
- nv = 1; d = lf->lfd.d;
- for (i=0; i<d; i++)
- { if (lf->evs.mg[i]==0)
- lf->evs.mg[i] = 2+(int)((lf->evs.fl[i+d]-lf->evs.fl[i])/(lf->lfd.sca[i]*cut(&lf->evs)));
- nv *= lf->evs.mg[i];
- }
- trchck(lf,nv,0,1<<d);
- for (i=0; i<nv; i++)
- { z = i;
- for (j=0; j<d; j++)
- { u0 = z%lf->evs.mg[j];
- u1 = lf->evs.mg[j]-1-u0;
- evptx(&lf->fp,i,j) = (lf->evs.mg[j]==1) ? lf->evs.fl[j] :
- (u1*lf->evs.fl[j]+u0*lf->evs.fl[j+d])/(lf->evs.mg[j]-1);
- z = z/lf->evs.mg[j];
- }
- lf->evs.s[i] = 0;
- PROC_VERTEX(des,lf,i);
- }
- lf->fp.nv = nv; lf->evs.nce = 0;
- }
- int findpt(fp,evs,i0,i1)
- fitpt *fp;
- evstruc *evs;
- int i0, i1;
- { int i;
- if (i0>i1) ISWAP(i0,i1);
- for (i=i1+1; i<fp->nv; i++)
- if ((evs->lo[i]==i0) && (evs->hi[i]==i1)) return(i);
- return(-1);
- }
- /*
- add a new vertex at the midpoint of (x[i0],x[i1]).
- return the vertex number.
- */
- int newsplit(des,lf,i0,i1,pv)
- design *des;
- lfit *lf;
- int i0, i1, pv;
- { int i, nv;
- i = findpt(&lf->fp,&lf->evs,i0,i1);
- if (i>=0) return(i);
- if (i0>i1) ISWAP(i0,i1);
- nv = lf->fp.nv;
-
- /* the point is new. Now check we have space for the new point. */
- if (nv>=lf->fp.nvm)
- {
- LERR(("newsplit: out of vertex space"));
- return(-1);
- }
- /* compute the new point, and evaluate the fit */
- lf->evs.lo[nv] = i0;
- lf->evs.hi[nv] = i1;
- for (i=0; i<lf->fp.d; i++)
- evptx(&lf->fp,nv,i) = (evptx(&lf->fp,i0,i)+evptx(&lf->fp,i1,i))/2;
- if (pv) /* pseudo vertex */
- { lf->fp.h[nv] = (lf->fp.h[i0]+lf->fp.h[i1])/2;
- lf->evs.s[nv] = 1; /* pseudo-vertex */
- }
- else /* real vertex */
- {
- PROC_VERTEX(des,lf,nv);
- lf->evs.s[nv] = 0;
- }
- lf->fp.nv++;
- return(nv);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Functions for constructing the fit and
- * interpolating on the circle/sphere. d=2 only.
- */
- #include "lfev.h"
- /*
- * Guess the number of fitting points.
- */
- void sphere_guessnv(nvm,ncm,vc,mg)
- int *nvm, *ncm, *vc, *mg;
- { *nvm = mg[1]*(mg[0]+1);
- *ncm = 0;
- *vc = 0;
- }
- void sphere_start(des,lf)
- design *des;
- lfit *lf;
- { int d, i, j, ct, nv, ncm, vc, *mg;
- double rmin, rmax, *orig, r, th, c, s;
- mg = mg(&lf->evs);
- sphere_guessnv(&nv,&ncm,&vc,mg);
- trchck(lf,nv,0,0);
- d = lf->lfd.d;
- rmin = lf->evs.fl[0];
- rmax = lf->evs.fl[1];
- orig = &lf->evs.fl[2];
- rmin = 0; rmax = 1; orig[0] = orig[1] = 0.0;
- ct = 0;
- for (i=0; i<mg[1]; i++)
- { th = 2*PI*i/mg[1];
- c = cos(th);
- s = sin(th);
- for (j=0; j<=mg[0]; j++)
- { r = rmin + (rmax-rmin)*j/mg[0];
- evptx(&lf->fp,ct,0) = orig[0] + r*c;
- evptx(&lf->fp,ct,1) = orig[1] + r*s;
- PROC_VERTEX(des,lf,ct);
- ct++;
- }
- }
- lf->fp.nv = ct;
- lf->evs.nce = 0;
- }
- double sphere_int(lf,x,what)
- lfit *lf;
- double *x;
- int what;
- { double rmin, rmax, *orig, dx, dy, r, th, th0, th1;
- double v[64][64], c0, c1, s0, s1, r0, r1, d0, d1;
- double ll[2], ur[2], xx[2];
- int i0, j0, i1, j1, *mg, nc, ce[4];
- rmin = lf->evs.fl[0];
- rmax = lf->evs.fl[1];
- orig = &lf->evs.fl[2];
- rmin = 0; rmax = 1; orig[0] = orig[1] = 0.0;
- mg = mg(&lf->evs);
- dx = x[0] - orig[0];
- dy = x[1] - orig[1];
- r = sqrt(dx*dx+dy*dy);
- th = atan2(dy,dx); /* between -pi and pi */
- i0 = (int)floor(mg[1]*th/(2*PI)) % mg[1];
- j0 = (int)(mg[0]*(r-rmin)/(rmax-rmin));
- i1 = (i0+1) % mg[1];
- j1 = j0+1; if (j1>mg[0]) { j0 = mg[0]-1; j1 = mg[0]; }
- ce[0] = i0*(mg[0]+1)+j0;
- ce[1] = i0*(mg[0]+1)+j1;
- ce[2] = i1*(mg[0]+1)+j0;
- ce[3] = i1*(mg[0]+1)+j1;
- nc = exvval(&lf->fp,v[0],ce[0],2,what,1);
- nc = exvval(&lf->fp,v[1],ce[1],2,what,1);
- nc = exvval(&lf->fp,v[2],ce[2],2,what,1);
- nc = exvval(&lf->fp,v[3],ce[3],2,what,1);
- th0 = 2*PI*i0/mg[1]; c0 = cos(th0); s0 = sin(th0);
- th1 = 2*PI*i1/mg[1]; c1 = cos(th1); s1 = sin(th1);
- r0 = rmin + j0*(rmax-rmin)/mg[0];
- r1 = rmin + j1*(rmax-rmin)/mg[0];
-
- d0 = c0*v[0][1] + s0*v[0][2];
- d1 = r0*(c0*v[0][2]-s0*v[0][1]);
- v[0][1] = d0; v[0][2] = d1;
- d0 = c0*v[1][1] + s0*v[1][2];
- d1 = r1*(c0*v[1][2]-s0*v[1][1]);
- v[1][1] = d0; v[1][2] = d1;
- d0 = c1*v[2][1] + s1*v[2][2];
- d1 = r0*(c1*v[2][2]-s1*v[2][1]);
- v[2][1] = d0; v[2][2] = d1;
- d0 = c1*v[3][1] + s1*v[3][2];
- d1 = r1*(c1*v[3][2]-s1*v[3][1]);
- v[3][1] = d0; v[3][2] = d1;
- xx[0] = r; xx[1] = th;
- ll[0] = r0; ll[1] = th0;
- ur[0] = r1; ur[1] = th1;
- return(rectcell_interp(xx,v,ll,ur,2,nc));
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- void solve(A,b,d) /* this is crude! A organized by column. */
- double *A, *b;
- int d;
- { int i, j, k;
- double piv;
- for (i=0; i<d; i++)
- { piv = A[(d+1)*i];
- for (j=i; j<d; j++) A[j*d+i] /= piv;
- b[i] /= piv;
- for (j=0; j<d; j++) if (j != i)
- { piv = A[i*d+j];
- A[i*d+j] = 0;
- for (k=i+1; k<d; k++)
- A[k*d+j] -= piv*A[k*d+i];
- b[j] -= piv*b[i];
- }
- }
- }
- void triang_guessnv(nvm,ncm,vc,d,mk)
- int *nvm, *ncm, *vc, d, mk;
- { *nvm = *ncm = mk*d;
- *vc = d+1;
- return;
- }
- int triang_split(lf,ce,le)
- lfit *lf;
- double *le;
- int *ce;
- { int d, i, j, k, nts, vc;
- double di, dfx[MXDIM];
- nts = 0; d = lf->fp.d; vc = d+1;
- for (i=0; i<d; i++)
- for (j=i+1; j<=d; j++)
- { for (k=0; k<d; k++)
- dfx[k] = evptx(&lf->fp,ce[i],k)-evptx(&lf->fp,ce[j],k);
- di = rho(dfx,lf->lfd.sca,d,KSPH,NULL);
- le[i*vc+j] = le[j*vc+i] = di/MIN(lf->fp.h[ce[i]],lf->fp.h[ce[j]]);
- nts = nts || le[i*vc+j]>cut(&lf->evs);
- }
- return(nts);
- }
- void resort(pv,xev,dig)
- double *xev;
- int *pv, *dig;
- { double d0, d1, d2;
- int i;
- d0 = d1 = d2 = 0;
- for (i=0; i<3; i++)
- { d0 += (xev[3*pv[11]+i]-xev[3*pv[1]+i])*(xev[3*pv[11]+i]-xev[3*pv[1]+i]);
- d1 += (xev[3*pv[ 7]+i]-xev[3*pv[2]+i])*(xev[3*pv[ 7]+i]-xev[3*pv[2]+i]);
- d2 += (xev[3*pv[ 6]+i]-xev[3*pv[3]+i])*(xev[3*pv[ 6]+i]-xev[3*pv[3]+i]);
- }
- if ((d0<=d1) & (d0<=d2))
- { dig[0] = pv[1]; dig[1] = pv[11];
- dig[2] = pv[2]; dig[3] = pv[7];
- dig[4] = pv[3]; dig[5] = pv[6];
- }
- else if (d1<=d2)
- { dig[0] = pv[2]; dig[1] = pv[7];
- dig[2] = pv[1]; dig[3] = pv[11];
- dig[4] = pv[3]; dig[5] = pv[6];
- }
- else
- { dig[0] = pv[3]; dig[1] = pv[6];
- dig[2] = pv[2]; dig[3] = pv[7];
- dig[4] = pv[1]; dig[5] = pv[11];
- }
- }
- void triang_grow(des,lf,ce,ct,term)
- design *des;
- lfit *lf;
- int *ce, *ct, *term;
- { double le[(1+MXDIM)*(1+MXDIM)], ml;
- int d, i, j, im, jm, vc, pv[(1+MXDIM)*(1+MXDIM)], dig[6];
- int nce[1+MXDIM];
- if (lf_error) return;
- d = lf->fp.d; vc = d+1;
- if (!triang_split(lf,ce,le))
- { if (ct != NULL)
- { for (i=0; i<vc; i++) term[*ct*vc+i] = ce[i];
- (*ct)++;
- }
- return;
- }
- if (d>3)
- { ml = 0;
- for (i=0; i<d; i++)
- for (j=i+1; j<vc; j++)
- if (le[i*vc+j]>ml) { ml = le[i*vc+j]; im = i; jm = j; }
- pv[0] = newsplit(des,lf,(int)ce[im],(int)ce[jm],0);
- for (i=0; i<vc; i++) nce[i] = ce[i];
- nce[im] = pv[0]; triang_grow(des,lf,nce,ct,term); nce[im] = ce[im];
- nce[jm] = pv[0]; triang_grow(des,lf,nce,ct,term);
- return;
- }
- for (i=0; i<d; i++)
- for (j=i+1; j<=d; j++)
- pv[i*vc+j] = pv[j*vc+i]
- = newsplit(des,lf,(int)ce[i],(int)ce[j],le[i*vc+j]<=cut(&lf->evs));
- for (i=0; i<=d; i++) /* corners */
- { for (j=0; j<=d; j++) nce[j] = (j==i) ? ce[i] : pv[i*vc+j];
- triang_grow(des,lf,nce,ct,term);
- }
-
- if (d==2) /* center for d=2 */
- { nce[0] = pv[5]; nce[1] = pv[2]; nce[2] = pv[1];
- triang_grow(des,lf,nce,ct,term);
- }
- if (d==3) /* center for d=3 */
- { resort(pv,evp(&lf->fp),dig);
- nce[0] = dig[0]; nce[1] = dig[1];
- nce[2] = dig[2]; nce[3] = dig[4]; triang_grow(des,lf,nce,ct,term);
- nce[2] = dig[5]; nce[3] = dig[3]; triang_grow(des,lf,nce,ct,term);
- nce[2] = dig[2]; nce[3] = dig[5]; triang_grow(des,lf,nce,ct,term);
- nce[2] = dig[4]; nce[3] = dig[3]; triang_grow(des,lf,nce,ct,term);
- }
- }
- void triang_descend(tr,xa,ce)
- lfit *tr;
- double *xa;
- int *ce;
- { double le[(1+MXDIM)*(1+MXDIM)], ml;
- int d, vc, i, j, im, jm, pv[(1+MXDIM)*(1+MXDIM)];
- design *des;
- des = NULL;
- if (!triang_split(tr,ce,le)) return;
- d = tr->fp.d; vc = d+1;
- if (d>3) /* split longest edge */
- { ml = 0;
- for (i=0; i<d; i++)
- for (j=i+1; j<vc; j++)
- if (le[i*vc+j]>ml) { ml = le[i*vc+j]; im = i; jm = j; }
- pv[0] = newsplit(des,tr,(int)ce[im],(int)ce[jm],0);
- if (xa[im]>xa[jm])
- { xa[im] -= xa[jm]; xa[jm] *= 2; ce[jm] = pv[0]; }
- else
- { xa[jm] -= xa[im]; xa[im] *= 2; ce[im] = pv[0]; }
- triang_descend(tr,xa,ce);
- return;
- }
- for (i=0; i<d; i++)
- for (j=i+1; j<=d; j++)
- pv[i*vc+j] = pv[j*vc+i]
- = newsplit(des,tr,(int)ce[i],(int)ce[j],le[i*d+j]<=cut(&tr->evs));
- for (i=0; i<=d; i++) if (xa[i]>=0.5) /* in corner */
- { for (j=0; j<=d; j++)
- { if (i!=j) ce[j] = pv[i*vc+j];
- xa[j] = 2*xa[j];
- }
- xa[i] -= 1;
- triang_descend(tr,xa,ce);
- return;
- }
- if (d==1) { LERR(("weights sum to < 1")); }
- if (d==2) /* center */
- { ce[0] = pv[5]; xa[0] = 1-2*xa[0];
- ce[1] = pv[2]; xa[1] = 1-2*xa[1];
- ce[2] = pv[1]; xa[2] = 1-2*xa[2];
- triang_descend(tr,xa,ce);
- }
- if (d==3) /* center */
- { double z; int dig[6];
- resort(pv,evp(&tr->fp),dig);
- ce[0] = dig[0]; ce[1] = dig[1];
- xa[0] *= 2; xa[1] *= 2; xa[2] *= 2; xa[3] *= 2;
- if (xa[0]+xa[2]>=1)
- { if (xa[0]+xa[3]>=1)
- { ce[2] = dig[2]; ce[3] = dig[4];
- z = xa[0];
- xa[3] += z-1; xa[2] += z-1; xa[0] = xa[1]; xa[1] = 1-z;
- }
- else
- { ce[2] = dig[2]; ce[3] = dig[5];
- z = xa[3]; xa[3] = xa[1]+xa[2]-1; xa[1] = z;
- z = xa[2]; xa[2] += xa[0]-1; xa[0] = 1-z;
- } }
- else
- { if (xa[1]+xa[2]>=1)
- { ce[2] = dig[5]; ce[3] = dig[3];
- xa[1] = 1-xa[1]; xa[2] -= xa[1]; xa[3] -= xa[1];
- }
- else
- { ce[2] = dig[4]; ce[3] = dig[3];
- z = xa[3]; xa[3] += xa[1]-1; xa[1] = xa[2];
- xa[2] = z+xa[0]-1; xa[0] = 1-z;
- } }
- triang_descend(tr,xa,ce);
- } }
- void covrofdata(lfd,V,mn) /* covar of data; mean in mn */
- lfdata *lfd;
- double *V, *mn;
- { int d, i, j, k;
- double s;
- s = 0; d = lfd->d;
- for (i=0; i<d*d; i++) V[i] = 0;
- for (i=0; i<lfd->n; i++)
- { s += prwt(lfd,i);
- for (j=0; j<d; j++)
- for (k=0; k<d; k++)
- V[j*d+k] += prwt(lfd,i)*(datum(lfd,j,i)-mn[j])*(datum(lfd,k,i)-mn[k]);
- }
- for (i=0; i<d*d; i++) V[i] /= s;
- }
- int intri(x,w,xev,xa,d) /* is x in triangle bounded by xd[0..d-1]? */
- double *x, *xev, *xa;
- int *w, d;
- { int i, j;
- double eps, *r, xd[MXDIM*MXDIM];
- eps = 1.0e-10;
- r = &xev[w[d]*d];
- for (i=0; i<d; i++)
- { xa[i] = x[i]-r[i];
- for (j=0; j<d; j++) xd[i*d+j] = xev[w[i]*d+j]-r[j];
- }
- solve(xd,xa,d);
- xa[d] = 1.0;
- for (i=0; i<d; i++) xa[d] -= xa[i];
- for (i=0; i<=d; i++) if ((xa[i]<-eps) | (xa[i]>1+eps)) return(0);
- return(1);
- }
- void triang_start(des,lf) /* Triangulation with polyhedral start */
- design *des;
- lfit *lf;
- {
- int i, j, k, n, d, nc, nvm, ncm, vc;
- int *ce, ed[1+MXDIM];
- double V[MXDIM*MXDIM], P[MXDIM*MXDIM], sigma, z[MXDIM], xa[1+MXDIM], *xev;
- xev = evp(&lf->fp);
- d = lf->lfd.d; n = lf->lfd.n;
- lf->fp.nv = nc = 0;
- triang_guessnv(&nvm,&ncm,&vc,d,mk(&lf->evs));
- trchck(lf,nvm,ncm,vc);
- ce = lf->evs.ce;
- for (j=0; j<d; j++) xev[j] = lf->pc.xbar[j];
- lf->fp.nv = 1;
- covrofdata(&lf->lfd,V,xev); /* fix this with scaling */
- eig_dec(V,P,d);
- for (i=0; i<d; i++) /* add vertices +- 2sigma*eigenvect */
- { sigma = sqrt(V[i*(d+1)]);
- for (j=0; j<d; j++)
- xev[lf->fp.nv*d+j] = xev[j]-2*sigma*P[j*d+i];
- lf->fp.nv++;
- for (j=0; j<d; j++)
- xev[lf->fp.nv*d+j] = xev[j]+2*sigma*P[j*d+i];
- lf->fp.nv++;
- }
- for (i=0; i<n; i++) /* is point i inside? */
- { ed[0] = 0;
- for (j=0; j<d; j++)
- { z[j] = 0;
- for (k=0; k<d; k++) z[j] += P[k*d+j]*(datum(&lf->lfd,k,i)-xev[k]);
- ed[j+1] = 2*j+1+(z[j]>0);
- for (k=0; k<d; k++) z[j] = datum(&lf->lfd,j,i);
- }
- k = intri(z,ed,xev,xa,d);
- if (xa[0]<0)
- { for (j=1; j<=d; j++)
- for (k=0; k<d; k++)
- xev[ed[j]*d+k] = xa[0]*xev[k]+(1-xa[0])*xev[ed[j]*d+k];
- }
- }
- nc = 1<<d; /* create initial cells */
- for (i=0; i<nc; i++)
- { ce[i*vc] = 0; k = i;
- for (j=0; j<d; j++)
- { ce[i*vc+j+1] = 2*j+(k%2)+1;
- k>>=1;
- }
- }
- for (i=0; i<lf->fp.nv; i++)
- { PROC_VERTEX(des,lf,i);
- if (lf_error) return;
- lf->evs.s[i] = 0;
- }
- for (i=0; i<nc; i++)
- triang_grow(des,lf,&ce[i*vc],NULL,NULL);
- lf->evs.nce = nc;
- }
- double triang_cubicint(v,vv,w,d,nc,xxa)
- double *v, *vv, *xxa;
- int *w, d, nc;
- { double sa, lb, *vert0, *vert1, *vals0, *vals1, deriv0, deriv1;
- int i, j, k;
- if (nc==1) /* linear interpolate */
- { sa = 0;
- for (i=0; i<=d; i++) sa += xxa[i]*vv[i];
- return(sa);
- }
- sa = 1.0;
- for (j=d; j>0; j--) /* eliminate v[w[j]] */
- { lb = xxa[j]/sa;
- for (k=0; k<j; k++) /* Interpolate edge v[w[k]],v[w[j]] */
- { vert0 = &v[w[k]*d];
- vert1 = &v[w[j]*d];
- vals0 = &vv[k*nc];
- vals1 = &vv[j*nc];
- deriv0 = deriv1 = 0;
- for (i=0; i<d; i++)
- { deriv0 += (vert1[i]-vert0[i])*vals0[i+1];
- deriv1 += (vert1[i]-vert0[i])*vals1[i+1];
- }
- vals0[0] = cubic_interp(lb,vals0[0],vals1[0],deriv0,deriv1);
- for (i=1; i<=d; i++)
- vals0[i] = (1-lb)*((1-lb)*vals0[i]+lb*vals1[i]);
- }
- sa -= xxa[j];
- if (sa<=0) j = 0;
- }
- return(vals0[0]);
- }
- double triang_clotoch(xev,vv,ce,p,xxa)
- double *xev, *vv, *xxa;
- int *ce, p;
- { double cfo[3], cfe[3], cg[9], *va, *vb, *vc,
- l0, nm[3], na, nb, nc, *xl, *xr, *xz, d0, d1, lb, dlt, gam;
- int i, w[3], cfl, cfr;
- if (p==1)
- return(xxa[0]*vv[0]+xxa[1]*vv[1]+xxa[2]*vv[2]);
- if (xxa[2]<=MIN(xxa[0],xxa[1]))
- { va = &xev[2*ce[0]]; vb = &xev[2*ce[1]]; vc = &xev[2*ce[2]];
- w[0] = 0; w[1] = 3; w[2] = 6;
- }
- else
- if (xxa[1]<xxa[0])
- { w[0] = 0; w[1] = 6; w[2] = 3;
- va = &xev[2*ce[0]]; vb = &xev[2*ce[2]]; vc = &xev[2*ce[1]];
- lb = xxa[1]; xxa[1] = xxa[2]; xxa[2] = lb;
- }
- else
- { w[0] = 6; w[1] = 3; w[2] = 0;
- va = &xev[2*ce[2]]; vb = &xev[2*ce[1]]; vc = &xev[2*ce[0]];
- lb = xxa[0]; xxa[0] = xxa[2]; xxa[2] = lb;
- }
-
- /* set cg to values and derivatives on standard triangle */
- for (i=0; i<3; i++)
- { cg[3*i] = vv[w[i]];
- cg[3*i+1] = ((vb[0]-va[0])*vv[w[i]+1]
- +(vb[1]-va[1])*vv[w[i]+2])/2; /* df/dx */
- cg[3*i+2] = ((2*vc[0]-vb[0]-va[0])*vv[w[i]+1]
- +(2*vc[1]-vb[1]-va[1])*vv[w[i]+2])/2.0; /* sqrt{3} df/dy */
- }
- dlt = (vb[0]-va[0])*(vc[1]-va[1])-(vc[0]-va[0])*(vb[1]-va[1]);
- /* Twice area; +ve if abc antic.wise -ve is abc c.wise */
- cfo[0] = (cg[0]+cg[3]+cg[6])/3;
- cfo[1] = (2*cg[0]-cg[3]-cg[6])/4;
- cfo[2] = (2*cg[3]-cg[0]-cg[6])/4;
- na = -cg[1]+cg[2]; /* perp. deriv, rel. length 2 */
- nb = -cg[4]-cg[5];
- nc = 2*cg[7];
- cfo[1] += (nb-nc)/16;
- cfo[2] += (nc-na)/16;
- na = -cg[1]-cg[2]/3.0; /* derivatives back to origin */
- nb = cg[4]-cg[5]/3.0;
- nc = cg[8]/1.5;
- cfo[0] -= (na+nb+nc)*7/54;
- cfo[1] += 13*(nb+nc-2*na)/144;
- cfo[2] += 13*(na+nc-2*nb)/144;
- for (i=0; i<3; i++)
- { /* Outward normals by linear interpolation on original triangle.
- Convert to outward normals on standard triangle.
- Actually, computed to opposite corner */
- switch(i)
- { case 0: xl = vc; xr = vb; xz = va; cfl = w[2]; cfr = w[1];
- break;
- case 1: xl = va; xr = vc; xz = vb; cfl = w[0]; cfr = w[2];
- break;
- case 2: xl = vb; xr = va; xz = vc; cfl = w[1]; cfr = w[0];
- break;
- }
- na = xr[0]-xl[0]; nb = xr[1]-xl[1];
- lb = na*na+nb*nb;
- d0 = 1.5*(vv[cfr]-vv[cfl]) - 0.25*(na*(vv[cfl+1]+vv[cfr+1])
- +nb*(vv[cfl+2]+vv[cfr+2]));
- d1 = 0.5*( na*(vv[cfl+2]+vv[cfr+2])-nb*(vv[cfl+1]+vv[cfr+1]) );
- l0 = (xz[0]-xl[0])*na+(xz[1]-xl[1])*nb-lb/2;
- nm[i] = (d1*dlt-l0*d0)/lb;
- }
- cfo[0] -= (nm[0]+nm[1]+nm[2])*4/81;
- cfo[1] += (2*nm[0]-nm[1]-nm[2])/27;
- cfo[2] += (2*nm[1]-nm[0]-nm[2])/27;
- gam = xxa[0]+xxa[1]-2*xxa[2];
- if (gam==0) return(cfo[0]);
- lb = (xxa[0]-xxa[2])/gam;
- d0 = -2*cg[4]; d1 = -2*cg[1];
- cfe[0] = cubic_interp(lb,cg[3],cg[0],d0,d1);
- cfe[1] = cubintd(lb,cg[3],cg[0],d0,d1);
- cfe[2] = -(1-lb)*(1-2*lb)*cg[5] + 4*lb*(1-lb)*nm[2] - lb*(2*lb-1)*cg[2];
- d0 = 2*(lb*cfo[1]+(1-lb)*cfo[2]);
- d1 = (lb-0.5)*cfe[1]+cfe[2]/3.0;
- return(cubic_interp(gam,cfo[0],cfe[0],d0,d1));
- }
- int triang_getvertexvals(fp,evs,vv,i,what)
- fitpt *fp;
- evstruc *evs;
- double *vv;
- int i, what;
- { double dx, P, le, vl[1+MXDIM], vh[1+MXDIM];
- int d, il, ih, j, nc;
- d = fp->d;
- if (evs->s[i]==0) return(exvval(fp,vv,i,d,what,0));
- il = evs->lo[i]; nc = triang_getvertexvals(fp,evs,vl,il,what);
- ih = evs->hi[i]; nc = triang_getvertexvals(fp,evs,vh,ih,what);
- vv[0] = (vl[0]+vh[0])/2;
- if (nc==1) return(nc);
- P = 1.5*(vh[0]-vl[0]);
- le = 0.0;
- for (j=0; j<d; j++)
- { dx = evptx(fp,ih,j)-evptx(fp,il,j);
- vv[0] += dx*(vl[j+1]-vh[j+1])/8;
- vv[j+1] = (vl[j+1]+vh[j+1])/2;
- P -= 1.5*dx*vv[j+1];
- le += dx*dx;
- }
- for (j=0; j<d; j++)
- vv[j+1] += P*(evptx(fp,ih,j)-evptx(fp,il,j))/le;
- return(nc);
- }
- double triang_int(lf,x,what)
- lfit *lf;
- double *x;
- int what;
- {
- int d, i, j, k, vc, nc;
- int *ce, nce[1+MXDIM];
- double xa[1+MXDIM], vv[(1+MXDIM)*(1+MXDIM)], lb;
- fitpt *fp;
- evstruc *evs;
- fp = &lf->fp;
- evs= &lf->evs;
- d = fp->d; vc = d+1;
- ce = evs->ce;
- i = 0;
- while ((i<evs->nce) && (!intri(x,&ce[i*vc],evp(fp),xa,d))) i++;
- if (i==evs->nce) return(NOSLN);
- i *= vc;
- for (j=0; j<vc; j++) nce[j] = ce[i+j];
- triang_descend(lf,xa,nce);
- /* order the vertices -- needed for asymmetric interptr */
- do
- { k=0;
- for (i=0; i<d; i++)
- if (nce[i]>nce[i+1])
- { j=nce[i]; nce[i]=nce[i+1]; nce[i+1]=j; k=1;
- lb = xa[i]; xa[i] = xa[i+1]; xa[i+1] = lb;
- }
- } while(k);
- nc = 0;
- for (i=0; i<vc; i++)
- nc = triang_getvertexvals(fp,evs,&vv[i*nc],nce[i],what);
- return((d==2) ? triang_clotoch(evp(fp),vv,nce,nc,xa) :
- triang_cubicint(evp(fp),vv,nce,d,nc,xa));
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * Functions for computing residuals and fitted values from
- * the locfit object.
- *
- * fitted(lf,fit,what,cv,ty) computes fitted values from the
- * fit structure in lf.
- * resid(y,c,w,th,mi,ty) converts fitted values to residuals
- */
- #include "lfev.h"
- #define NRT 8
- static char *rtype[NRT] = { "deviance", "d2", "pearson", "raw",
- "ldot", "lddot", "fit", "mean" };
- static int rvals[NRT] = { RDEV, RDEV2, RPEAR, RRAW, RLDOT, RLDDT, RFIT, RMEAN};
- int restyp(z)
- char *z;
- { int val;
- val = pmatch(z, rtype, rvals, NRT, -1);
- if (val==-1) LERR(("Unknown type = %s",z));
- return(val);
- }
- double resid(y,w,th,fam,ty,res)
- int fam, ty;
- double y, w, th, *res;
- { double raw;
- fam = fam & 63;
- if ((fam==TGAUS) | (fam==TROBT) | (fam==TCAUC))
- raw = y-res[ZMEAN];
- else
- raw = y-w*res[ZMEAN];
- switch(ty)
- { case RDEV:
- if (res[ZDLL]>0) return(sqrt(-2*res[ZLIK]));
- else return(-sqrt(-2*res[ZLIK]));
- case RPEAR:
- if (res[ZDDLL]<=0)
- { if (res[ZDLL]==0) return(0);
- return(NOSLN);
- }
- return(res[ZDLL]/sqrt(res[ZDDLL]));
- case RRAW: return(raw);
- case RLDOT: return(res[ZDLL]);
- case RDEV2: return(-2*res[ZLIK]);
- case RLDDT: return(res[ZDDLL]);
- case RFIT: return(th);
- case RMEAN: return(res[ZMEAN]);
- default: LERR(("resid: unknown residual type %d",ty));
- }
- return(0.0);
- }
- double studentize(res,inl,var,ty,link)
- double res, inl, var, *link;
- int ty;
- { double den;
- inl *= link[ZDDLL];
- var = var*var*link[ZDDLL];
- if (inl>1) inl = 1;
- if (var>inl) var = inl;
- den = 1-2*inl+var;
- if (den<0) return(0.0);
- switch(ty)
- { case RDEV:
- case RPEAR:
- case RRAW:
- case RLDOT:
- return(res/sqrt(den));
- case RDEV2:
- return(res/den);
- default: return(res);
- }
- }
- void fitted(lf,fit,what,cv,st,ty)
- lfit *lf;
- double *fit;
- int what, cv, st, ty;
- { int i, j, d, n, evo;
- double xx[MXDIM], th, inl, var, link[LLEN];
- n = lf->lfd.n;
- d = lf->lfd.d;
- evo = ev(&lf->evs);
- cv &= (evo!=ECROS);
- if ((evo==EDATA)|(evo==ECROS)) evo = EFITP;
- setfamily(&lf->sp);
- for (i=0; i<n; i++)
- { for (j=0; j<d; j++) xx[j] = datum(&lf->lfd,j,i);
- th = dointpoint(lf,xx,what,evo,i);
- if ((what==PT0)|(what==PVARI)) th = th*th;
- if (what==PCOEF)
- {
- th += base(&lf->lfd,i);
- stdlinks(link,&lf->lfd,&lf->sp,i,th,rsc(&lf->fp));
- if ((cv)|(st))
- { inl = dointpoint(lf,xx,PT0,evo,i);
- inl = inl*inl;
- if (cv)
- { th -= inl*link[ZDLL];
- stdlinks(link,&lf->lfd,&lf->sp,i,th,rsc(&lf->fp));
- }
- if (st) var = dointpoint(lf,xx,PNLX,evo,i);
- }
- fit[i] = resid(resp(&lf->lfd,i),prwt(&lf->lfd,i),th,fam(&lf->sp),ty,link);
- if (st) fit[i] = studentize(fit[i],inl,var,ty,link);
- } else fit[i] = th;
- if (lf_error) return;
- }
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- extern double robscale;
- /* special version of ressumm to estimate sigma^2, with derivative estimation */
- void ressummd(lf)
- lfit *lf;
- { int i;
- double s0, s1;
- s0 = s1 = 0.0;
- if ((fam(&lf->sp)&64)==0)
- { rv(&lf->fp) = 1.0;
- return;
- }
- for (i=0; i<lf->fp.nv; i++)
- { s0 += lf->fp.lik[2*lf->fp.nvm+i];
- s1 += lf->fp.lik[i];
- }
- if (s0==0.0)
- rv(&lf->fp) = 0.0;
- else
- rv(&lf->fp) = -2*s1/s0;
- }
- /*
- * res[0] = log-likelihood.
- * res[1] = df0 = tr(H)
- * res[2] = df0 = tr(H'H)
- * res[3] = s^2.
- * res[5] = robustscale.
- */
- void ressumm(lf,des,res)
- lfit *lf;
- design *des;
- double *res;
- { int i, j, evo, tg;
- double *oy, pw, r1, r2, rdf, t0, t1, u[MXDIM], link[LLEN];
- fitpt *fp;
- res[0] = res[1] = res[2] = 0.0;
- evo = ev(&lf->evs);
- if ((evo==EKDCE) | (evo==EPRES))
- { res[3] = 1.0;
- return;
- }
- if (lf->dv.nd>0)
- { ressummd(lf);
- return;
- }
- r1 = r2 = 0.0;
- if ((evo==EDATA) | (evo==ECROS)) evo = EFITP;
- for (i=0; i<lf->lfd.n; i++)
- { for (j=0; j<lf->lfd.d; j++) u[j] = datum(&lf->lfd,j,i);
- fitv(des,i) = base(&lf->lfd,i)+dointpoint(lf,u,PCOEF,evo,i);
- des->wd[i] = resp(&(lf->lfd),i) - fitv(des,i);
- wght(des,i) = 1.0;
- des->ind[i] = i;
- }
- tg = fam(&lf->sp);
- res[5] = 1.0;
- if ((tg==TROBT+64) | (tg==TCAUC+64)) /* global robust scale */
- { oy = lf->lfd.y; lf->lfd.y = des->wd;
- des->xev = lf->pc.xbar;
- locfit(&lf->lfd,des,&lf->sp,1,0,0);
- lf->lfd.y = oy;
- res[5] = robscale;
- }
- for (i=0; i<lf->lfd.n; i++)
- { for (j=0; j<lf->lfd.d; j++) u[j] = datum(&lf->lfd,j,i);
- t0 = dointpoint(lf,u,PT0,evo,i);
- t1 = dointpoint(lf,u,PNLX,evo,i);
- stdlinks(link,&lf->lfd,&lf->sp,i,fitv(des,i),res[5]);
- t1 = t1*t1*link[ZDDLL];
- t0 = t0*t0*link[ZDDLL];
- if (t1>1) t1 = 1;
- if (t0>1) t0 = 1; /* no observation gives >1 deg.free */
- res[0] += link[ZLIK];
- res[1] += t0;
- res[2] += t1;
- pw = prwt(&lf->lfd,i);
- if (pw>0)
- { r1 += link[ZDLL]*link[ZDLL]/pw;
- r2 += link[ZDDLL]/pw;
- }
- }
- res[3] = 1.0;
- if ((fam(&lf->sp)&64)==64) /* quasi family */
- { rdf = lf->lfd.n-2*res[1]+res[2];
- if (rdf<1.0)
- { WARN(("Estimated rdf < 1.0; not estimating variance"));
- }
- else
- res[3] = r1/r2 * lf->lfd.n / rdf;
- }
- /* try to ensure consistency for family="circ"! */
- if (((fam(&lf->sp)&63)==TCIRC) & (lf->lfd.d==1))
- { int *ind, nv;
- double dlt, th0, th1;
- ind = des->ind;
- nv = fp->nv;
- for (i=0; i<nv; i++) ind[i] = i;
- lforder(ind,evp(fp),0,nv-1);
- for (i=1; i<nv; i++)
- { dlt = evptx(fp,ind[i],0)-evptx(fp,ind[i-1],0);
- th0 = fp->coef[ind[i]]-dlt*fp->coef[ind[i]+nv]-fp->coef[ind[i-1]];
- th1 = fp->coef[ind[i]]-dlt*fp->coef[ind[i-1]+nv]-fp->coef[ind[i-1]];
- if ((th0>PI)&(th1>PI))
- { for (j=0; j<i; j++)
- fp->coef[ind[j]] += 2*PI;
- i--;
- }
- if ((th0<(-PI))&(th1<(-PI)))
- { for (j=0; j<i; j++)
- fp->coef[ind[j]] -= 2*PI;
- i--;
- }
- }
- }
- }
- double rss(lf,des,df)
- lfit *lf;
- design *des;
- double *df;
- { double ss, res[10];
- ss = 0;
- ressumm(lf,des,res);
- *df = lf->lfd.n - 2*res[1] + res[2];
- return(-2*res[0]);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- *
- * Derivative corrections. The local slopes are not the derivatives
- * of the local likelihood estimate; the function dercor() computes
- * the adjustment to get the correct derivatives under the assumption
- * that h is constant.
- *
- * By differentiating the local likelihood equations, one obtains
- *
- * d ^ ^ T -1 T d . ^
- * -- a = a - (X W V X) X -- W l( Y, X a)
- * dx 0 1 dx
- */
- #include "lfev.h"
- extern double robscale;
- void dercor(lfd,sp,des,coef)
- lfdata *lfd;
- smpar *sp;
- design *des;
- double *coef;
- { double s1, dc[MXDIM], wd, link[LLEN];
- int i, ii, j, m, d, p;
- if (fam(sp)<=THAZ) return;
- if (ker(sp)==WPARM) return;
- d = lfd->d;
- p = des->p; m = des->n;
- if (lf_debug>1) mut_printf(" Correcting derivatives\n");
- fitfun(lfd, sp, des->xev,des->xev,des->f1,NULL);
- jacob_solve(&des->xtwx,des->f1);
- setzero(dc,d);
- /* correction term is e1^T (XTWVX)^{-1} XTW' ldot. */
- for (i=0; i<m; i++)
- { s1 = innerprod(des->f1,d_xi(des,i),p);
- ii = des->ind[i];
- stdlinks(link,lfd,sp,ii,fitv(des,ii),robscale);
- for (j=0; j<d; j++)
- { wd = wght(des,ii)*weightd(datum(lfd,j,ii)-des->xev[j],lfd->sca[j],
- d,ker(sp),kt(sp),des->h,lfd->sty[j],dist(des,ii));
- dc[j] += s1*wd*link[ZDLL];
- }
- }
- for (j=0; j<d; j++) coef[j+1] += dc[j];
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- void allocallcf(lf)
- lfit *lf;
- { lf->fp.coef = VVEC(lf,0);
- lf->fp.h = VVEC(lf,NPAR(lf));
- }
- int procvallcf(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { int i, p, lf_status;
- lf_status = procv_nov(des,lf,v);
- if (lf_error) return(lf_status);
- p = NPAR(lf);
- for (i=0; i<p; i++) VVAL(lf,v,i) = des->cf[i];
- lf->fp.h[v] = des->h;
- return(0);
- }
- void initallcf(lf)
- lfit *lf;
- { PROCV(lf) = procvallcf;
- ALLOC(lf) = allocallcf;
- PPROC(lf) = NULL;
- KEEPV(lf) = NPAR(lf)+1;
- KEEPC(lf) = 0;
- NOPC(lf) = 1;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- void pprocgam(lf,des,res)
- lfit *lf;
- design *des;
- double *res;
- { int i, j, n, evo, op;
- double *fv, *vr, df, t0, t1, u[MXDIM], link[LLEN];
- n = lf->lfd.n;
- fv = res;
- vr = &res[n];
- df = 0.0;
- evo = ev(&lf->evs);
- if (evo==EDATA) evo = EFITP;
-
- for (i=0; i<n; i++)
- { for (j=0; j<lf->lfd.d; j++) u[j] = datum(&lf->lfd,j,i);
- fitv(des,i) = base(&lf->lfd,i)+dointpoint(lf,u,PCOEF,evo,i);
- lf->lfd.y[i] -= fitv(des,i);
- wght(des,i) = 1.0;
- des->ind[i] = i;
- t0 = dointpoint(lf,u,PT0,evo,i);
- t1 = dointpoint(lf,u,PNLX,evo,i);
- stdlinks(link,&lf->lfd,&lf->sp,i,fitv(des,i),1.0);
- t0 = t0*t0*link[ZDDLL];
- t1 = t1*t1*link[ZDDLL];
- if (t0>1) t0 = 1; /* no observation gives >1 deg.free */
- if (t1>1) t1 = 1; /* no observation gives >1 deg.free */
- vr[i] = t1;
- df += t0;
- }
- des->n = n;
- deg(&lf->sp) = 1;
- op = npar(&lf->sp);
- npar(&lf->sp) = des->p = 1+lf->lfd.d;
- des->xev = lf->pc.xbar;
- locfit(&lf->lfd,des,&lf->sp,1,0,0);
- for (i=0; i<n; i++) fv[i] = resp(&lf->lfd,i) - fitv(des,i);
- for (i=0; i<=lf->lfd.d; i++)
- lf->pc.coef[i] += des->cf[i];
- res[2*n] = df-2;
- npar(&lf->sp) = op;
- }
- void initgam(lf)
- lfit *lf;
- { initstd(lf);
- PPROC(lf) = pprocgam;
- KEEPC(lf) = 2*NOBS(lf)+1;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- int procvhatm(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { int k;
- double *l;
- l = &lf->fp.coef[v*lf->lfd.n];
- if ((ker(&lf->sp)!=WPARM) | (!haspc(&lf->pc)))
- { k = procv_nov(des,lf,v);
- wdiag(&lf->lfd,&lf->sp,des,l,&lf->dv,0,1,1);
- }
- else
- wdiagp(&lf->lfd,&lf->sp,des,l,&lf->pc,&lf->dv,0,1,1);
- lf->fp.h[v] = des->h;
- return(k);
- }
- void allochatm(lf)
- lfit *lf;
- { lf->fp.coef = VVEC(lf,0);
- lf->fp.h = VVEC(lf,NOBS(lf));
- }
- void pprochatm(lf,des,res)
- lfit *lf;
- design *des;
- double *res;
- { transpose(lf->fp.coef,lf->fp.nvm,lf->lfd.n);
- }
- void inithatm(lf)
- lfit *lf;
- { PROCV(lf) = procvhatm;
- ALLOC(lf) = allochatm;
- PPROC(lf) = pprochatm;
- KEEPV(lf) = NOBS(lf)+1;
- KEEPC(lf) = 1;
- NOPC(lf) = 1; /* could use pc if mi[MKER] == WPARM */
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- static lfit *lf_scb;
- static lfdata *lfd_scb;
- static smpar *scb_sp;
- static design *des_scb;
- int scbfitter(x,l,reqd)
- double *x, *l;
- int reqd;
- {
- int m;
- des_scb->xev = x;
- if ((ker(scb_sp)!=WPARM) | (!haspc(&lf_scb->pc)))
- { locfit(lfd_scb,des_scb,&lf_scb->sp,1,1,0);
- m = wdiag(lfd_scb, scb_sp, des_scb,l,&lf_scb->dv,reqd,2,0);
- }
- else
- m = wdiagp(lfd_scb, scb_sp, des_scb,l,&lf_scb->pc,&lf_scb->dv,reqd,2,0);
- return(m);
- }
- int constants(lf,des,res)
- lfit *lf;
- design *des;
- double *res;
- {
- int d, m, nt;
- double *wk;
- evstruc *evs;
- lf_scb = lf;
- des_scb = des;
- lfd_scb = &lf->lfd;
- scb_sp = &lf->sp;
- evs = &lf->evs;
- d = lfd_scb->d;
- m = lfd_scb->n;
- trchck(lf,0,0,0);
- if (lf_error) return(0);
- if ((ker(scb_sp) != WPARM) && (lf->sp.nn>0))
- WARN(("constants are approximate for varying h"));
- npar(scb_sp) = calcp(scb_sp,lf->lfd.d);
- des_init(des,m,npar(scb_sp));
- set_scales(&lf->lfd);
- set_flim(&lf->lfd,&lf->evs);
- compparcomp(des,&lf->lfd,&lf->sp,&lf->pc,ker(scb_sp)!=WPARM);
-
- wk = &res[d+1];
- nt = tube_constants(scbfitter,d,m,ev(evs),mg(evs),evs->fl,
- res,wk,(d>3) ? 4 : d+1,0);
- lf->evs.nce = nt; /* cheat way to return it to S. */
- return(nt);
- }
- void initkappa(lf)
- lfit *lf;
- { PROCV(lf) = NULL;
- ALLOC(lf) = NULL;
- PPROC(lf) = (void *)constants;
- KEEPV(lf) = 0;
- KEEPC(lf) = NVAR(lf)+1+k0_reqd(NVAR(lf),NOBS(lf),0);
- NOPC(lf) = 0;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- /* fix df computation for link=IDENT. */
- void pproclscv(lf,des,res)
- lfit *lf;
- design *des;
- double *res;
- { double df, fh, fh_cv, infl, z0, z1, x[MXDIM];
- int i, n, j, evo;
- z1 = df = 0.0;
- evo = ev(&lf->evs);
- n = lf->lfd.n;
- if ((evo==EDATA) | (evo==ECROS)) evo = EFITP;
- z0 = dens_integrate(lf,des,2);
- for (i=0; i<n; i++)
- { for (j=0; j<lf->lfd.d; j++) x[j] = datum(&lf->lfd,j,i);
- fh = base(&lf->lfd,i)+dointpoint(lf,x,PCOEF,evo,i);
- if (link(&lf->sp)==LLOG) fh = exp(fh);
- infl = dointpoint(lf,x,PT0,evo,i);
- infl = infl * infl;
- if (infl>1) infl = 1;
- fh_cv = (link(&lf->sp) == LIDENT) ?
- (n*fh - infl) / (n-1.0) : fh*(1-infl)*n/(n-1.0);
- z1 += fh_cv;
- df += infl;
- }
- res[0] = z0-2*z1/n;
- res[1] = df;
- }
- void initlscv(lf)
- lfit *lf;
- { initstd(lf);
- KEEPC(lf) = 2;
- PPROC(lf) = pproclscv;
- NOPC(lf) = 1;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- static double pen, sig2;
- void goldensec(f,des,tr,eps,xm,ym,meth)
- double (*f)(), eps, *xm, *ym;
- int meth;
- design *des;
- lfit *tr;
- { double x[4], y[4], xx[11], yy[11];
- int i, im;
- xx[0] = tr->sp.fixh;
- if (xx[0]<=0)
- { LERR(("regband: initialize h>0"));
- return;
- }
- for (i=0; i<=10; i++)
- { if (i>0) xx[i] = (1+gold_rat)*xx[i-1];
- yy[i] = f(xx[i],des,tr,meth);
- if ((i==0) || (yy[i]<yy[im])) im = i;
- }
- if (im==0) im = 1;
- if (im==10)im = 9;
- x[0] = xx[im-1]; y[0] = yy[im-1];
- x[1] = xx[im]; y[1] = yy[im];
- x[3] = xx[im+1]; y[3] = yy[im+1];
- x[2] = gold_rat*x[3]+(1-gold_rat)*x[0];
- y[2] = f(x[2],des,tr,meth);
- while (x[3]-x[0]>eps)
- { if (y[1]<y[2])
- { x[3] = x[2]; y[3] = y[2];
- x[2] = x[1]; y[2] = y[1];
- x[1] = gold_rat*x[0]+(1-gold_rat)*x[3];
- y[1] = f(x[1],des,tr,meth);
- }
- else
- { x[0] = x[1]; y[0] = y[1];
- x[1] = x[2]; y[1] = y[2];
- x[2] = gold_rat*x[3]+(1-gold_rat)*x[0];
- y[2] = f(x[2],des,tr,meth);
- }
- }
- im = 0;
- for (i=1; i<4; i++) if (y[i]<y[im]) im = i;
- *xm = x[im]; *ym = y[im];
- }
- double dnk(x,k)
- double x;
- int k;
- { double f;
- switch(k)
- { case 0: f = 1; break;
- case 1: f = -x; break;
- case 2: f = x*x-1; break;
- case 3: f = x*(x*x-3); break;
- case 4: f = 3-x*x*(6-x*x); break;
- case 5: f = -x*(15-x*x*(10-x*x)); break;
- case 6: f = -15+x*x*(45-x*x*(15-x*x)); break;
- default: LERR(("dnk: k=%d too large",k)); return(0.0);
- }
- return(f*exp(-x*x/2)/S2PI);
- }
- double locai(h,des,lf)
- double h;
- design *des;
- lfit *lf;
- { double cp, res[10];
- nn(&lf->sp) = h;
- lf->mdl.procv = procvstd;
- nstartlf(des,lf);
- ressumm(lf,des,res);
- cp = -2*res[0] + pen*res[1];
- return(cp);
- }
- static int fc;
- double loccp(h,des,lf,m) /* m=1: cp m=2: gcv */
- double h;
- design *des;
- lfit *lf;
- int m;
- { double cp, res[10];
- int dg, n;
- n = lf->lfd.n;
- nn(&lf->sp) = 0;
- fixh(&lf->sp) = h;
- lf->mdl.procv = procvstd;
- nstartlf(des,lf);
- ressumm(lf,des,res);
- if (m==1)
- { if (fc) sig2 = res[3]; /* first call - set sig2 */
- cp = -2*res[0]/sig2 - n + 2*res[1];
- }
- else
- cp = -2*n*res[0]/((n-res[1])*(n-res[1]));
- fc = 0;
- return(cp);
- }
- double cp(des,lf,meth)
- design *des;
- lfit *lf;
- int meth;
- { double hm, ym;
- fc = 1;
- goldensec(loccp,des,lf,0.001,&hm,&ym,meth);
- return(hm);
- }
- double gkk(des,lf)
- design *des;
- lfit *lf;
- { double h, h5, nf, th;
- int i, j, n, dg0, dg1;
- ev(&lf->evs)= EDATA;
- nn(&lf->sp) = 0;
- n = lf->lfd.n;
- dg0 = deg0(&lf->sp); /* target degree */
- dg1 = dg0+1+(dg0%2==0); /* pilot degree */
- nf = exp(log(1.0*n)/10); /* bandwidth inflation factor */
- h = lf->sp.fixh; /* start bandwidth */
- for (i=0; i<=10; i++)
- { deg(&lf->sp) = dg1;
- lf->sp.fixh = h*nf;
- lf->mdl.procv = procvstd;
- nstartlf(des,lf);
- th = 0;
- for (j=10; j<n-10; j++)
- th += lf->fp.coef[dg1*n+j]*lf->fp.coef[dg1*n+j];
- th *= n/(n-20.0);
- h5 = sig2 * Wikk(ker(&lf->sp),dg0) / th;
- h = exp(log(h5)/(2*dg1+1));
- if (lf_error) return(0.0);
- /* mut_printf("pilot %8.5f sel %8.5f\n",lf->sp.fixh,h); */
- }
- return(h);
- }
- double rsw(des,lf)
- design *des;
- lfit *lf;
- { int i, j, k, nmax, nvm, n, mk, evo, dg0, dg1;
- double rss[6], cp[6], th22, dx, d2, hh;
- nmax = 5;
- evo = ev(&lf->evs); ev(&lf->evs) = EGRID;
- mk = ker(&lf->sp); ker(&lf->sp) = WRECT;
- dg0 = deg0(&lf->sp);
- dg1 = 1 + dg0 + (dg0%2==0);
- deg(&lf->sp) = 4;
- for (k=nmax; k>0; k--)
- { lf->evs.mg[0] = k;
- lf->evs.fl[0] = 1.0/(2*k);
- lf->evs.fl[1] = 1-1.0/(2*k);
- nn(&lf->sp) = 0;
- fixh(&lf->sp) = 1.0/(2*k);
- lf->mdl.procv = procvstd;
- nstartlf(des,lf);
- nvm = lf->fp.nvm;
- rss[k] = 0;
- for (i=0; i<k; i++) rss[k] += -2*lf->fp.lik[i];
- }
- n = lf->lfd.n; k = 1;
- for (i=1; i<=nmax; i++)
- { /* cp[i] = (n-5*nmax)*rss[i]/rss[nmax]-(n-10*i); */
- cp[i] = rss[i]/sig2-(n-10*i);
- if (cp[i]<cp[k]) k = i;
- }
- lf->evs.mg[0] = k;
- lf->evs.fl[0] = 1.0/(2*k);
- lf->evs.fl[1] = 1-1.0/(2*k);
- nn(&lf->sp) = 0;
- fixh(&lf->sp) = 1.0/(2*k);
- lf->mdl.procv = procvstd;
- nstartlf(des,lf);
- ker(&lf->sp) = mk; ev(&lf->evs) = evo;
- nvm = lf->fp.nvm;
- th22 = 0;
- for (i=10; i<n-10; i++)
- { j = floor(k*datum(&lf->lfd,0,i));
- if (j>=k) j = k-1;
- dx = datum(&lf->lfd,0,i)-evptx(&lf->fp,0,j);
- if (dg1==2)
- d2 = lf->fp.coef[2*nvm+j]+dx*lf->fp.coef[3*nvm+j]+dx*dx*lf->fp.coef[4*nvm+j]/2;
- else d2 = lf->fp.coef[4*nvm+j];
- th22 += d2*d2;
- }
- hh = Wikk(mk,dg0)*sig2/th22*(n-20.0)/n;
- return(exp(log(hh)/(2*dg1+1)));
- }
- #define MAXMETH 10
- void rband(lf,des,hhat)
- lfit *lf;
- design *des;
- double *hhat;
- { int i, dg, nmeth, meth[MAXMETH];
- double h0, res[10];
- nmeth = lf->dv.nd;
- for (i=0; i<nmeth; i++) meth[i] = lf->dv.deriv[i];
- lf->dv.nd = 0;
- /* first, estimate sigma^2.
- * this is ridiculously bad. lf->sp.fixh = 0.05????
- */
- /* dg = deg(&lf->sp); deg(&lf->sp) = 2;
- h0 = lf->sp.fixh; lf->sp.fixh = 0.05;
- lf->mdl.procv = procvstd;
- nstartlf(des,lf);
- ressumm(lf,des,res);
- deg(&lf->sp) = dg; lf->sp.fixh = h0;
- sig2 = res[3]; */
- for (i=0; i<nmeth; i++)
- {
- switch(meth[i])
- { case 0: hhat[i] = cp(des,lf,1);
- break;
- case 1: hhat[i] = cp(des,lf,2);
- break;
- case 2: hhat[i] = gkk(des,lf);
- break;
- case 3: hhat[i] = rsw(des,lf);
- break;
- default: hhat[i] = 0;
- mut_printf("Unknown method %d\n",meth[i]);
- }
- if (lf_error) i = nmeth;
- }
- lf->dv.nd = nmeth;
- }
- void initrband(lf)
- lfit *lf;
- {
- initstd(lf);
- KEEPC(lf) = MAXMETH;
- PROCV(lf) = NULL;
- PPROC(lf) = rband;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- static double scb_crit, *x, c[10], kap[5], kaq[5], max_p2;
- static int side, type;
- design *scb_des;
- double covar_par(lf,des,x1,x2)
- lfit *lf;
- design *des;
- double x1, x2;
- { double *v1, *v2, *wk;
- paramcomp *pc;
- int i, j, p, ispar;
- v1 = des->f1; v2 = des->ss; wk = des->oc;
- ispar = (ker(&lf->sp)==WPARM) && (haspc(&lf->pc));
- p = npar(&lf->sp);
- /* for parametric models, the covariance is
- * A(x1)^T (X^T W V X)^{-1} A(x2)
- * which we can find easily from the parametric component.
- */
- if (ispar)
- { pc = &lf->pc;
- fitfun(&lf->lfd, &lf->sp, &x1,pc->xbar,v1,NULL);
- fitfun(&lf->lfd, &lf->sp, &x2,pc->xbar,v2,NULL);
- jacob_hsolve(&lf->pc.xtwx,v1);
- jacob_hsolve(&lf->pc.xtwx,v2);
- }
- /* for non-parametric models, we must use the cholseky decomposition
- * of M2 = X^T W^2 V X. Courtesy of lf_vcov caclulations, should have
- * des->P = M2^{1/2} M1^{-1}.
- */
- if (!ispar)
- { fitfun(&lf->lfd, &lf->sp, &x1,des->xev,wk,NULL);
- for (i=0; i<p; i++)
- { v1[i] = 0;
- for (j=0; j<p; j++) v1[i] += des->P[i*p+j]*wk[j];
- }
- fitfun(&lf->lfd, &lf->sp, &x2,des->xev,wk,NULL);
- for (i=0; i<p; i++)
- { v2[i] = 0;
- for (j=0; j<p; j++) v2[i] += des->P[i*p+j]*wk[j];
- }
- }
- return(innerprod(v1,v2,p));
- }
- void cumulant(lf,des,sd)
- lfit *lf;
- design *des;
- double sd;
- { double b2i, b3i, b3j, b4i;
- double ss, si, sj, uii, uij, ujj, k1;
- int ii, i, j, jj;
- for (i=1; i<10; i++) c[i] = 0.0;
- k1 = 0;
- /* ss = sd*sd; */
- ss = covar_par(lf,des,des->xev[0],des->xev[0]);
- /*
- * this isn't valid for nonparametric models. At a minimum,
- * the sums would have to include weights. Still have to work
- * out the right way.
- */
- for (i=0; i<lf->lfd.n; i++)
- { ii = des->ind[i];
- b2i = b2(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,ii));
- b3i = b3(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,ii));
- b4i = b4(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,ii));
- si = covar_par(lf,des,des->xev[0],datum(&lf->lfd,0,ii));
- uii= covar_par(lf,des,datum(&lf->lfd,0,ii),datum(&lf->lfd,0,ii));
- if (lf_error) return;
- c[2] += b4i*si*si*uii;
- c[6] += b4i*si*si*si*si;
- c[7] += b3i*si*uii;
- c[8] += b3i*si*si*si;
- /* c[9] += b2i*si*si*si*si;
- c[9] += b2i*b2i*si*si*si*si; */
- k1 += b3i*si*(si*si/ss-uii);
- /* i=j components */
- c[1] += b3i*b3i*si*si*uii*uii;
- c[3] += b3i*b3i*si*si*si*si*uii;
- c[4] += b3i*b3i*si*si*uii*uii;
- for (j=i+1; j<lf->lfd.n; j++)
- { jj = des->ind[j];
- b3j = b3(fitv(des,ii),fam(&lf->sp),prwt(&lf->lfd,jj));
- sj = covar_par(lf,des,des->xev[0],datum(&lf->lfd,0,jj));
- uij= covar_par(lf,des,datum(&lf->lfd,0,ii),datum(&lf->lfd,0,jj));
- ujj= covar_par(lf,des,datum(&lf->lfd,0,jj),datum(&lf->lfd,0,jj));
- c[1] += 2*b3i*b3j*si*sj*uij*uij;
- c[3] += 2*b3i*b3j*si*si*sj*sj*uij;
- c[4] += b3i*b3j*uij*(si*si*ujj+sj*sj*uii);
- if (lf_error) return;
- }
- }
- c[5] = c[1];
- c[7] = c[7]*c[8];
- c[8] = c[8]*c[8];
- c[1] /= ss; c[2] /= ss; c[3] /= ss*ss; c[4] /= ss;
- c[5] /= ss; c[6] /= ss*ss; c[7] /= ss*ss;
- c[8] /= ss*ss*ss; c[9] /= ss*ss;
- /* constants used in p(x,z) computation */
- kap[1] = k1/(2*sqrt(ss));
- kap[2] = 1 + 0.5*(c[1]-c[2]+c[4]-c[7]) - 3*c[3] + c[6] + 1.75*c[8];
- kap[4] = -9*c[3] + 3*c[6] + 6*c[8] + 3*c[9];
- /* constants used in q(x,u) computation */
- kaq[2] = c[3] - 1.5*c[8] - c[5] - c[4] + 0.5*c[7] + c[6] - c[2];
- kaq[4] = -3*c[3] - 6*c[4] - 6*c[5] + 3*c[6] + 3*c[7] - 3*c[8] + 3*c[9];
- }
- /* q2(u) := u+q2(x,u) in paper */
- double q2(u)
- double u;
- { return(u-u*(36.0*kaq[2] + 3*kaq[4]*(u*u-3) + c[8]*((u*u-10)*u*u+15))/72.0);
- }
- /* p2(u) := p2(x,u) in paper */
- double p2(u)
- double u;
- { return( -u*( 36*(kap[2]-1+kap[1]*kap[1])
- + 3*(kap[4]+4*kap[1]*sqrt(kap[3]))*(u*u-3)
- + c[8]*((u*u-10)*u*u+15) ) / 72 );
- }
- extern int likereg();
- double gldn_like(a)
- double a;
- { int err;
- scb_des->fix[0] = 1;
- scb_des->cf[0] = a;
- max_nr(likereg, scb_des->cf, scb_des->oc, scb_des->res, scb_des->f1,
- &scb_des->xtwx, scb_des->p, lf_maxit, 1.0e-6, &err);
- scb_des->fix[0] = 0;
- return(scb_des->llk);
- }
- /* v1/v2 is correct for deg=0 only */
- void get_gldn(fp,des,lo,hi,v)
- fitpt *fp;
- design *des;
- double *lo, *hi;
- int v;
- { double v1, v2, c, tlk;
- int err;
- v1 = fp->nlx[v];
- v2 = fp->t0[v];
- c = scb_crit * v1 / v2;
- tlk = des->llk - c*c/2;
- mut_printf("v %8.5f %8.5f c %8.5f tlk %8.5f llk %8.5f\n",v1,v2,c,tlk,des->llk);
- /* want: { a : l(a) >= l(a-hat) - c*c/2 } */
- lo[v] = fp->coef[v] - scb_crit*v1;
- hi[v] = fp->coef[v] + scb_crit*v1;
- err = 0;
- mut_printf("lo %2d\n",v);
- lo[v] = solve_secant(gldn_like,tlk,lo[v],fp->coef[v],1e-8,BDF_EXPLEFT,&err);
- if (err>0) mut_printf("solve_secant error\n");
- mut_printf("hi %2d\n",v);
- hi[v] = solve_secant(gldn_like,tlk,fp->coef[v],hi[v],1e-8,BDF_EXPRIGHT,&err);
- if (err>0) mut_printf("solve_secant error\n");
- }
- int procvscb2(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { double thhat, sd, *lo, *hi, u;
- int err, st, tmp;
- x = des->xev = evpt(&lf->fp,v);
- tmp = haspc(&lf->pc);
- /* if ((ker(&lf->sp)==WPARM) && (haspc(&lf->pc)))
- { lf->coef[v] = thhat = addparcomp(lf,des->xev,PCOEF);
- lf->nlx[v] = lf->t0[v] = sd = addparcomp(lf,des->xev,PNLX);
- }
- else */
- { haspc(&lf->pc) = 0;
- st = procvstd(des,lf,v);
- thhat = lf->fp.coef[v];
- sd = lf->fp.nlx[v];
- }
- if ((type==GLM2) | (type==GLM3) | (type==GLM4))
- { if (ker(&lf->sp) != WPARM)
- WARN(("nonparametric fit; correction is invalid"));
- cumulant(lf,des,sd);
- }
- haspc(&lf->pc) = tmp;
- lo = lf->fp.t0;
- hi = &lo[lf->fp.nvm];
- switch(type)
- {
- case GLM1:
- return(st);
- case GLM2: /* centered scr */
- lo[v] = kap[1];
- hi[v] = sqrt(kap[2]);
- return(st);
- case GLM3: /* corrected 2 */
- lo[v] = solve_secant(q2,scb_crit,0.0,2*scb_crit,0.000001,BDF_NONE,&err);
- return(st);
- case GLM4: /* corrected 2' */
- u = fabs(p2(scb_crit));
- max_p2 = MAX(max_p2,u);
- return(st);
- case GLDN:
- get_gldn(&lf->fp,des,lo,hi,v);
- return(st);
- }
- LERR(("procvscb2: invalid type"));
- return(st);
- }
- void scb(lf,des,res)
- lfit *lf;
- design *des;
- double *res;
- { double k1, k2, *lo, *hi, sig, thhat, nlx, rss[10];
- int i, nterms;
- scb_des= des;
- npar(&lf->sp) = calcp(&lf->sp,lf->lfd.d);
- des_init(des,lf->lfd.n,npar(&lf->sp));
- type = geth(&lf->fp);
- if (type >= 80) /* simultaneous */
- {
- nterms = constants(lf,des,res);
- scb_crit = critval(0.05,res,nterms,lf->lfd.d,TWO_SIDED,0.0,GAUSS);
- type -= 10;
- }
- else /* pointwise */
- { res[0] = 1;
- scb_crit = critval(0.05,res,1,lf->lfd.d,TWO_SIDED,0.0,GAUSS);
- }
- max_p2 = 0.0;
- lf->mdl.procv = procvscb2;
- nstartlf(des,lf);
- if ((fam(&lf->sp)&64)==64)
- { i = haspc(&lf->pc); haspc(&lf->pc) = 0;
- ressumm(lf,des,rss);
- haspc(&lf->pc) = i;
- sig = sqrt(rss[3]);
- }
- else sig = 1.0;
- lo = lf->fp.t0;
- hi = &lo[lf->fp.nvm];
- for (i=0; i<lf->fp.nv; i++)
- { thhat = lf->fp.coef[i];
- nlx = lf->fp.nlx[i];
- switch(type)
- {
- case GLM1: /* basic scb */
- lo[i] = thhat - scb_crit * sig * nlx;
- hi[i] = thhat + scb_crit * sig * nlx;
- break;
- case GLM2:
- k1 = lo[i];
- k2 = hi[i];
- lo[i] = thhat - k1*nlx - scb_crit*nlx*k2;
- hi[i] = thhat - k1*nlx + scb_crit*nlx*k2;
- break;
- case GLM3:
- k1 = lo[i];
- lo[i] = thhat - k1*nlx;
- hi[i] = thhat + k1*nlx;
- case GLM4: /* corrected 2' */
- lo[i] = thhat - (scb_crit-max_p2)*lf->fp.nlx[i];
- hi[i] = thhat + (scb_crit-max_p2)*lf->fp.nlx[i];
- break;
- case GLDN:
- break;
- }
- }
- }
- void initscb(lf)
- lfit *lf;
- { initstd(lf);
- PROCV(lf) = NULL;
- KEEPC(lf) = NVAR(lf)+1+k0_reqd(NVAR(lf),NOBS(lf),0);
- PPROC(lf) = scb;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- int procvsimple(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { int lf_status;
- lf_status = procv_nov(des,lf,v);
- VVAL(lf,v,0) = des->cf[cfn(des,0)];
- return(lf_status);
- }
- void allocsimple(lf)
- lfit *lf;
- { lf->fp.coef = VVEC(lf,0);
- lf->fp.h = NULL;
- }
- void initsimple(lf)
- lfit *lf;
- {
- PROCV(lf) = procvsimple;
- ALLOC(lf) = allocsimple;
- PPROC(lf) = NULL;
- KEEPV(lf) = 1;
- KEEPC(lf) = 1;
- NOPC(lf) = 1;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- /* 3d+8 variables to keep:
- * d+1 coef+derivs.
- * d+1 sd's + derivs.
- * d+1 infl + derivs.
- * 3 likelihood and d.f's.
- * 1 bandwidth h
- * 1 degree.
- */
- void allocstd(lf)
- lfit *lf;
- { int d;
- d = NVAR(lf);
- lf->fp.coef = VVEC(lf,0);
- lf->fp.nlx = VVEC(lf,d+1);
- lf->fp.t0 = VVEC(lf,2*d+2);
- lf->fp.lik = VVEC(lf,3*d+3);
- lf->fp.h = VVEC(lf,3*d+6);
- lf->fp.deg = VVEC(lf,3*d+7);
- }
- int procvstd(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { int d, p, nvm, i, k;
- double t0[1+MXDIM], vari[1+MXDIM];
- k = procv_var(des,lf,v);
- if (lf_error) return(k);
-
- d = lf->lfd.d;
- p = npar(&lf->sp);
- nvm = lf->fp.nvm;
- if (k != LF_OK) lf_status_msg(k);
- lf->fp.lik[v] = des->llk;
- lf->fp.lik[nvm+v] = des->tr2;
- lf->fp.lik[2*nvm+v] = des->tr0 - des->tr2;
- for (i=0; i<des->ncoef; i++)
- vari[i] = des->V[p*cfn(des,0) + cfn(des,i)];
- vari[0] = sqrt(vari[0]);
- if (vari[0]>0) for (i=1; i<des->ncoef; i++) vari[i] /= vari[0];
- t0[0] = sqrt(des->f1[0]);
- if (t0[0]>0) for (i=1; i<des->ncoef; i++) t0[i] = des->f1[i]/t0[0];
- if (dc(&lf->fp)) dercor(&lf->lfd,&lf->sp,des,des->cf);
- subparcomp(des,lf,des->cf);
- for (i=0; i<des->ncoef; i++)
- lf->fp.coef[i*lf->fp.nvm+v] = des->cf[cfn(des,i)];
- subparcomp2(des,lf,vari,t0);
- for (i=0; i<des->ncoef; i++)
- { lf->fp.nlx[i*nvm+v] = vari[i];
- lf->fp.t0[i*nvm+v] = t0[i];
- }
- lf->fp.deg[v] = deg(&lf->sp);
- return(k);
- }
- void pprocstd(lf,des,res)
- lfit *lf;
- design *des;
- double *res;
- {
- ressumm(lf,des,res);
- }
- void initstd(lf)
- lfit *lf;
- { PROCV(lf) = procvstd;
- ALLOC(lf) = allocstd;
- PPROC(lf) = pprocstd;
- KEEPV(lf) = 3*NVAR(lf) + 8;
- KEEPC(lf) = 6;
- NOPC(lf) = 0;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- extern void procstd(), allocstd();
- extern double robscale;
- double vocri(lk,t0,t2,pen)
- double lk, t0, t2, pen;
- { if (pen==0) return(-2*t0*lk/((t0-t2)*(t0-t2)));
- return((-2*lk+pen*t2)/t0);
- }
- double intvo(des,lf,c0,c1,a,p,t0,t20,t21)
- design *des;
- lfit *lf;
- double *c0, *c1, a, t0, t20, t21;
- int p;
- { double th, lk, link[LLEN];
- int i, ii;
- lk = 0;
- for (i=0; i<des->n; i++)
- { ii = des->ind[i];
- th = (1-a)*innerprod(c0,d_xi(des,i),p) + a*innerprod(c1,d_xi(des,i),p);
- stdlinks(link,&lf->lfd,&lf->sp,ii,th,robscale);
- lk += wght(des,ii)*link[ZLIK];
- }
- des->llk = lk;
- return(vocri(des->llk,t0,(1-a)*t20+a*t21,pen(&lf->sp)));
- }
- int procvvord(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { double tr[6], gcv, g0, ap, coef[4][10], t2[4], th, md;
- int i, j, k, d1, i0, p1, ip;
- des->xev = evpt(&lf->fp,v);
- ap = pen(&lf->sp);
- if ((ap==0) & ((fam(&lf->sp)&63)!=TGAUS)) ap = 2.0;
- d1 = deg(&lf->sp); p1 = npar(&lf->sp);
- for (i=0; i<p1; i++) coef[0][i] = coef[1][i] = coef[2][i] = coef[3][i] = 0.0;
- i0 = 0; g0 = 0;
- ip = 1;
- for (i=deg0(&lf->sp); i<=d1; i++)
- { deg(&lf->sp) = i;
- des->p = npar(&lf->sp) = calcp(&lf->sp,lf->lfd.d);
- k = locfit(&lf->lfd,des,&lf->sp,0, i==deg0(&lf->sp),0);
- local_df(&lf->lfd,&lf->sp,des,tr);
- gcv = vocri(des->llk,tr[0],tr[2],ap);
- if ((i==deg0(&lf->sp)) || (gcv<g0)) { i0 = i; g0 = gcv; md = i; }
- for (j=0; j<des->p; j++) coef[i][j] = des->cf[j];
- t2[i] = tr[2];
- #ifdef RESEARCH
- if ((ip) && (i>deg0(&lf->sp)))
- { for (j=1; j<10; j++)
- { gcv = intvo(des,lf,coef[i-1],coef[i],j/10.0,des->p,tr[0],t2[i-1],t2[i]);
- if (gcv<g0) { g0 = gcv; md = i-1+j/10.0; }
- }
- }
- #endif
- }
- lf->fp.h[v] = des->h;
- if (lf->fp.h[v]<=0) WARN(("zero bandwidth in procvvord"));
- if (i0<d1) /* recompute the best fit */
- { deg(&lf->sp) = i0;
- des->p = npar(&lf->sp) = calcp(&lf->sp,lf->lfd.d);
- k = locfit(&lf->lfd,des,&lf->sp,0,0,0);
- for (i=npar(&lf->sp); i<p1; i++) des->cf[i] = 0.0;
- i0 = md; if (i0==d1) i0--;
- th = md-i0;
- for (i=0; i<p1; i++) des->cf[i] = (1-th)*coef[i0][i]+th*coef[i0+1][i];
- deg(&lf->sp) = d1; npar(&lf->sp) = p1;
- }
- for (i=0; i<p1; i++) lf->fp.coef[i*lf->fp.nvm+v] = des->cf[i];
- lf->fp.deg[v] = md;
- return(k);
- }
- void initvord(lf)
- lfit *lf;
- { initstd(lf);
- PROCV(lf) = procvvord;
- ALLOC(lf) = allocstd;
- PPROC(lf) = NULL;
- KEEPC(lf) = 0;
- NOPC(lf) = 1;
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * functions for computing and subtracting, adding the
- * parametric component
- */
- #include "lfev.h"
- int noparcomp(sp)
- smpar *sp;
- { int tg;
- if (ubas(sp)) return(1);
- tg = fam(sp) & 63;
- if (tg<=THAZ) return(1);
- if (tg==TROBT) return(1);
- if (tg==TCAUC) return(1);
- if (tg==TQUANT) return(1);
- return(0);
- }
- int pc_reqd(d,p)
- int d, p;
- { return(d + 2*p + jac_reqd(p));
- }
- void pcchk(pc,d,p,lc)
- paramcomp *pc;
- int d, p, lc;
- { int rw;
- double *z;
- rw = pc_reqd(d,p);
- if (pc->lwk < rw)
- { pc->wk = (double *)calloc(rw,sizeof(double));
- if ( pc->wk == NULL ) {
- printf("Problem allocating memory for pc->wk\n");fflush(stdout);
- }
- pc->lwk= rw;
- }
- z = pc->wk;
- pc->xbar = z; z += d;
- pc->coef = z; z += p;
- pc->f = z; z += p;
- z = jac_alloc(&pc->xtwx,p,z);
- pc->xtwx.p = p;
- }
- void compparcomp(des,lfd,sp,pc,nopc)
- design *des;
- lfdata *lfd;
- smpar *sp;
- paramcomp *pc;
- int nopc;
- { int i, j, k, p;
- double wt, sw;
- if (lf_debug>1) mut_printf(" compparcomp:\n");
- p = des->p;
- pcchk(pc,lfd->d,p,1);
- for (i=0; i<lfd->d; i++) pc->xbar[i] = 0.0;
- sw = 0.0;
- for (i=0; i<lfd->n; i++)
- {
- wt = prwt(lfd,i);
- sw += wt;
- for (j=0; j<lfd->d; j++)
- pc->xbar[j] += datum(lfd,j,i)*wt;
- des->ind[i] = i;
- wght(des,i) = 1.0;
- }
- for (i=0; i<lfd->d; i++) pc->xbar[i] /= sw;
- if ((nopc) || noparcomp(sp))
- { haspc(pc) = 0;
- return;
- }
- haspc(pc) = 1;
- des->xev = pc->xbar;
- k = locfit(lfd,des,sp,0,0,0);
- if (k != LF_OK) lf_status_msg(k);
- if (lf_error) return;
- switch(k)
- { case LF_NOPT: return;
- case LF_INFA: return;
- case LF_NCON: return;
- case LF_OOB: return;
- case LF_NSLN: return;
- case LF_PF:
- WARN(("compparcomp: perfect fit"));
- case LF_OK:
- case LF_DONE:
- for (i=0; i<p; i++)
- { pc->coef[i] = des->cf[i];
- pc->xtwx.dg[i] = des->xtwx.dg[i];
- pc->xtwx.wk[i] = des->xtwx.wk[i];
- }
- for (i=0; i<p*p; i++)
- { pc->xtwx.Z[i] = des->xtwx.Z[i];
- pc->xtwx.Q[i] = des->xtwx.Q[i];
- }
- pc->xtwx.sm = des->xtwx.sm;
- pc->xtwx.st = des->xtwx.st;
- return;
- default:
- LERR(("compparcomp: locfit unknown return status %d",k));
- return;
- }
- }
- void subparcomp(des,lf,coef)
- design *des;
- lfit *lf;
- double *coef;
- { int i, nd;
- deriv *dv;
- paramcomp *pc;
- pc = &lf->pc;
- if (!haspc(pc)) return;
- dv = &lf->dv; nd = dv->nd;
- fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,des->f1,dv);
- coef[0] -= innerprod(pc->coef,des->f1,pc->xtwx.p);
- if (des->ncoef == 1) return;
- dv->nd = nd+1;
- for (i=0; i<lf->lfd.d; i++)
- { dv->deriv[nd] = i;
- fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,des->f1,dv);
- coef[i+1] -= innerprod(pc->coef,des->f1,pc->xtwx.p);
- }
- dv->nd = nd;
- }
- void subparcomp2(des,lf,vr,il)
- design *des;
- lfit *lf;
- double *vr, *il;
- { double t0, t1;
- int i, nd;
- deriv *dv;
- paramcomp *pc;
- pc = &lf->pc;
- if (!haspc(pc)) return;
- dv = &lf->dv; nd = dv->nd;
- fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,des->f1,dv);
- for (i=0; i<npar(&lf->sp); i++) pc->f[i] = des->f1[i];
- jacob_solve(&pc->xtwx,des->f1);
- t0 = sqrt(innerprod(pc->f,des->f1,pc->xtwx.p));
- vr[0] -= t0;
- il[0] -= t0;
- if ((t0==0) | (des->ncoef==1)) return;
- dv->nd = nd+1;
- for (i=0; i<lf->lfd.d; i++)
- { dv->deriv[nd] = i;
- fitfun(&lf->lfd, &lf->sp, des->xev,pc->xbar,pc->f,dv);
- t1 = innerprod(pc->f,des->f1,pc->xtwx.p)/t0;
- vr[i+1] -= t1;
- il[i+1] -= t1;
- }
- dv->nd = nd;
- }
- double addparcomp(lf,x,c)
- lfit *lf;
- double *x;
- int c;
- { double y;
- paramcomp *pc;
- pc = &lf->pc;
- if (!haspc(pc)) return(0.0);
- fitfun(&lf->lfd, &lf->sp, x,pc->xbar,pc->f,&lf->dv);
- if (c==PCOEF) return(innerprod(pc->coef,pc->f,pc->xtwx.p));
- if ((c==PNLX)|(c==PT0)|(c==PVARI))
- { y = sqrt(jacob_qf(&pc->xtwx,pc->f));
- return(y);
- }
- return(0.0);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- /*
- preplot(): interpolates the fit to a new set of points.
- lf -- the fit structure.
- x -- the points to predict at.
- f -- vector to return the predictions.
- se -- vector to return std errors (NULL if not req'd)
- band-- char for conf band type. ('n'=none, 'g'=global etc.)
- n -- no of predictions (or vector of margin lengths for grid)
- where -- where to predict:
- 1 = points in the array x.
- 2 = grid defined by margins in x.
- 3 = data points from lf (ignore x).
- 4 = fit points from lf (ignore x).
- what -- what to predict.
- (PCOEF etc; see lfcons.h file)
- */
- #define NWH 8
- static char *whtyp[NWH] = { "coef", "nlx", "infl", "band",
- "degr", "like", "rdf", "vari" };
- static int whval[NWH] = { PCOEF, PNLX, PT0, PBAND, PDEGR, PLIK, PRDF, PVARI };
- int ppwhat(z)
- char *z;
- { int val;
- val = pmatch(z, whtyp, whval, NWH, -1);
- if (val==-1) LERR(("Unknown what = %s",z));
- return(val);
- }
- static char cb;
- double *sef, *fit, sigmahat;
- void predptall(lf,x,what,ev,i)
- lfit *lf;
- double *x;
- int what, ev, i;
- { double lik, rdf;
- fit[i] = dointpoint(lf,x,what,ev,i);
- if (cb=='n') return;
- sef[i] = dointpoint(lf,x,PNLX,ev,i);
- if (cb=='g')
- { sef[i] *= sigmahat;
- return;
- }
- if (cb=='l')
- { lik = dointpoint(lf,x,PLIK,ev,i);
- rdf = dointpoint(lf,x,PRDF,ev,i);
- sef[i] *= sqrt(-2*lik/rdf);
- return;
- }
- if (cb=='p')
- { sef[i] = sigmahat*sqrt(1+sef[i]*sef[i]);
- return;
- }
- }
- void predptdir(lf,des,x,what,i)
- lfit *lf;
- design *des;
- double *x;
- int what, i;
- { int needcv;
- des->xev = x;
- needcv = (what==PVARI) | (what==PNLX) | (what==PT0) | (what==PRDF);
- locfit(&lf->lfd,des,&lf->sp,0,1,needcv);
- switch(what)
- { case PCOEF: fit[i] = des->cf[0]; break;
- case PVARI: fit[i] = des->V[0]; break;
- case PNLX: fit[i] = sqrt(des->V[0]); break;
- case PT0: fit[i] = des->f1[0]; break;
- case PBAND: fit[i] = des->h; break;
- case PDEGR: fit[i] = deg(&lf->sp); break;
- case PLIK: fit[i] = des->llk; break;
- case PRDF: fit[i] = des->tr0 - des->tr2; break;
- default: LERR(("unknown what in predptdir"));
- }
- }
- void prepvector(lf,des,x,n,what,dir) /* interpolate a vector */
- lfit *lf;
- design *des;
- double **x;
- int n, what, dir;
- { int i, j;
- double xx[MXDIM];
- for (i=0; i<n; i++)
- { for (j=0; j<lf->fp.d; j++) xx[j] = x[j][i];
- if (dir)
- predptdir(lf,des,xx,what,i);
- else
- predptall(lf,xx,what,ev(&lf->evs),i);
- if (lf_error) return;
- }
- }
- void prepfitp(lf,what)
- lfit *lf;
- int what;
- { int i;
- for (i=0; i<lf->fp.nv; i++)
- { predptall(lf,evpt(&lf->fp,i),what,EFITP,i);
- if (lf_error) return;
- }
- }
- void prepgrid(lf,des,x,mg,n,what,dir) /* interpolate a grid given margins */
- lfit *lf;
- design *des;
- double **x;
- int *mg, dir, n, what;
- { int i, ii, j, d;
- double xv[MXDIM];
- d = lf->fp.d;
- for (i=0; i<n; i++)
- { ii = i;
- for (j=0; j<d; j++)
- { xv[j] = x[j][ii%mg[j]];
- ii /= mg[j];
- }
- if (dir)
- predptdir(lf,des,xv,what,i);
- else
- predptall(lf,xv,what,ev(&lf->evs),i);
- if (lf_error) return;
- }
- }
- void preplot(lf,x,f,se,band,mg,where,what,dir)
- lfit *lf;
- double **x, *f, *se;
- int *mg, where, what, dir;
- char band;
- { int d, i, n;
- double *xx[MXDIM];
- design ppdes;
- d = lf->fp.d;
- fit = f;
- sef = se;
- cb = band;
- if (cb!='n') sigmahat = sqrt(rv(&lf->fp));
- if (dir) des_init(&ppdes,lf->lfd.n,npar(&lf->sp));
- switch(where)
- { case 1: /* vector */
- n = mg[0];
- prepvector(lf,&ppdes,x,n,what,dir);
- break;
- case 2: /* grid */
- n = 1;
- for (i=0; i<d; i++) n *= mg[i];
- prepgrid(lf,&ppdes,x,mg,n,what,dir);
- break;
- case 3: /* data */
- n = lf->lfd.n;
- if ((ev(&lf->evs)==EDATA) | (ev(&lf->evs)==ECROS))
- { prepfitp(lf,what);
- dir = 0;
- }
- else
- { for (i=0; i<d; i++) xx[i] = dvari(&lf->lfd,i);
- prepvector(lf,&ppdes,xx,n,what,dir);
- }
- break;
- case 4: /* fit points */
- n = lf->fp.nv; dir = 0;
- prepfitp(lf,what);
- break;
- default:
- LERR(("unknown where in preplot"));
- }
- if ((!dir) && ((what==PT0)|(what==PVARI)))
- for (i=0; i<n; i++) f[i] = f[i]*f[i];
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- #include "lfev.h"
- int procv_nov(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { int lf_status;
- if (lf_debug>1) mut_printf(" procveraw: %d\n",v);
- des->xev = evpt(&lf->fp,v);
- if (acri(&lf->sp)==ANONE)
- lf_status = locfit(&lf->lfd,des,&lf->sp,0,1,0);
- else
- lf_status = alocfit(&lf->lfd,&lf->sp,&lf->dv,des,0);
- if (lf->fp.h != NULL) lf->fp.h[v] = des->h;
- return(lf_status);
- }
- int procv_var(des,lf,v)
- design *des;
- lfit *lf;
- int v;
- { int i, lf_status;
- if (lf_debug>1) mut_printf(" procvraw: %d\n",v);
- des->xev = evpt(&lf->fp,v);
- if (acri(&lf->sp)==ANONE)
- lf_status = locfit(&lf->lfd,des,&lf->sp,0,1,1);
- else
- lf_status = alocfit(&lf->lfd,&lf->sp,&lf->dv,des,1);
- if (lf->fp.h != NULL) lf->fp.h[v] = des->h;
- return(lf_status);
- }
- /*
- * Copyright 1996-2006 Catherine Loader.
- */
- /*
- * startmodule(lf,des,mod,dir) -- the standard entry point.
- * des and lf are pointers to the design and fit structures.
- * mod - module name. Set to NULL if the module is already
- * initialized.
- * dir - for dynamic modules, the directory.
- *
- * initmodule(mdl,mod,dir,lf)
- * direct call for module initialization.
- *
- */
- #include "lfev.h"
- #ifdef WINDOWS
- #define DIRSEP '\\'
- #define PATHSEP ';'
- #else
- #define DIRSEP '/'
- #define PATHSEP ':'
- #endif
- #ifdef ALLOW_MODULES
- #ifdef WINDOWS
- #include <windows.h>
- #define DLEXT "dll"
- #define DLOPEN(x) LoadLibrary(x)
- #define DLSYM GetProcAddress
- #else
- #include <dlfcn.h>
- #define DLEXT "so"
- #define DLOPEN(x) dlopen(x,RTLD_LAZY)
- #define DLSYM dlsym
- #endif
- #endif
- static double fpkap[6];
- void fitpt_init(fp)
- fitpt *fp;
- {
- dc(fp) = 0;
- geth(fp) = GSTD;
- fp->nv = fp->nvm = 0;
- if (fp->kap==NULL) fp->kap = fpkap;
- }
- void lfit_init(lf)
- lfit *lf;
- {
- lfdata_init(&lf->lfd);
- evstruc_init(&lf->evs);
- smpar_init(&lf->sp,&lf->lfd);
- deriv_init(&lf->dv);
- fitpt_init(&lf->fp);
- lf->mdl.np = 0;
- }
- void fitdefault(lf)
- lfit *lf;
- { WARN(("fitdefault deprecated -- use lfit_init()"));
- lfit_init(lf);
- }
- void set_flim(lfd,evs)
- lfdata *lfd;
- evstruc *evs;
- { int i, j, d, n;
- double z, mx, mn, *bx;
- if (ev(evs)==ESPHR) return;
- d = lfd->d; n = lfd->n;
- bx = evs->fl;
- for (i=0; i<d; i++)
- if (bx[i]==bx[i+d])
- { if (lfd->sty[i]==STANGL)
- { bx[i] = 0.0; bx[i+d] = 2*PI*lfd->sca[i];
- }
- else
- { mx = mn = datum(lfd,i,0);
- for (j=1; j<n; j++)
- { mx = MAX(mx,datum(lfd,i,j));
- mn = MIN(mn,datum(lfd,i,j));
- }
- if (lfd->xl[i]<lfd->xl[i+d]) /* user set xlim; maybe use them. */
- { z = mx-mn;
- if (mn-0.2*z < lfd->xl[i]) mn = lfd->xl[i];
- if (mx+0.2*z > lfd->xl[i+d]) mx = lfd->xl[i+d];
- }
- bx[i] = mn;
- bx[i+d] = mx;
- }
- }
- }
- double vvari(v,n)
- double *v;
- int n;
- { int i;
- double xb, s2;
- xb = s2 = 0.0;
- for (i=0; i<n; i++) xb += v[i];
- xb /= n;
- for (i=0; i<n; i++) s2 += SQR(v[i]-xb);
- return(s2/(n-1));
- }
- void set_scales(lfd)
- lfdata *lfd;
- { int i;
- for (i=0; i<lfd->d; i++)
- if (lfd->sca[i]<=0) /* set automatic scales */
- { if (lfd->sty[i]==STANGL)
- lfd->sca[i] = 1.0;
- else lfd->sca[i] = sqrt(vvari(lfd->x[i],lfd->n));
- }
- }
- void nstartlf(des,lf)
- design *des;
- lfit *lf;
- { int i, d, n;
- if (lf_debug>0) mut_printf("nstartlf\n");
- n = lf->lfd.n;
- d = lf->lfd.d;
- npar(&lf->sp) = calcp(&lf->sp,d);
- des_init(des,n,npar(&lf->sp));
- set_scales(&lf->lfd);
- set_flim(&lf->lfd,&lf->evs);
- compparcomp(des,&lf->lfd,&lf->sp,&lf->pc,lf->mdl.nopc);
- if (lf_error) return;
- makecfn(&lf->sp,des,&lf->dv,lf->lfd.d);
- lf->lfd.ord = 0;
- if ((d==1) && (lf->lfd.sty[0]!=STANGL))
- { i = 1;
- while ((i<n) && (datum(&lf->lfd,0,i)>=datum(&lf->lfd,0,i-1))) i++;
- lf->lfd.ord = (i==n);
- }
- for (i=0; i<npar(&lf->sp); i++) des->fix[i] = 0;
- lf->fp.d = lf->lfd.d;
- lf->fp.hasd = (des->ncoef==(1+lf->fp.d));
- lf->fp.nv = lf->evs.nce = 0;
- if (lf_debug>1) mut_printf("call eval structure %d\n",ev(&lf->evs));
- switch(ev(&lf->evs))
- { case EPHULL: triang_start(des,lf); break;
- case EDATA: dataf(des,lf); break;
- case ECROS: crossf(des,lf); break;
- case EGRID: gridf(des,lf); break;
- case ETREE: atree_start(des,lf); break;
- case EKDCE: kt(&lf->sp) = KCE;
- case EKDTR: kdtre_start(des,lf); break;
- case EPRES: preset(des,lf); break;
- case EXBAR: xbarf(des,lf); break;
- case ENONE: return;
- case ESPHR: sphere_start(des,lf); break;
- case ESPEC: lf->evs.espec(des,lf); break;
- default: LERR(("startlf: Invalid evaluation structure %d",ev(&lf->evs)));
- }
- /* renormalize for family=density */
- if ((de_renorm) && (fam(&lf->sp)==TDEN)) dens_renorm(lf,des);
- }
- /*
- * getnextdir() gets the next dir from a string dirpath="dir1:dir2:dir3:..."
- * (;-separated on windows).
- * The directory is returned through dirnext, and the function returns
- * a pointer to the next string.
- * typical usage is recursive, dirpath = getnextdir(dirpath,dirnext).
- * with the above example, this sets dirnext="dir1" and dirpath="dir2:dir3:...".
- * if the input dirpath has no :, then it is copied to dirnext, and return is "".
- * if input dirpath is "", dirnext is set to "", and null pointer returned.
- */
- char *getnextdir(dirpath,dirnext)
- char *dirpath, *dirnext;
- { char *z;
- if (strlen(dirpath)==0)
- { sprintf(dirnext,"");
- return(NULL);
- }
- z = strchr(dirpath,PATHSEP);
- if (z==NULL)
- { sprintf(dirnext,"%s%c",dirpath,DIRSEP);
- return(&dirpath[strlen(dirnext)]);
- }
- *z = '\0';
- sprintf(dirnext,"%s%c",dirpath,DIRSEP);
- return(++z);
- }
- int initmodule(mdl, mod, dir, lf)
- module *mdl;
- lfit *lf;
- char *mod, *dir;
- { int n, d, p;
- #ifdef ALLOW_MODULES
- #ifdef WINDOWS
- HINSTANCE res;
- typedef void (CALLBACK* DLLFN)();
- DLLFN init;
- #else
- void *res;
- void (*init)();
- #endif
- char distname[500];
- #endif
- n = lf->lfd.n;
- d = lf->lfd.d;
- p = npar(&lf->sp) = calcp(&lf->sp,d);
- mdl->isset = 1;
- PPROC(lf) = NULL;
- if (strcmp(mod,"std")==0) { initstd(lf); return(1); }
- if (strcmp(mod,"simple")==0) { initsimple(lf); return(1); }
- if (strcmp(mod,"allcf")==0) { initallcf(lf); return(1); }
- if (strcmp(mod,"hatm")==0) { inithatm(lf); return(1); }
- if (strcmp(mod,"kappa")==0) { initkappa(lf); return(1); }
- if (strcmp(mod,"lscv")==0) { initlscv(lf); return(1); }
- if (strcmp(mod,"gamf")==0) { initgam(lf); return(1); }
- if (strcmp(mod,"gamp")==0) { initgam(lf); return(1); }
- if (strcmp(mod,"rband")==0) { initrband(lf); return(1); }
- if (strcmp(mod,"scb")==0) { initscb(lf); return(1); }
- if (strcmp(mod,"vord")==0) { initvord(lf); return(1); }
- #ifdef ALLOW_MODULES
- while (dir != NULL)
- {
- dir = getnextdir(dir,distname);
- sprintf(&distname[strlen(distname)],"mod%s.%s",mod,DLEXT);
- res = DLOPEN(distname);
- if (res==NULL)
- {
- #ifdef WINDOWS
- mut_printf("LoadLibrary failed: %s, %d\n",distname,GetLastError());
- #else
- mut_printf("dlopen failed: %s\n",dlerror());
- #endif
- }
- else
- {
- #ifdef WINDOWS
- mut_printf("LoadLibrary success: %s\n",distname);
- #else
- mut_printf("dlopen success: %s\n",distname);
- #endif
- sprintf(distname,"init%s",mod);
- init = (void *)DLSYM(res,distname);
- if (init==NULL)
- { mut_printf("I can't find %s() function.\n",distname);
- mdl->isset = 0;
- return(0);
- }
- init(lf);
- return(1);
- }
- }
- #endif
- mdl->isset = 0;
- return(0);
- }
- /*
- * startmodule is the entry point to launch the fit.
- * if mod is provided, will first initialize the module.
- * if mod==NULL, assumes the module has been initialized separately.
- */
- void startmodule(lf,des,mod,dir)
- lfit *lf;
- design *des;
- char *mod, *dir;
- { int z;
- if (mod != NULL)
- { z = initmodule(&lf->mdl,mod,dir,lf);
- if (!z) return;
- }
- lf->fp.nv = lf->evs.nce = 0;
- if (lf_error) return;
- if (PROCV(lf) != NULL) nstartlf(des,lf);
- if (lf_error) return;
- if (PPROC(lf) != NULL) PPROC(lf)(lf,des,lf->fp.kap);
- }
- /* for compatability, more or less. */
- void startlf(des,lf,vfun,nopc)
- design *des;
- lfit *lf;
- int (*vfun)(), nopc;
- { int z;
- z = initmodule(&lf->mdl,"std",NULL,lf);
- if (!z) return;
- lf->mdl.procv = vfun;
- lf->mdl.nopc = nopc;
- nstartlf(des,lf);
- }
|